diff options
| author | Akira Hatanaka <ahatanaka@apple.com> | 2018-12-21 07:05:36 +0000 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-12-21 07:05:36 +0000 |
| commit | 71645c2febab89e33fb346672a6fb807c4a5d47e (patch) | |
| tree | 669079d6e54e37c55c0e104b8af987c5285a9a61 /clang/lib | |
| parent | b6dac89c8753e654d3dafeec398ddcd7e9b02c4b (diff) | |
| download | bcm5719-llvm-71645c2febab89e33fb346672a6fb807c4a5d47e.tar.gz bcm5719-llvm-71645c2febab89e33fb346672a6fb807c4a5d47e.zip | |
[Sema] Produce diagnostics when C++17 aligned allocation/deallocation
functions that are unavailable on Darwin are explicitly called or called
from deleting destructors.
rdar://problem/40736230
Differential Revision: https://reviews.llvm.org/D47757
llvm-svn: 349890
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 45 |
3 files changed, 34 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d46aa23c274..8973d632550 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8288,6 +8288,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { } } + DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4ba0fb12e70..5178b03cfd7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -66,6 +66,12 @@ bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() && DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false)) return false; + + // See if this is an aligned allocation/deallocation function that is + // unavailable. + if (TreatUnavailableAsInvalid && + isUnavailableAlignedAllocationFunction(*FD)) + return false; } // See if this function is unavailable. @@ -228,6 +234,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, // The function 'main' shall not be used within a program. if (cast<FunctionDecl>(D)->isMain()) Diag(Loc, diag::ext_main_used); + + diagnoseUnavailableAlignedAllocation(*cast<FunctionDecl>(D), Loc); } // See if this is an auto-typed variable whose initializer we are parsing. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 2b054c4b0f3..18d0e78a4f5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1744,28 +1744,33 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, return false; } -// 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) - return; - - // Return if there is a definition. +bool +Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const { + if (!getLangOpts().AlignedAllocationUnavailable) + return false; if (FD.isDefined()) - return; - + return false; bool IsAligned = false; - if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) { - const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple(); + if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) + return true; + return false; +} + +// Emit a diagnostic if an aligned allocation/deallocation function that is not +// implemented in the standard library is selected. +void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc) { + if (isUnavailableAlignedAllocationFunction(FD)) { + const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( - S.getASTContext().getTargetInfo().getPlatformName()); + getASTContext().getTargetInfo().getPlatformName()); - S.Diag(Loc, diag::err_aligned_allocation_unavailable) + OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator(); + bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete; + Diag(Loc, diag::err_aligned_allocation_unavailable) << IsDelete << FD.getType().getAsString() << OSName << alignedAllocMinVersion(T.getOS()).getAsString(); - S.Diag(Loc, diag::note_silence_aligned_allocation_unavailable); + Diag(Loc, diag::note_silence_aligned_allocation_unavailable); } } @@ -2149,13 +2154,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, 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: @@ -3405,8 +3408,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - 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 @@ -3539,6 +3541,9 @@ Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, return ExprError(); assert(OperatorNewOrDelete && "should be found"); + DiagnoseUseOfDecl(OperatorNewOrDelete, TheCall->getExprLoc()); + MarkFunctionReferenced(TheCall->getExprLoc(), OperatorNewOrDelete); + TheCall->setType(OperatorNewOrDelete->getReturnType()); for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) { QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType(); |

