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 5252188..e166e9c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3731,12 +3731,6 @@
         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<CXXDestructorDecl>(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 @@
         !hasAnyErrorsInThisFunction())
       DiagnoseInvalidJumps(Body);
 
-    if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
+    if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(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 5677b5c..204949d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2877,8 +2877,9 @@
     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 80acc24..13243f5 100644
--- a/test/CXX/special/class.dtor/p9.cpp
+++ b/test/CXX/special/class.dtor/p9.cpp
@@ -43,6 +43,30 @@
     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 4f6c76b..1502f73 100644
--- a/test/SemaCXX/destructor.cpp
+++ b/test/SemaCXX/destructor.cpp
@@ -103,5 +103,5 @@
   };
 
   class B : A<int> { B(); };
-  B::B() {}
+  B::B() {} // expected-note {{in instantiation of member function 'test6::A<int>::~A' requested here}}
 }