aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-11-15 16:43:15 +0000
committerAnders Carlsson <andersca@mac.com>2009-11-15 16:43:15 +0000
commit50724302e24d44a27e3bc45e7185a710d6eb3c2d (patch)
treed2b649dbc11eebe172d0937226db6593f52526aa
parent84423a8c8450a1f3ce82730fb35d5ee4e7980701 (diff)
If we find a deallocation function in the class scope, but it is a placement function we should not look for a deallocation function in the global scope.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88851 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaExprCXX.cpp17
-rw-r--r--test/SemaCXX/new-delete.cpp10
3 files changed, 29 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 2cc29caa01..e3f2383798 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3e07f3495e..f5ce44e106 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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,
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 63a716338b..417ca8ff9e 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -178,7 +178,15 @@ public:
class X8 : public X6, public X7 {
};
-void f(X8* x8) {
+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'}}
+}