diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2024-01-09 20:00:28 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-19 21:14:10 +0000 |
| commit | cdc20ff6a7f12464aed70d9b6e67ea07da9f0399 (patch) | |
| tree | 0c2f259d41b6d1f146c344cb9cf2b15ea99d35bb /contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp | |
| parent | 7adf29b6244fe016ef869f287a66048195f9af29 (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp | 79 |
1 files changed, 56 insertions, 23 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp index df6b40999e64..7f20413c104e 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -35,7 +35,6 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" @@ -345,15 +344,26 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( using namespace TemplateInstArgsHelpers; const Decl *CurDecl = ND; + + if (!CurDecl) + CurDecl = Decl::castFromDeclContext(DC); + if (Innermost) { Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), Innermost->asArray(), Final); - CurDecl = Response::UseNextDecl(ND).NextDecl; + // Populate placeholder template arguments for TemplateTemplateParmDecls. + // This is essential for the case e.g. + // + // template <class> concept Concept = false; + // template <template <Concept C> class T> void foo(T<int>) + // + // where parameter C has a depth of 1 but the substituting argument `int` + // has a depth of 0. + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) + HandleDefaultTempArgIntoTempTempParam(TTP, Result); + CurDecl = Response::UseNextDecl(CurDecl).NextDecl; } - if (!ND) - CurDecl = Decl::castFromDeclContext(DC); - while (!CurDecl->isFileContextDecl()) { Response R; if (const auto *VarTemplSpec = @@ -381,10 +391,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( R = Response::ChangeDecl(CTD->getLexicalDeclContext()); } else if (!isa<DeclContext>(CurDecl)) { R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); - if (CurDecl->getDeclContext()->isTranslationUnit()) { - if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) { - R = HandleDefaultTempArgIntoTempTempParam(TTP, Result); - } + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) { + R = HandleDefaultTempArgIntoTempTempParam(TTP, Result); } } else { R = HandleGenericDeclContext(CurDecl); @@ -1142,8 +1150,7 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: // We're either substituting explicitly-specified template arguments, // deduced template arguments. SFINAE applies unless we are in a lambda - // expression, see [temp.deduct]p9. - [[fallthrough]]; + // body, see [temp.deduct]p9. case CodeSynthesisContext::ConstraintSubstitution: case CodeSynthesisContext::RequirementInstantiation: case CodeSynthesisContext::RequirementParameterInstantiation: @@ -1190,6 +1197,7 @@ namespace { const MultiLevelTemplateArgumentList &TemplateArgs; SourceLocation Loc; DeclarationName Entity; + // Whether to evaluate the C++20 constraints or simply substitute into them. bool EvaluateConstraints = true; public: @@ -1444,13 +1452,6 @@ namespace { LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this); - Sema::CodeSynthesisContext C; - C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution; - C.PointOfInstantiation = E->getBeginLoc(); - SemaRef.pushCodeSynthesisContext(C); - auto PopCtx = - llvm::make_scope_exit([this] { SemaRef.popCodeSynthesisContext(); }); - ExprResult Result = inherited::TransformLambdaExpr(E); if (Result.isInvalid()) return Result; @@ -1478,6 +1479,23 @@ namespace { return Result; } + StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) { + // Currently, we instantiate the body when instantiating the lambda + // expression. However, `EvaluateConstraints` is disabled during the + // instantiation of the lambda expression, causing the instantiation + // failure of the return type requirement in the body. If p0588r1 is fully + // implemented, the body will be lazily instantiated, and this problem + // will not occur. Here, `EvaluateConstraints` is temporarily set to + // `true` to temporarily fix this issue. + // FIXME: This temporary fix can be removed after fully implementing + // p0588r1. + bool Prev = EvaluateConstraints; + EvaluateConstraints = true; + StmtResult Stmt = inherited::TransformLambdaBody(E, Body); + EvaluateConstraints = Prev; + return Stmt; + } + ExprResult TransformRequiresExpr(RequiresExpr *E) { LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); ExprResult TransReq = inherited::TransformRequiresExpr(E); @@ -1630,9 +1648,7 @@ bool TemplateInstantiator::TransformExceptionSpec( SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI, SmallVectorImpl<QualType> &Exceptions, bool &Changed) { if (ESI.Type == EST_Uninstantiated) { - ESI.NoexceptExpr = cast<FunctionProtoType>(ESI.SourceTemplate->getType()) - ->getNoexceptExpr(); - ESI.Type = EST_DependentNoexcept; + ESI.instantiate(); Changed = true; } return inherited::TransformExceptionSpec(Loc, ESI, Exceptions, Changed); @@ -2499,6 +2515,17 @@ TemplateInstantiator::TransformNestedRequirement( Req->getConstraintExpr()->getBeginLoc(), Req, Sema::InstantiatingTemplate::ConstraintsCheck{}, Req->getConstraintExpr()->getSourceRange()); + if (!getEvaluateConstraints()) { + ExprResult TransConstraint = TransformExpr(Req->getConstraintExpr()); + if (TransConstraint.isInvalid() || !TransConstraint.get()) + return nullptr; + if (TransConstraint.get()->isInstantiationDependent()) + return new (SemaRef.Context) + concepts::NestedRequirement(TransConstraint.get()); + ConstraintSatisfaction Satisfaction; + return new (SemaRef.Context) concepts::NestedRequirement( + SemaRef.Context, TransConstraint.get(), Satisfaction); + } ExprResult TransConstraint; ConstraintSatisfaction Satisfaction; @@ -4093,13 +4120,19 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { ExprResult Sema::SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { + // FIXME: should call SubstExpr directly if this function is equivalent or + // should it be different? + return SubstExpr(E, TemplateArgs); +} + +ExprResult Sema::SubstConstraintExprWithoutSatisfaction( + Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { if (!E) return E; - // This is where we need to make sure we 'know' constraint checking needs to - // happen. TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), DeclarationName()); + Instantiator.setEvaluateConstraints(false); return Instantiator.TransformExpr(E); } |
