diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 93 |
1 files changed, 61 insertions, 32 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 2bf1511..dcf2876 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -9,6 +9,7 @@ //===----------------------------------------------------------------------===// #include "TreeTransform.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -1222,8 +1223,9 @@ static ExprResult formImmediatelyDeclaredConstraint( if (auto *CD = dyn_cast<ConceptDecl>(NamedConcept)) { ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId( SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, - /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, CD, - &ConstraintArgs); + /*FoundDecl=*/FoundDecl ? FoundDecl : CD, CD, &ConstraintArgs, + /*DoCheckConstraintSatisfaction=*/ + !S.inParameterMappingSubstitution()); } // We have a template template parameter else { @@ -4850,13 +4852,11 @@ void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS, diagnoseMissingTemplateArguments(Name, Loc); } -ExprResult -Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &ConceptNameInfo, - NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, - const TemplateArgumentListInfo *TemplateArgs) { +ExprResult Sema::CheckConceptTemplateId( + const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, + TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, + bool DoCheckConstraintSatisfaction) { assert(NamedConcept && "A concept template id without a template?"); if (NamedConcept->isInvalidDecl()) @@ -4873,33 +4873,48 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc()); + // There's a bug with CTAI.CanonicalConverted. + // If the template argument contains a DependentDecltypeType that includes a + // TypeAliasType, and the same written type had occurred previously in the + // source, then the DependentDecltypeType would be canonicalized to that + // previous type which would mess up the substitution. + // FIXME: Reland https://github.com/llvm/llvm-project/pull/101782 properly! auto *CSD = ImplicitConceptSpecializationDecl::Create( Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), - CTAI.CanonicalConverted); + CTAI.SugaredConverted); ConstraintSatisfaction Satisfaction; bool AreArgsDependent = TemplateSpecializationType::anyDependentTemplateArguments( - *TemplateArgs, CTAI.CanonicalConverted); - MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.CanonicalConverted, + *TemplateArgs, CTAI.SugaredConverted); + MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.SugaredConverted, /*Final=*/false); - LocalInstantiationScope Scope(*this); - - EnterExpressionEvaluationContext EECtx{ - *this, ExpressionEvaluationContext::Unevaluated, CSD}; - - if (!AreArgsDependent && - CheckConstraintSatisfaction( - NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()), - MLTAL, - SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(), - TemplateArgs->getRAngleLoc()), - Satisfaction)) - return ExprError(); auto *CL = ConceptReference::Create( Context, SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs)); + + bool Error = false; + if (const auto *Concept = dyn_cast<ConceptDecl>(NamedConcept); + Concept && Concept->getConstraintExpr() && !AreArgsDependent && + DoCheckConstraintSatisfaction) { + + LocalInstantiationScope Scope(*this); + + EnterExpressionEvaluationContext EECtx{ + *this, ExpressionEvaluationContext::Unevaluated, CSD}; + + Error = CheckConstraintSatisfaction( + NamedConcept, AssociatedConstraint(Concept->getConstraintExpr()), MLTAL, + SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(), + TemplateArgs->getRAngleLoc()), + Satisfaction, CL); + Satisfaction.ContainsErrors = Error; + } + + if (Error) + return ExprError(); + return ConceptSpecializationExpr::Create( Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction); } @@ -5217,10 +5232,11 @@ bool Sema::CheckTemplateTypeArgument( } default: { // We allow instantiating a template with template argument packs when - // building deduction guides. + // building deduction guides or mapping constraint template parameters. if (Arg.getKind() == TemplateArgument::Pack && - CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides) { + (CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::BuildingDeductionGuides || + inParameterMappingSubstitution())) { SugaredConverted.push_back(Arg); CanonicalConverted.push_back(Arg); return false; @@ -5813,6 +5829,20 @@ bool Sema::CheckTemplateArgumentList( TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) { + return CheckTemplateArgumentList( + Template, GetTemplateParameterList(Template), TemplateLoc, TemplateArgs, + DefaultArgs, PartialTemplateArgs, CTAI, UpdateArgsWithConversions, + ConstraintsNotSatisfied); +} + +/// Check that the given template argument list is well-formed +/// for specializing the given template. +bool Sema::CheckTemplateArgumentList( + TemplateDecl *Template, TemplateParameterList *Params, + SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, + const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, + CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions, + bool *ConstraintsNotSatisfied) { if (ConstraintsNotSatisfied) *ConstraintsNotSatisfied = false; @@ -5822,8 +5852,6 @@ bool Sema::CheckTemplateArgumentList( // template. TemplateArgumentListInfo NewArgs = TemplateArgs; - TemplateParameterList *Params = GetTemplateParameterList(Template); - SourceLocation RAngleLoc = NewArgs.getRAngleLoc(); // C++23 [temp.arg.general]p1: @@ -6163,11 +6191,12 @@ bool Sema::CheckTemplateArgumentList( CXXThisScopeRAII Scope(*this, RD, ThisQuals, RD != nullptr); MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( - Template, NewContext, /*Final=*/false, CTAI.CanonicalConverted, + Template, NewContext, /*Final=*/true, CTAI.SugaredConverted, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConceptInstantiation=*/true); - if (EnsureTemplateArgumentListConstraints( + if (!isa<ConceptDecl>(Template) && + EnsureTemplateArgumentListConstraints( Template, MLTAL, SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { if (ConstraintsNotSatisfied) |