aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-08-17 07:23:57 +0000
committerJohn McCall <rjmccall@apple.com>2010-08-17 07:23:57 +0000
commit572fc62b52b5b113cbaf528bd3ec00fcde19a46e (patch)
treee1a3be080486783193f960a14812154945af8f3a
parent727d93ef49e18147149354fadd10e86b13bc4ab0 (diff)
Don't try to initialize a reference with a constructed temporary if either
of the classes is invalid. A class is invalid if a base is invalid. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111227 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp7
-rw-r--r--lib/Sema/SemaInit.cpp5
-rw-r--r--test/SemaCXX/constructor-initializer.cpp14
3 files changed, 25 insertions, 1 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1d0b4a9450..3f59fb71d0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -483,8 +483,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// defined class.
if (RequireCompleteType(BaseLoc, BaseType,
PDiag(diag::err_incomplete_base_class)
- << SpecifierRange))
+ << SpecifierRange)) {
+ Class->setInvalidDecl();
return 0;
+ }
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
@@ -503,6 +505,9 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
}
SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
+
+ if (BaseDecl->isInvalidDecl())
+ Class->setInvalidDecl();
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index e1fcab0c40..13ba8ee5f9 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2306,6 +2306,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
Con != ConEnd; ++Con) {
@@ -2333,6 +2334,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
}
}
}
+ if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
const RecordType *T2RecordType = 0;
if ((T2RecordType = T2->getAs<RecordType>()) &&
@@ -2380,6 +2383,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
}
}
}
+ if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
SourceLocation DeclLoc = Initializer->getLocStart();
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index cf309f5597..31d53302bf 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -221,3 +221,17 @@ namespace PR7402 {
S s(3);
}
}
+
+// <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 3 {{candidate}} expected-note {{passing argument}}
+ 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 {{no viable conversion}} expected-error {{does not name}}
+ }
+ };
+}