aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-09-14 21:34:24 +0000
committerJohn McCall <rjmccall@apple.com>2010-09-14 21:34:24 +0000
commitedeb6c9b47e802da1a9a149ea1ea4f1ddd7f6182 (patch)
tree13359252839bb741fd717c36b5c21c25842c2207
parent7d8647f194ae4f2499e5bcd40dcfea34cd21ebc6 (diff)
The paired 'operator delete' for a placement 'operator new' is always a
placement 'operator delete', even if there are no placement args (i.e. overload resolution selected an operator new with default arguments). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113861 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExprCXX.cpp9
-rw-r--r--test/SemaCXX/new-delete.cpp18
2 files changed, 26 insertions, 1 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index e03c5721c6..6d8c914654 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1046,7 +1046,14 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
llvm::SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;
- if (NumPlaceArgs > 0) {
+ // Whether we're looking for a placement operator delete is dictated
+ // by whether we selected a placement operator new, not by whether
+ // we had explicit placement arguments. This matters for things like
+ // struct A { void *operator new(size_t, int = 0); ... };
+ // A *a = new A()
+ bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1);
+
+ if (isPlacementNew) {
// C++ [expr.new]p20:
// A declaration of a placement deallocation function matches the
// declaration of a placement allocation function if it has the
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index ef20aee009..f6129d1984 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -354,3 +354,21 @@ namespace DeleteParam {
void operator delete(void* const);
};
}
+
+// <rdar://problem/8427878>
+// Test that the correct 'operator delete' is selected to pair with
+// the unexpected placement 'operator new'.
+namespace PairedDelete {
+ template <class T> struct A {
+ A();
+ void *operator new(size_t s, double d = 0);
+ void operator delete(void *p, double d);
+ void operator delete(void *p) {
+ T::dealloc(p);
+ }
+ };
+
+ A<int> *test() {
+ return new A<int>();
+ }
+}