When we're trying to define an implicit virtual destructor, make sure that we have a valid delete operator.

llvm-svn: 90156
This commit is contained in:
Anders Carlsson 2009-11-30 21:24:50 +00:00
parent 5b2f5cadbd
commit 26a807d37a
4 changed files with 38 additions and 10 deletions

View File

@ -443,8 +443,9 @@ def err_implicit_object_parameter_init : Error<
def note_field_decl : Note<"member is declared here">;
def note_previous_class_decl : Note<
"%0 declared here">;
def note_ctor_synthesized_at : Note<
"implicit default constructor for %0 first required here">;
def note_member_synthesized_at : Note<
"implicit default %select{constructor|copy constructor|"
"copy assignment operator|destructor}0 for %1 first required here">;
def err_missing_default_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{base class|member}2 %3 which does not have a default "

View File

@ -2135,7 +2135,7 @@ public:
void CheckConstructor(CXXConstructorDecl *Constructor);
QualType CheckDestructorDeclarator(Declarator &D,
FunctionDecl::StorageClass& SC);
void CheckDestructor(CXXDestructorDecl *Destructor);
bool CheckDestructor(CXXDestructorDecl *Destructor);
void CheckConversionDeclarator(Declarator &D, QualType &R,
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);

View File

@ -2367,9 +2367,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
ClassDecl->addedConstructor(Context, Constructor);
}
/// CheckDestructor - Checks a fully-formed destructor for
/// well-formedness, issuing any diagnostics required.
void Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
/// CheckDestructor - Checks a fully-formed destructor for well-formedness,
/// issuing any diagnostics required. Returns true on error.
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
if (Destructor->isVirtual()) {
@ -2384,9 +2384,13 @@ void Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
FunctionDecl *OperatorDelete = 0;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
Destructor->setOperatorDelete(OperatorDelete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
return true;
Destructor->setOperatorDelete(OperatorDelete);
}
return false;
}
static inline bool
@ -3071,8 +3075,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) {
Diag(CurrentLocation, diag::note_ctor_synthesized_at)
<< Context.getTagDeclType(ClassDecl);
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
Constructor->setInvalidDecl();
} else {
Constructor->setUsed();
@ -3124,6 +3128,17 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
}
}
}
// FIXME: If CheckDestructor fails, we should emit a note about where the
// implicit destructor was needed.
if (CheckDestructor(Destructor)) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDestructor << Context.getTagDeclType(ClassDecl);
Destructor->setInvalidDecl();
return;
}
Destructor->setUsed();
}

View File

@ -190,3 +190,15 @@ class X9 {
void f(X9 *x9) {
delete x9; // expected-error {{no suitable member 'operator delete' in 'X9'}}
}
struct X10 {
virtual ~X10();
};
struct X11 : X10 { // expected-error {{no suitable member 'operator delete' in 'X11'}}
void operator delete(void*, int); // expected-note {{'operator delete' declared here}}
};
void f() {
X11 x11; // expected-note {{implicit default destructor for 'struct X11' first required here}}
}