aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaConcept.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaConcept.cpp')
-rw-r--r--clang/lib/Sema/SemaConcept.cpp47
1 files changed, 45 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index c6a54dc..a4f660c3 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -792,7 +792,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
bool ForOverloadResolution) {
// Don't check constraints if the function is dependent. Also don't check if
// this is a function template specialization, as the call to
- // CheckinstantiatedFunctionTemplateConstraints after this will check it
+ // CheckFunctionTemplateConstraints after this will check it
// better.
if (FD->isDependentContext() ||
FD->getTemplatedKind() ==
@@ -1060,12 +1060,55 @@ bool Sema::EnsureTemplateArgumentListConstraints(
return false;
}
-bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+static bool CheckFunctionConstraintsWithoutInstantiation(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ ConstraintSatisfaction &Satisfaction) {
+ SmallVector<AssociatedConstraint, 3> TemplateAC;
+ Template->getAssociatedConstraints(TemplateAC);
+ if (TemplateAC.empty()) {
+ Satisfaction.IsSatisfied = true;
+ return false;
+ }
+
+ LocalInstantiationScope Scope(SemaRef);
+
+ FunctionDecl *FD = Template->getTemplatedDecl();
+ // Collect the list of template arguments relative to the 'primary'
+ // template. We need the entire list, since the constraint is completely
+ // uninstantiated at this point.
+
+ // FIXME: Add TemplateArgs through the 'Innermost' parameter once
+ // the refactoring of getTemplateInstantiationArgs() relands.
+ MultiLevelTemplateArgumentList MLTAL;
+ MLTAL.addOuterTemplateArguments(Template, std::nullopt, /*Final=*/false);
+ SemaRef.getTemplateInstantiationArgs(
+ MLTAL, /*D=*/FD, FD,
+ /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
+ MLTAL.replaceInnermostTemplateArguments(Template, TemplateArgs);
+
+ Sema::ContextRAII SavedContext(SemaRef, FD);
+ std::optional<Sema::CXXThisScopeRAII> ThisScope;
+ if (auto *Method = dyn_cast<CXXMethodDecl>(FD))
+ ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
+ /*ThisQuals=*/Method->getMethodQualifiers());
+ return SemaRef.CheckConstraintSatisfaction(
+ Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
+}
+
+bool Sema::CheckFunctionTemplateConstraints(
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
ArrayRef<TemplateArgument> TemplateArgs,
ConstraintSatisfaction &Satisfaction) {
// In most cases we're not going to have constraints, so check for that first.
FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
+
+ if (!Template)
+ return ::CheckFunctionConstraintsWithoutInstantiation(
+ *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
+ TemplateArgs, Satisfaction);
+
// Note - code synthesis context for the constraints check is created
// inside CheckConstraintsSatisfaction.
SmallVector<AssociatedConstraint, 3> TemplateAC;