From: Richard Smith Date: Tue, 5 Dec 2017 23:54:25 +0000 (+0000) Subject: P0722R2: The first parameter in an implicit call to a destroying operator X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ee1bf3270a30ad876bd7f55fba8c1b1c6207298;p=clang P0722R2: The first parameter in an implicit call to a destroying operator 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 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 56b14ddd7f..e4634d96d1 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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(); diff --git a/test/SemaCXX/cxx2a-destroying-delete.cpp b/test/SemaCXX/cxx2a-destroying-delete.cpp index a085c11c26..6115774e38 100644 --- a/test/SemaCXX/cxx2a-destroying-delete.cpp +++ b/test/SemaCXX/cxx2a-destroying-delete.cpp @@ -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':}} + } +}