// 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();
};
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':}}
+ }
+}