зеркало из https://github.com/microsoft/clang-1.git
<rdar://problem/13267210> Ensure that Sema::CompareReferenceRelationship returns consistent results with invalid types.
When Sema::RequireCompleteType() is given a class template specialization type that then fails to instantiate, it returns 'true'. On subsequent invocations, it can return false. Make sure that this difference doesn't change the result of Sema::CompareReferenceRelationship, which is expected to remain stable while we're checking an initialization sequence. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178088 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
7020346e41
Коммит
0162c1ce29
|
@ -1311,29 +1311,25 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
|
|||
(CXXBaseSpecifier**)(Bases), NumBases);
|
||||
}
|
||||
|
||||
static CXXRecordDecl *GetClassForType(QualType T) {
|
||||
if (const RecordType *RT = T->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl());
|
||||
else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>())
|
||||
return ICT->getDecl();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the type \p Derived is a C++ class that is
|
||||
/// derived from the type \p Base.
|
||||
bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
|
||||
if (!getLangOpts().CPlusPlus)
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *DerivedRD = GetClassForType(Derived);
|
||||
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
|
||||
if (!DerivedRD)
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *BaseRD = GetClassForType(Base);
|
||||
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
|
||||
if (!BaseRD)
|
||||
return false;
|
||||
|
||||
|
||||
// If either the base or the derived type is invalid, don't try to
|
||||
// check whether one is derived from the other.
|
||||
if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
|
||||
return false;
|
||||
|
||||
// FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
|
||||
return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
|
||||
}
|
||||
|
@ -1344,11 +1340,11 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
|
|||
if (!getLangOpts().CPlusPlus)
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *DerivedRD = GetClassForType(Derived);
|
||||
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
|
||||
if (!DerivedRD)
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *BaseRD = GetClassForType(Base);
|
||||
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
|
||||
if (!BaseRD)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -3937,6 +3937,15 @@ CompareDerivedToBaseConversions(Sema &S,
|
|||
return ImplicitConversionSequence::Indistinguishable;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given type is valid, e.g., it is not an invalid
|
||||
/// C++ class.
|
||||
static bool isTypeValid(QualType T) {
|
||||
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
|
||||
return !Record->isInvalidDecl();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// CompareReferenceRelationship - Compare the two types T1 and T2 to
|
||||
/// determine whether they are reference-related,
|
||||
/// reference-compatible, reference-compatible with added
|
||||
|
@ -3970,7 +3979,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
|
|||
if (UnqualT1 == UnqualT2) {
|
||||
// Nothing to do.
|
||||
} else if (!RequireCompleteType(Loc, OrigT2, 0) &&
|
||||
IsDerivedFrom(UnqualT2, UnqualT1))
|
||||
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
|
||||
IsDerivedFrom(UnqualT2, UnqualT1))
|
||||
DerivedToBase = true;
|
||||
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
|
||||
UnqualT2->isObjCObjectOrInterfaceType() &&
|
||||
|
|
|
@ -232,13 +232,15 @@ namespace PR7402 {
|
|||
// <rdar://problem/8308215>: don't crash.
|
||||
// Lots of questionable recovery here; errors can change.
|
||||
namespace test3 {
|
||||
class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 2 {{candidate}}
|
||||
class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 4 {{candidate}}
|
||||
class B : public A {
|
||||
public:
|
||||
B(const String& s, int e=0) // expected-error {{unknown type name}}
|
||||
: A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}}
|
||||
B(const B& e)
|
||||
: A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{does not name}} expected-error {{no member named 'm_String' in 'test3::B'}}
|
||||
: A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{does not name}} \
|
||||
// expected-error {{no member named 'm_String' in 'test3::B'}} \
|
||||
// expected-error {{no matching}}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,3 +10,21 @@ void test() {
|
|||
Foo2(vector2<int*>()); // expected-error{{no matching function for call to 'Foo2'}}
|
||||
Foo(vector<int*>()); // expected-error{{no matching function for call to 'Foo'}}
|
||||
}
|
||||
|
||||
namespace rdar13267210 {
|
||||
template < typename T > class A {
|
||||
BaseTy; // expected-error{{C++ requires a type specifier for all declarations}}
|
||||
};
|
||||
|
||||
template < typename T, int N > class C: A < T > {};
|
||||
|
||||
class B {
|
||||
C<long, 16> ExternalDefinitions;
|
||||
C<long, 64> &Record;
|
||||
|
||||
void AddSourceLocation(A<long> &R); // expected-note{{passing argument to parameter 'R' here}}
|
||||
void AddTemplateKWAndArgsInfo() {
|
||||
AddSourceLocation(Record); // expected-error{{non-const lvalue reference to type}}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче