aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-03-26 23:36:30 +0000
committerDouglas Gregor <dgregor@apple.com>2013-03-26 23:36:30 +0000
commit0162c1ce296fc48fbe03a31a2ae00b939eef86a8 (patch)
treeb2b56e876043541f2a0dbc228e506a8c89c4e82a
parent7020346e4137375d41fc4ac70bfda06e2c724444 (diff)
<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
-rw-r--r--lib/Sema/SemaDeclCXX.cpp24
-rw-r--r--lib/Sema/SemaOverload.cpp12
-rw-r--r--test/SemaCXX/constructor-initializer.cpp6
-rw-r--r--test/SemaTemplate/derived.cpp18
4 files changed, 43 insertions, 17 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index cc0aadeec2..1da1884752 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 3ed0465794..5d931cfcaf 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -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() &&
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index c54956db41..17576328c1 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -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}}
}
};
}
diff --git a/test/SemaTemplate/derived.cpp b/test/SemaTemplate/derived.cpp
index 1fb9401c94..7b91f9a3ed 100644
--- a/test/SemaTemplate/derived.cpp
+++ b/test/SemaTemplate/derived.cpp
@@ -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}}
+ }
+ };
+}