]> granicus.if.org Git - clang/commitdiff
If we find a deallocation function in the class scope, but it is a placement function...
authorAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 16:43:15 +0000 (16:43 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 16:43:15 +0000 (16:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88851 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/new-delete.cpp

index 2cc29caa0173b40c61af696cbded0265315b682f..e3f23837986cef4cfb56c4df7953fb7551f7cd0f 100644 (file)
@@ -1739,6 +1739,10 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
                                          "expression of type %0 to a pointer">;
 def warn_delete_incomplete : Warning<
   "deleting pointer to incomplete type %0 may cause undefined behaviour">;
+def err_no_suitable_delete_member_function_found : Error<
+  "no suitable member %0 in %1">;
+def note_delete_member_function_declared_here : Note<
+  "%0 declared here">;
 def err_decrement_bool : Error<"cannot decrement expression of type bool">;
 def warn_increment_bool : Warning<
   "incrementing expression of type bool is deprecated">;
index 3e07f3495ee7d2e380ab7f9f8726230ec4c908e0..f5ce44e106330c79154b08eb0ee2fa192321e723 100644 (file)
@@ -844,12 +844,12 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
     DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
                                       ArrayForm ? OO_Array_Delete : OO_Delete);
 
+    LookupResult Found;
     if (Pointee->isRecordType() && !UseGlobal) {
       CXXRecordDecl *Record
         = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl());
       
       // Try to find operator delete/operator delete[] in class scope.
-      LookupResult Found;
       LookupQualifiedName(Found, Record, DeleteName, LookupOrdinaryName);
       
       if (Found.isAmbiguous()) {
@@ -867,6 +867,21 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
           }
       }
       
+      if (!OperatorDelete && !Found.empty()) {
+        // We did find operator delete/operator delete[] declarations, but
+        // none of them were suitable.
+        Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+        << DeleteName << Record;
+        
+        for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+             F != FEnd; ++F) {
+          Diag((*F)->getLocation(), 
+               diag::note_delete_member_function_declared_here)
+          << DeleteName;
+        }
+        return ExprError();
+      }
+      
       if (!Record->hasTrivialDestructor())
         if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context))
           MarkDeclarationReferenced(StartLoc,
index 63a716338ba349637094836e1f279f697b74ba36..417ca8ff9ef7bd7556eda1bf9afafed4cdd08f04 100644 (file)
@@ -178,7 +178,15 @@ public:
 class X8 : public X6, public X7 {
 };
 
-void f(X8x8) {
+void f(X8 *x8) {
   delete x8; // expected-error {{member 'operator delete' found in multiple base classes of different types}}
 }
 
+class X9 {
+  static void operator delete(void*, int); // expected-note {{'operator delete' declared here}}
+  static void operator delete(void*, float); // expected-note {{'operator delete' declared here}}
+};
+
+void f(X9 *x9) {
+  delete x9; // expected-error {{no suitable member 'operator delete' in 'X9'}}
+}