aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.cpp17
-rw-r--r--clang/lib/Sema/SemaChecking.cpp22
-rw-r--r--clang/lib/Sema/SemaConcept.cpp57
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp24
-rw-r--r--clang/lib/Sema/SemaOpenACC.cpp25
-rw-r--r--clang/lib/Sema/SemaType.cpp18
6 files changed, 118 insertions, 45 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 215ac18..23bf7f2 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -276,10 +276,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
SourceMgr(PP.getSourceManager()), APINotes(SourceMgr, LangOpts),
AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
- LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
- OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
- StackHandler(Diags), CurScope(nullptr), Ident_super(nullptr),
- AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
+ LateTemplateParser(nullptr), OpaqueParser(nullptr), CurContext(nullptr),
+ ExternalSource(nullptr), StackHandler(Diags), CurScope(nullptr),
+ Ident_super(nullptr), AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
ARMPtr(std::make_unique<SemaARM>(*this)),
AVRPtr(std::make_unique<SemaAVR>(*this)),
BPFPtr(std::make_unique<SemaBPF>(*this)),
@@ -1248,9 +1247,6 @@ void Sema::ActOnEndOfTranslationUnit() {
? TUFragmentKind::Private
: TUFragmentKind::Normal);
- if (LateTemplateParserCleanup)
- LateTemplateParserCleanup(OpaqueParser);
-
CheckDelayedMemberExceptionSpecs();
} else {
// If we are building a TU prefix for serialization, it is safe to transfer
@@ -1484,6 +1480,13 @@ void Sema::ActOnEndOfTranslationUnit() {
Consumer.CompleteTentativeDefinition(VD);
}
+ // In incremental mode, tentative definitions belong to the current
+ // partial translation unit (PTU). Once they have been completed and
+ // emitted to codegen, drop them to prevent re-emission in future PTUs.
+ if (PP.isIncrementalProcessingEnabled())
+ TentativeDefinitions.erase(TentativeDefinitions.begin(ExternalSource.get()),
+ TentativeDefinitions.end());
+
for (auto *D : ExternalDeclarations) {
if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed())
continue;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2990fd6..f99c01e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1498,6 +1498,24 @@ static void builtinAllocaAddrSpace(Sema &S, CallExpr *TheCall) {
TheCall->setType(S.Context.getPointerType(RT));
}
+static bool checkBuiltinInferAllocToken(Sema &S, CallExpr *TheCall) {
+ if (S.checkArgCountAtLeast(TheCall, 1))
+ return true;
+
+ for (Expr *Arg : TheCall->arguments()) {
+ // If argument is dependent on a template parameter, we can't resolve now.
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ continue;
+ // Reject void types.
+ QualType ArgTy = Arg->IgnoreParenImpCasts()->getType();
+ if (ArgTy->isVoidType())
+ return S.Diag(Arg->getBeginLoc(), diag::err_param_with_void_type);
+ }
+
+ TheCall->setType(S.Context.UnsignedLongLongTy);
+ return false;
+}
+
namespace {
enum PointerAuthOpKind {
PAO_Strip,
@@ -2779,6 +2797,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
builtinAllocaAddrSpace(*this, TheCall);
}
break;
+ case Builtin::BI__builtin_infer_alloc_token:
+ if (checkBuiltinInferAllocToken(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__arithmetic_fence:
if (BuiltinArithmeticFence(TheCall))
return ExprError();
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 54cbfe4..f04cc45 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -385,6 +385,28 @@ public:
return inherited::TraverseStmt(E->getReplacement());
}
+ bool TraverseTemplateName(TemplateName Template) {
+ if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
+ Template.getAsTemplateDecl());
+ TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return true;
+
+ TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+ if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
+ }
+ assert(!Arg.getAsTemplate().isNull() &&
+ "Null template template argument");
+ UsedTemplateArgs.push_back(
+ SemaRef.Context.getCanonicalTemplateArgument(Arg));
+ }
+ return inherited::TraverseTemplateName(Template);
+ }
+
void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
if (!Constraint.hasParameterMapping()) {
for (const auto &List : TemplateArgs)
@@ -417,8 +439,8 @@ class ConstraintSatisfactionChecker {
const NamedDecl *Template;
SourceLocation TemplateNameLoc;
UnsignedOrNone PackSubstitutionIndex;
-
ConstraintSatisfaction &Satisfaction;
+ bool BuildExpression;
private:
ExprResult
@@ -461,10 +483,11 @@ public:
ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
SourceLocation TemplateNameLoc,
UnsignedOrNone PackSubstitutionIndex,
- ConstraintSatisfaction &Satisfaction)
+ ConstraintSatisfaction &Satisfaction,
+ bool BuildExpression)
: S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
PackSubstitutionIndex(PackSubstitutionIndex),
- Satisfaction(Satisfaction) {}
+ Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
ExprResult Evaluate(const NormalizedConstraint &Constraint,
const MultiLevelTemplateArgumentList &MLTAL);
@@ -821,9 +844,10 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
Satisfaction.ContainsErrors = false;
ExprResult Expr =
ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
- UnsignedOrNone(I), Satisfaction)
+ UnsignedOrNone(I), Satisfaction,
+ /*BuildExpression=*/false)
.Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
- if (Expr.isUsable()) {
+ if (BuildExpression && Expr.isUsable()) {
if (Out.isUnset())
Out = Expr;
else
@@ -834,7 +858,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
Constraint.getBeginLoc(),
FPOptionsOverride{});
} else {
- assert(!Satisfaction.IsSatisfied);
+ assert(!BuildExpression || !Satisfaction.IsSatisfied);
}
if (!Conjunction && Satisfaction.IsSatisfied) {
Satisfaction.Details.erase(Satisfaction.Details.begin() +
@@ -985,7 +1009,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
- if (!E.isUsable()) {
+ if (E.isInvalid()) {
Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
return E;
}
@@ -1041,7 +1065,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
return LHS;
- if (!Conjunction && LHS.isUsable() && Satisfaction.IsSatisfied &&
+ if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
!Satisfaction.ContainsErrors)
return LHS;
@@ -1050,12 +1074,15 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
- if (RHS.isUsable() && Satisfaction.IsSatisfied &&
+ if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
!Satisfaction.ContainsErrors)
Satisfaction.Details.erase(Satisfaction.Details.begin() +
EffectiveDetailEndIndex,
Satisfaction.Details.end());
+ if (!BuildExpression)
+ return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
+
if (!LHS.isUsable())
return RHS;
@@ -1136,10 +1163,11 @@ static bool CheckConstraintSatisfaction(
Template, /*CSE=*/nullptr,
S.ArgPackSubstIndex);
- ExprResult Res =
- ConstraintSatisfactionChecker(S, Template, TemplateIDRange.getBegin(),
- S.ArgPackSubstIndex, Satisfaction)
- .Evaluate(*C, TemplateArgsLists);
+ ExprResult Res = ConstraintSatisfactionChecker(
+ S, Template, TemplateIDRange.getBegin(),
+ S.ArgPackSubstIndex, Satisfaction,
+ /*BuildExpression=*/ConvertedExpr != nullptr)
+ .Evaluate(*C, TemplateArgsLists);
if (Res.isInvalid())
return true;
@@ -2672,8 +2700,9 @@ FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
});
if (Compound.getCompoundKind() == FormulaType::Kind) {
+ unsigned SizeLeft = Left.size();
Res = std::move(Left);
- Res.reserve(Left.size() + Right.size());
+ Res.reserve(SizeLeft + Right.size());
std::for_each(std::make_move_iterator(Right.begin()),
std::make_move_iterator(Right.end()), Add);
return Res;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9475b8a..964a2a7 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5206,16 +5206,36 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleDeviceKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
bool IsFunctionTemplate = FD && FD->getDescribedFunctionTemplate();
- if (S.getASTContext().getTargetInfo().getTriple().isNVPTX()) {
+ llvm::Triple Triple = S.getASTContext().getTargetInfo().getTriple();
+ const LangOptions &LangOpts = S.getLangOpts();
+ // OpenCL has its own error messages.
+ if (!LangOpts.OpenCL && FD && !FD->isExternallyVisible()) {
+ S.Diag(AL.getLoc(), diag::err_hidden_device_kernel) << FD;
+ AL.setInvalid();
+ return;
+ }
+ if (Triple.isNVPTX()) {
handleGlobalAttr(S, D, AL);
} else {
// OpenCL C++ will throw a more specific error.
- if (!S.getLangOpts().OpenCLCPlusPlus && (!FD || IsFunctionTemplate)) {
+ if (!LangOpts.OpenCLCPlusPlus && (!FD || IsFunctionTemplate)) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str)
<< AL << AL.isRegularKeywordAttribute() << "functions";
+ AL.setInvalid();
+ return;
}
handleSimpleAttribute<DeviceKernelAttr>(S, D, AL);
}
+ // TODO: isGPU() should probably return true for SPIR.
+ bool TargetDeviceEnvironment = Triple.isGPU() || Triple.isSPIR() ||
+ LangOpts.isTargetDevice() || LangOpts.OpenCL;
+ if (!TargetDeviceEnvironment) {
+ S.Diag(AL.getLoc(), diag::warn_cconv_unsupported)
+ << AL << (int)Sema::CallingConventionIgnoredReason::ForThisTarget;
+ AL.setInvalid();
+ return;
+ }
+
// Make sure we validate the CC with the target
// and warn/error if necessary.
handleCallConvAttr(S, D, AL);
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 3bb8080..ee9b2b3 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -2999,11 +2999,11 @@ bool SemaOpenACC::CreateReductionCombinerRecipe(
BinOp = BinaryOperatorKind::BO_LT;
break;
case OpenACCReductionOperator::And:
+ BinOp = BinaryOperatorKind::BO_LAnd;
+ break;
case OpenACCReductionOperator::Or:
- // We just want a 'NYI' error in the backend, so leave an empty combiner
- // recipe, and claim success.
- CombinerRecipes.push_back({nullptr, nullptr, nullptr});
- return false;
+ BinOp = BinaryOperatorKind::BO_LOr;
+ break;
}
// If VarTy is an array type, at the top level only, we want to do our
@@ -3068,8 +3068,21 @@ bool SemaOpenACC::CreateReductionCombinerRecipe(
: CombinerFailureKind::Assignment};
}
case OpenACCReductionOperator::And:
- case OpenACCReductionOperator::Or:
- llvm_unreachable("And/Or not implemented, but should fail earlier");
+ case OpenACCReductionOperator::Or: {
+ // These are done as LHS = LHS && RHS (or LHS = LHS || RHS). So after the
+ // binop, all we have to do is the assignment.
+ if (!BinOpRes.isUsable())
+ return {BinOpRes, CombinerFailureKind::BinOp};
+
+ // Build assignment.
+ ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
+ BinaryOperatorKind::BO_Assign,
+ LHSDRE, BinOpRes.get(),
+ /*ForFoldExpr=*/false);
+ return {Assignment, Assignment.isUsable()
+ ? CombinerFailureKind::None
+ : CombinerFailureKind::Assignment};
+ }
case OpenACCReductionOperator::Invalid:
llvm_unreachable("Invalid should have been caught above");
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 7c1fb12..280b3c9 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -134,7 +134,6 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
case ParsedAttr::AT_VectorCall: \
case ParsedAttr::AT_AArch64VectorPcs: \
case ParsedAttr::AT_AArch64SVEPcs: \
- case ParsedAttr::AT_DeviceKernel: \
case ParsedAttr::AT_MSABI: \
case ParsedAttr::AT_SysVABI: \
case ParsedAttr::AT_Pcs: \
@@ -3786,7 +3785,8 @@ static CallingConv getCCForDeclaratorChunk(
}
}
}
- for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
+ for (const ParsedAttr &AL : llvm::concat<ParsedAttr>(
+ D.getDeclSpec().getAttributes(), D.getAttributes())) {
if (AL.getKind() == ParsedAttr::AT_DeviceKernel) {
CC = CC_DeviceKernel;
break;
@@ -7569,8 +7569,6 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
return createSimpleAttr<AArch64SVEPcsAttr>(Ctx, Attr);
case ParsedAttr::AT_ArmStreaming:
return createSimpleAttr<ArmStreamingAttr>(Ctx, Attr);
- case ParsedAttr::AT_DeviceKernel:
- return createSimpleAttr<DeviceKernelAttr>(Ctx, Attr);
case ParsedAttr::AT_Pcs: {
// The attribute may have had a fixit applied where we treated an
// identifier as a string literal. The contents of the string are valid,
@@ -8809,16 +8807,6 @@ static void HandleHLSLParamModifierAttr(TypeProcessingState &State,
}
}
-static bool isMultiSubjectAttrAllowedOnType(const ParsedAttr &Attr) {
- // The DeviceKernel attribute is shared for many targets, and
- // it is only allowed to be a type attribute with the AMDGPU
- // spelling, so skip processing the attr as a type attr
- // unless it has that spelling.
- if (Attr.getKind() != ParsedAttr::AT_DeviceKernel)
- return true;
- return DeviceKernelAttr::isAMDGPUSpelling(Attr);
-}
-
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
TypeAttrLocation TAL,
const ParsedAttributesView &attrs,
@@ -9072,8 +9060,6 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
[[fallthrough]];
FUNCTION_TYPE_ATTRS_CASELIST:
- if (!isMultiSubjectAttrAllowedOnType(attr))
- break;
attr.setUsedAsTypeAttr();