// 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();
}
SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
+
+ if (BaseDecl->isInvalidDecl())
+ Class->setInvalidDecl();
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
// 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) {
}
}
}
+ if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
const RecordType *T2RecordType = 0;
if ((T2RecordType = T2->getAs<RecordType>()) &&
}
}
}
+ if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
SourceLocation DeclLoc = Initializer->getLocStart();
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}}
+ }
+ };
+}