summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorSaar Raz <saar@raz.email>2020-01-25 22:54:27 +0200
committerSaar Raz <saar@raz.email>2020-01-25 23:10:40 +0200
commitc21e178bf22b6b46f087e6aab02a34d11dd98432 (patch)
treeda17ffa2315dc6dac7a64d5727e9536771e7a34d /clang/lib/Sema
parent0df13627c6a4006de39e5f01d81a338793b0e82b (diff)
downloadbcm5719-llvm-c21e178bf22b6b46f087e6aab02a34d11dd98432.tar.gz
bcm5719-llvm-c21e178bf22b6b46f087e6aab02a34d11dd98432.zip
[Concepts] Transform constraints of non-template functions to ConstantEvaluated
We would previously try to evaluate atomic constraints of non-template functions as-is, and since they are now unevaluated at first, this would cause incorrect evaluation (bugs #44657, #44656). Substitute into atomic constraints of non-template functions as we would atomic constraints of template functions, in order to rebuild the expressions in a constant-evaluated context. (cherry picked from commit 713562f54858f10bf8998ee21ff2c7e7bad0d177)
Diffstat (limited to 'clang/lib/Sema')
-rwxr-xr-xclang/lib/Sema/SemaConcept.cpp58
-rw-r--r--clang/lib/Sema/SemaExpr.cpp3
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaOverload.cpp20
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp17
5 files changed, 57 insertions, 44 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 81601b09ce0..e5c0fa28c11 100755
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -167,9 +167,8 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
return false;
}
-template <typename TemplateDeclT>
static bool calculateConstraintSatisfaction(
- Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction(
@@ -182,8 +181,9 @@ static bool calculateConstraintSatisfaction(
{
TemplateDeductionInfo Info(TemplateNameLoc);
Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
- Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
- Info, AtomicExpr->getSourceRange());
+ Sema::InstantiatingTemplate::ConstraintSubstitution{},
+ const_cast<NamedDecl *>(Template), Info,
+ AtomicExpr->getSourceRange());
if (Inst.isInvalid())
return ExprError();
// We do not want error diagnostics escaping here.
@@ -230,8 +230,7 @@ static bool calculateConstraintSatisfaction(
});
}
-template<typename TemplateDeclT>
-static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
+static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange,
@@ -249,8 +248,8 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
}
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
- Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
- TemplateIDRange);
+ Sema::InstantiatingTemplate::ConstraintsCheck{},
+ const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
if (Inst.isInvalid())
return true;
@@ -273,7 +272,7 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
}
bool Sema::CheckConstraintSatisfaction(
- NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+ const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
ConstraintSatisfaction &OutSatisfaction) {
if (ConstraintExprs.empty()) {
@@ -284,7 +283,8 @@ bool Sema::CheckConstraintSatisfaction(
llvm::FoldingSetNodeID ID;
void *InsertPos;
ConstraintSatisfaction *Satisfaction = nullptr;
- if (LangOpts.ConceptSatisfactionCaching) {
+ bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
+ if (ShouldCache) {
ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
if (Satisfaction) {
@@ -295,27 +295,15 @@ bool Sema::CheckConstraintSatisfaction(
} else {
Satisfaction = &OutSatisfaction;
}
- bool Failed;
- if (auto *T = dyn_cast<TemplateDecl>(Template))
- Failed = ::CheckConstraintSatisfaction(*this, T, ConstraintExprs,
- TemplateArgs, TemplateIDRange,
- *Satisfaction);
- else if (auto *P =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(Template))
- Failed = ::CheckConstraintSatisfaction(*this, P, ConstraintExprs,
- TemplateArgs, TemplateIDRange,
- *Satisfaction);
- else
- Failed = ::CheckConstraintSatisfaction(
- *this, cast<VarTemplatePartialSpecializationDecl>(Template),
- ConstraintExprs, TemplateArgs, TemplateIDRange, *Satisfaction);
- if (Failed) {
- if (LangOpts.ConceptSatisfactionCaching)
+ if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
+ TemplateArgs, TemplateIDRange,
+ *Satisfaction)) {
+ if (ShouldCache)
delete Satisfaction;
return true;
}
- if (LangOpts.ConceptSatisfactionCaching) {
+ if (ShouldCache) {
// We cannot use InsertNode here because CheckConstraintSatisfaction might
// have invalidated it.
SatisfactionCache.InsertNode(Satisfaction);
@@ -333,6 +321,22 @@ bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
});
}
+bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
+ ConstraintSatisfaction &Satisfaction,
+ SourceLocation UsageLoc) {
+ const Expr *RC = FD->getTrailingRequiresClause();
+ assert(!RC->isInstantiationDependent() &&
+ "CheckFunctionConstraints can only be used with functions with "
+ "non-dependent constraints");
+ // We substitute with empty arguments in order to rebuild the atomic
+ // constraint in a constant-evaluated context.
+ // FIXME: Should this be a dedicated TreeTransform?
+ return CheckConstraintSatisfaction(
+ FD, {RC}, /*TemplateArgs=*/{},
+ SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
+ Satisfaction);
+}
+
bool Sema::EnsureTemplateArgumentListConstraints(
TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ea4b93ee6a5..4f777e7b981 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -335,7 +335,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (Expr *RC = FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- bool Failed = CheckConstraintSatisfaction(RC, Satisfaction);
+ bool Failed = CheckConstraintSatisfaction(FD, {RC}, /*TemplateArgs=*/{},
+ SourceRange(Loc), Satisfaction);
if (Failed)
// A diagnostic will have already been generated (non-constant
// constraint expression, for example)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 192c237b6c1..98af7fb73ec 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -8487,7 +8487,8 @@ concepts::NestedRequirement *
Sema::BuildNestedRequirement(Expr *Constraint) {
ConstraintSatisfaction Satisfaction;
if (!Constraint->isInstantiationDependent() &&
- CheckConstraintSatisfaction(Constraint, Satisfaction))
+ CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
+ Constraint->getSourceRange(), Satisfaction))
return nullptr;
return new (Context) concepts::NestedRequirement(Context, Constraint,
Satisfaction);
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0fd932fac97..9f4996b5463 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6291,9 +6291,9 @@ void Sema::AddOverloadCandidate(
return;
}
- if (Expr *RequiresClause = Function->getTrailingRequiresClause()) {
+ if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -6808,9 +6808,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
}
- if (Expr *RequiresClause = Method->getTrailingRequiresClause()) {
+ if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Method, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -7204,10 +7204,9 @@ void Sema::AddConversionCandidate(
return;
}
- Expr *RequiresClause = Conversion->getTrailingRequiresClause();
- if (RequiresClause) {
+ if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Conversion, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -9947,9 +9946,9 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
- if (const Expr *RC = FD->getTrailingRequiresClause()) {
+ if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (S.CheckConstraintSatisfaction(RC, Satisfaction))
+ if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
return false;
if (!Satisfaction.IsSatisfied) {
if (Complain) {
@@ -10974,8 +10973,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc /* Ignored */;
ConstraintSatisfaction Satisfaction;
- if (S.CheckConstraintSatisfaction(Fn->getTrailingRequiresClause(),
- Satisfaction))
+ if (S.CheckFunctionConstraints(Fn, Satisfaction))
break;
S.DiagnoseUnsatisfiedConstraint(Satisfaction);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 39bc28d6230..26dc5d92f23 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -763,21 +763,30 @@ void Sema::PrintInstantiationStack() {
case CodeSynthesisContext::ConstraintsCheck: {
unsigned DiagID = 0;
+ if (!Active->Entity) {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_nested_requirement_here)
+ << Active->InstantiationRange;
+ break;
+ }
if (isa<ConceptDecl>(Active->Entity))
DiagID = diag::note_concept_specialization_here;
else if (isa<TemplateDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_template_id_here;
else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_var_spec_id_here;
- else {
- assert(isa<ClassTemplatePartialSpecializationDecl>(Active->Entity));
+ else if (isa<ClassTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_class_spec_id_here;
+ else {
+ assert(isa<FunctionDecl>(Active->Entity));
+ DiagID = diag::note_checking_constraints_for_function_here;
}
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
cast<NamedDecl>(Active->Entity)->printName(OS);
- printTemplateArgumentList(OS, Active->template_arguments(),
- getPrintingPolicy());
+ if (!isa<FunctionDecl>(Active->Entity))
+ printTemplateArgumentList(OS, Active->template_arguments(),
+ getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
<< Active->InstantiationRange;
break;
OpenPOWER on IntegriCloud