From: John McCall Date: Wed, 4 Aug 2010 01:04:25 +0000 (+0000) Subject: Only look up an 'operator delete' on the definition of a destructor, not on X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15442825bb2c3f2cc48f3ed753d172beb8ed1232;p=clang Only look up an 'operator delete' on the definition of a destructor, not on a declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110175 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5252188635..e166e9cc2d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3731,12 +3731,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, AddOverriddenMethods(Method->getParent(), Method); } - // Additional checks for the destructor; make sure we do this after we - // figure out whether the destructor is virtual. - if (CXXDestructorDecl *Destructor = dyn_cast(NewFD)) - if (!Destructor->getParent()->isDependentType()) - CheckDestructor(Destructor); - // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) @@ -4793,9 +4787,13 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, !hasAnyErrorsInThisFunction()) DiagnoseInvalidJumps(Body); - if (CXXDestructorDecl *Destructor = dyn_cast(dcl)) + if (CXXDestructorDecl *Destructor = dyn_cast(dcl)) { + if (!Destructor->getParent()->isDependentType()) + CheckDestructor(Destructor); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), Destructor->getParent()); + } // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 5677b5c993..204949d11e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2877,8 +2877,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { ClassDecl->addedConstructor(Context, Constructor); } -/// CheckDestructor - Checks a fully-formed destructor for well-formedness, -/// issuing any diagnostics required. Returns true on error. +/// CheckDestructor - Checks a fully-formed destructor definition for +/// well-formedness, issuing any diagnostics required. Returns true +/// on error. bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); diff --git a/test/CXX/special/class.dtor/p9.cpp b/test/CXX/special/class.dtor/p9.cpp index 80acc2499d..13243f510f 100644 --- a/test/CXX/special/class.dtor/p9.cpp +++ b/test/CXX/special/class.dtor/p9.cpp @@ -43,6 +43,30 @@ namespace test1 { using A::operator delete; using B::operator delete; - ~C(); // expected-error {{multiple suitable 'operator delete' functions in 'C'}} + ~C(); + }; + + C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}} +} + +// ...at the point of definition of a virtual destructor... +namespace test2 { + struct A { + virtual ~A(); + static void operator delete(void*, const int &); + }; + + struct B { + virtual ~B(); + static void operator delete(void*, const int &); // expected-note {{declared here}} + }; + B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}} + + struct CBase { virtual ~CBase(); }; + struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}} + static void operator delete(void*, const int &); // expected-note {{declared here}} }; + void test() { + C c; // expected-note {{first required here}} + } } diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 4f6c76bc90..1502f73471 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -103,5 +103,5 @@ namespace test6 { }; class B : A { B(); }; - B::B() {} + B::B() {} // expected-note {{in instantiation of member function 'test6::A::~A' requested here}} }