diff options
author | Younan Zhang <zyn7109@gmail.com> | 2025-01-05 10:50:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-05 10:50:52 +0800 |
commit | 96eced624e0f120155256033fdcb8342e7e58d6e (patch) | |
tree | 68e423e65c83c5013c9343f168cdfdc44ec99322 /clang/lib/Sema/SemaConcept.cpp | |
parent | 2d9d291da0fb94c05b31de0b08ccb881dbead798 (diff) | |
download | llvm-96eced624e0f120155256033fdcb8342e7e58d6e.zip llvm-96eced624e0f120155256033fdcb8342e7e58d6e.tar.gz llvm-96eced624e0f120155256033fdcb8342e7e58d6e.tar.bz2 |
[Clang] Implement CWG2369 "Ordering between constraints and substitution" (#102857)
This patch partially implements CWG2369 for non-lambda-constrained
functions.
Lambdas are left intact at this point because we need extra work to
correctly instantiate captures before the function instantiation.
As a premise of CWG2369, this patch also implements CWG2770 to ensure
the function parameters are instantiated on demand.
Closes https://github.com/llvm/llvm-project/issues/54440
Diffstat (limited to 'clang/lib/Sema/SemaConcept.cpp')
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 539de00..10f4920 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -846,7 +846,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() == @@ -1111,12 +1111,55 @@ bool Sema::EnsureTemplateArgumentListConstraints( return false; } -bool Sema::CheckInstantiatedFunctionTemplateConstraints( +static bool CheckFunctionConstraintsWithoutInstantiation( + Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, + ConstraintSatisfaction &Satisfaction) { + SmallVector<const Expr *, 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<const Expr *, 3> TemplateAC; |