summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2018-12-21 07:05:36 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2018-12-21 07:05:36 +0000
commit24b719c0fc2b1251a37741a2339ffcfe9cdcd475 (patch)
treebf8ec7f429da912c28cb060306760cc1d8f16c7d /lib
parent4e2a388a999e41a12743314deb9e0f060252a621 (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349890 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaExprCXX.cpp45
3 files changed, 34 insertions, 20 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d46aa23c27..8973d63255 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4ba0fb12e7..5178b03cfd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 2b054c4b0f..18d0e78a4f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/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();