Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5166,6 +5166,11 @@ SourceRange DirectInitRange, Expr *Initializer); + /// Produce diagnostics if FD is an aligned allocation or deallocation + /// function that is unavailable. + void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc); + bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -8186,6 +8186,7 @@ } } + DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -226,6 +226,8 @@ // The function 'main' shall not be used within a program. if (cast(D)->isMain()) Diag(Loc, diag::ext_main_used); + + diagnoseUnavailableAlignedAllocation(*cast(D), Loc); } // See if this is an auto-typed variable whose initializer we are parsing. Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -1681,10 +1681,9 @@ // Emit a diagnostic if an aligned allocation/deallocation function that is not // implemented in the standard library is selected. -static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, - SourceLocation Loc, bool IsDelete, - Sema &S) { - if (!S.getLangOpts().AlignedAllocationUnavailable) +void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc) { + if (!getLangOpts().AlignedAllocationUnavailable) return; // Return if there is a definition. @@ -1693,14 +1692,15 @@ bool IsAligned = false; if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) { - const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple(); + const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( - S.getASTContext().getTargetInfo().getPlatformName()); - - S.Diag(Loc, diag::warn_aligned_allocation_unavailable) + getASTContext().getTargetInfo().getPlatformName()); + OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator(); + bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete; + Diag(Loc, diag::warn_aligned_allocation_unavailable) << IsDelete << FD.getType().getAsString() << OSName << alignedAllocMinVersion(T.getOS()).getAsString(); - S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable); + Diag(Loc, diag::note_silence_unligned_allocation_unavailable); } } @@ -2091,13 +2091,11 @@ if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); - diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this); } if (OperatorDelete) { if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); } // C++0x [expr.new]p17: @@ -3329,8 +3327,7 @@ } } - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, - *this); + DiagnoseUseOfDecl(OperatorDelete, StartLoc); // Convert the operand to the type of the first parameter of operator // delete. This is only necessary if we selected a destroying operator @@ -3463,6 +3460,8 @@ return ExprError(); assert(OperatorNewOrDelete && "should be found"); + DiagnoseUseOfDecl(OperatorNewOrDelete, TheCall->getExprLoc()); + TheCall->setType(OperatorNewOrDelete->getReturnType()); for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) { QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType(); Index: test/CXX/drs/dr2xx.cpp =================================================================== --- test/CXX/drs/dr2xx.cpp +++ test/CXX/drs/dr2xx.cpp @@ -726,7 +726,7 @@ }; struct C { inline void operator delete(void*) __attribute__((unused)); - virtual ~C() {} + virtual ~C() {} // expected-warning {{'operator delete' was marked unused but was used}} }; struct D { Index: test/SemaCUDA/call-host-fn-from-device.cu =================================================================== --- test/SemaCUDA/call-host-fn-from-device.cu +++ test/SemaCUDA/call-host-fn-from-device.cu @@ -85,7 +85,7 @@ } __host__ __device__ void class_specific_delete(T *t, U *u) { - delete t; // ok, call sized device delete even though host has preferable non-sized version + delete t; // expected-error {{reference to __host__ function 'operator delete' in __host__ __device__ function}} delete u; // ok, call non-sized HD delete rather than sized D delete } Index: test/SemaCXX/unavailable_aligned_allocation.cpp =================================================================== --- test/SemaCXX/unavailable_aligned_allocation.cpp +++ test/SemaCXX/unavailable_aligned_allocation.cpp @@ -124,7 +124,73 @@ // expected-note@-20 2 {{if you supply your own aligned allocation functions}} #endif -// No errors if user-defined aligned allocation functions are available. +// Test that diagnostics are produced when an unavailable aligned deallocation +// function is called from a deleting destructor. +struct alignas(256) OveralignedS2 { + int a[4]; + virtual ~OveralignedS2(); +}; + +OveralignedS2::~OveralignedS2() {} + +#ifdef NO_ERRORS +// expected-no-diagnostics +#else +#if defined(IOS) +// expected-error@-6 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on iOS 11 or newer}}} +// expected-note@-7 {{if you supply your own aligned allocation functions}} +#elif defined(TVOS) +// expected-error@-9 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on tvOS 11 or newer}}} +// expected-note@-10 {{if you supply your own aligned allocation functions}} +#elif defined(WATCHOS) +// expected-error@-12 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} +// expected-note@-13 {{if you supply your own aligned allocation functions}} +#else +// expected-error@-15 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}} +// expected-note@-16 {{if you supply your own aligned allocation functions}} +#endif +#endif + +void testExplicitOperatorNewDelete() { + void *p = operator new(128); + operator delete(p); + p = operator new[](128); + operator delete[](p); + p = __builtin_operator_new(128); + __builtin_operator_delete(p); +} + +void testExplicitOperatorNewDeleteOveraligned() { + void *p = operator new(128, (std::align_val_t)64); + operator delete(p, (std::align_val_t)64); + p = operator new[](128, (std::align_val_t)64); + operator delete[](p, (std::align_val_t)64); + p = __builtin_operator_new(128, (std::align_val_t)64); + __builtin_operator_delete(p, (std::align_val_t)64); +} + +#ifdef NO_ERRORS +// expected-no-diagnostics +#else +// expected-error@-11 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-12 {{if you supply your own aligned allocation functions}} + +// expected-error@-13 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-14 {{if you supply your own aligned allocation functions}} + +// expected-error@-15 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-16 {{if you supply your own aligned allocation functions}} + +// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-18 {{if you supply your own aligned allocation functions}} + +// expected-error@-19 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-20 {{if you supply your own aligned allocation functions}} + +// expected-error@-21 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-22 {{if you supply your own aligned allocation functions}} +#endif + void *operator new(std::size_t __sz, std::align_val_t) { static char array[256]; return &array;