]> granicus.if.org Git - clang/commitdiff
P0722R2: The first parameter in an implicit call to a destroying operator
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 5 Dec 2017 23:54:25 +0000 (23:54 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 5 Dec 2017 23:54:25 +0000 (23:54 +0000)
delete should be a cv-unqualified pointer to the deleted object.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319858 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/cxx2a-destroying-delete.cpp

index 56b14ddd7fe2dc2c821b1cb2a5ca6ec64479854b..e4634d96d1d3d50cb352542384779894f2495397 100644 (file)
@@ -3293,6 +3293,15 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
     // is trivial and left to AST consumers to handle.
     QualType ParamType = OperatorDelete->getParamDecl(0)->getType();
     if (!IsVirtualDelete && !ParamType->getPointeeType()->isVoidType()) {
+      Qualifiers Qs = Pointee.getQualifiers();
+      if (Qs.hasCVRQualifiers()) {
+        // Qualifiers are irrelevant to this conversion; we're only looking
+        // for access and ambiguity.
+        Qs.removeCVRQualifiers();
+        QualType Unqual = Context.getPointerType(
+            Context.getQualifiedType(Pointee.getUnqualifiedType(), Qs));
+        Ex = ImpCastExprToType(Ex.get(), Unqual, CK_NoOp);
+      }
       Ex = PerformImplicitConversion(Ex.get(), ParamType, AA_Passing);
       if (Ex.isInvalid())
         return ExprError();
index a085c11c26f57a0bf25fb509a36ed73317fa650d..6115774e3836dfc5ff4ad8ee82e23d0a85e8977b 100644 (file)
@@ -101,3 +101,22 @@ namespace delete_selection {
   };
   void delete_I(I *i) { delete i; } // expected-error {{deleted}}
 }
+
+namespace first_param_conversion {
+  struct A {
+    void operator delete(A *, std::destroying_delete_t);
+  };
+  void f(const volatile A *a) {
+    delete a; // ok
+  }
+
+  struct B {
+    void operator delete(B *, std::destroying_delete_t);
+  };
+  struct C : B {};
+  struct D : B {};
+  struct E : C, D {};
+  void g(E *e) {
+    delete e; // expected-error {{ambiguous conversion from derived class 'first_param_conversion::E' to base class 'first_param_conversion::B':}}
+  }
+}