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.

llvm-svn: 111227
This commit is contained in:
John McCall 2010-08-17 07:23:57 +00:00
parent 411dfad981
commit 3696dcb171
3 changed files with 25 additions and 1 deletions

View File

@ -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,

View File

@ -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();

View File

@ -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}}
}
};
}