r178088 - <rdar://problem/13267210> Ensure that Sema::CompareReferenceRelationship returns consistent results with invalid types.
Douglas Gregor
dgregor at apple.com
Tue Mar 26 16:36:31 PDT 2013
Author: dgregor
Date: Tue Mar 26 18:36:30 2013
New Revision: 178088
URL: http://llvm.org/viewvc/llvm-project?rev=178088&view=rev
Log:
<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.
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/constructor-initializer.cpp
cfe/trunk/test/SemaTemplate/derived.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=178088&r1=178087&r2=178088&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 26 18:36:30 2013
@@ -1311,29 +1311,25 @@ void Sema::ActOnBaseSpecifiers(Decl *Cla
(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 Derive
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;
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=178088&r1=178087&r2=178088&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Mar 26 18:36:30 2013
@@ -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(Sourc
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() &&
Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=178088&r1=178087&r2=178088&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Tue Mar 26 18:36:30 2013
@@ -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}}
}
};
}
Modified: cfe/trunk/test/SemaTemplate/derived.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/derived.cpp?rev=178088&r1=178087&r2=178088&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/derived.cpp (original)
+++ cfe/trunk/test/SemaTemplate/derived.cpp Tue Mar 26 18:36:30 2013
@@ -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}}
+ }
+ };
+}
More information about the cfe-commits
mailing list