Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5166,6 +5166,9 @@ SourceRange DirectInitRange, Expr *Initializer); + void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc, bool IsDelete); + bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -8160,6 +8160,7 @@ // If we have a virtual destructor, look up the deallocation function if (FunctionDecl *OperatorDelete = FindDeallocationFunctionForDestructor(Loc, RD)) { + diagnoseUnavailableAlignedAllocation(*OperatorDelete, Loc, true); Expr *ThisArg = nullptr; // If the notional 'delete this' expression requires a non-trivial Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -1681,10 +1681,10 @@ // 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, + bool IsDelete) { + if (!getLangOpts().AlignedAllocationUnavailable) return; // Return if there is a definition. @@ -1693,14 +1693,14 @@ 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()); + getASTContext().getTargetInfo().getPlatformName()); - S.Diag(Loc, diag::warn_aligned_allocation_unavailable) + 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,13 @@ if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); - diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this); + diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false); } if (OperatorDelete) { if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true); } // C++0x [expr.new]p17: @@ -3329,8 +3329,7 @@ } } - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, - *this); + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true); // Convert the operand to the type of the first parameter of operator // delete. This is only necessary if we selected a destroying operator Index: test/SemaCXX/unavailable_aligned_allocation.cpp =================================================================== --- test/SemaCXX/unavailable_aligned_allocation.cpp +++ test/SemaCXX/unavailable_aligned_allocation.cpp @@ -124,6 +124,33 @@ // expected-note@-20 2 {{if you supply your own aligned allocation functions}} #endif +// 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 + // No errors if user-defined aligned allocation functions are available. void *operator new(std::size_t __sz, std::align_val_t) { static char array[256];