From 3f14172f63c10ef5efac9b63e123821dd3388d2a Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Sat, 14 Jun 2025 18:49:03 +0800 Subject: [PATCH 1/2] checkpoint AST/ByteCode/libcxx/deref-to-array.cpp now compiles But there are more tests getting regressed now, as I have disabled ShouldPreserveTemplateArgumentsPacks, which caused bugs for deref-to-array.cpp Failed Tests (13): Clang :: AST/ByteCode/libcxx/minmax.cpp Clang :: AST/ByteCode/libcxx/primitive-temporary.cpp Clang :: CXX/drs/cwg25xx.cpp Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: CXX/temp/temp.param/p10-2a.cpp Clang :: CodeGenCXX/mangle-concept.cpp Clang :: Modules/pr62943.cppm Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/concepts.cpp Clang :: SemaTemplate/instantiate-template-argument.cpp Clang :: SemaTemplate/temp_arg_nontype_cxx2c.cpp --- clang/lib/Sema/SemaConcept.cpp | 55 +++++++++++++++------- clang/lib/Sema/SemaTemplate.cpp | 11 +++++ clang/lib/Sema/SemaTemplateDeduction.cpp | 11 +++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 ++-- clang/lib/Sema/TreeTransform.h | 6 +-- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index b3488c9dc903d..a7a4c87e3d696 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -380,21 +380,29 @@ SubstitutionInTemplateArguments( Constraint.getParameterMapping(), MLTAL, SubstArgs) || Trap.hasErrorOccurred()) return std::nullopt; + // Sema::CheckTemplateArgumentInfo CTAI; + // auto *TD = const_cast( + // cast(Constraint.getConstraintDecl())); + // if (S.CheckTemplateArgumentList(TD, TD->getLocation(), SubstArgs, + // /*DefaultArguments=*/{}, + // /*PartialTemplateArgs=*/true, CTAI)) + // return std::nullopt; NormalizedConstraint::OccurenceList Used = Constraint.mappingOccurenceList(); SubstitutedOuterMost = llvm::to_vector_of(MLTAL.getOutermost()); - for (unsigned I = 0, MappedIndex = 0; I < SubstArgs.size(); I++) - if (I < Used.size() && Used[I]) { + for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) { + TemplateArgument Arg; + if (Used[I]) // SubstitutedOuterMost[I].dump(); // SubstArgs[MappedIndex].getArgument().dump(); - TemplateArgument Arg = S.Context.getCanonicalTemplateArgument( + Arg = S.Context.getCanonicalTemplateArgument( SubstArgs[MappedIndex++].getArgument()); - if (I < SubstitutedOuterMost.size()) - SubstitutedOuterMost[I] = Arg; - else - SubstitutedOuterMost.push_back(Arg); - } + if (I < SubstitutedOuterMost.size()) + SubstitutedOuterMost[I] = Arg; + else + SubstitutedOuterMost.push_back(Arg); + } MLTAL.replaceOutermostTemplateArguments( const_cast(Constraint.getConstraintDecl()), SubstitutedOuterMost); @@ -681,7 +689,7 @@ static bool calculateConstraintSatisfaction( Ok = calculateConstraintSatisfaction(S, Constraint.getRHS(), Template, TemplateNameLoc, MLTAL, Satisfaction, PackSubstitutionIndex); - if(Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors) + if (Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors) Satisfaction.Details.erase(Satisfaction.Details.begin() + EffectiveDetailEndIndex, Satisfaction.Details.end()); return Ok; @@ -1574,9 +1582,9 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N, /*OnlyDeduced=*/false, /*Depth=*/0, OccurringIndices); } else if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) { - auto Args = static_cast(N) - .getConceptId() - ->getTemplateArgsAsWritten(); + auto *Args = static_cast(N) + .getConceptId() + ->getTemplateArgsAsWritten(); if (Args) S.MarkUsedTemplateParameters(Args->arguments(), /*Depth=*/0, OccurringIndices); @@ -1613,12 +1621,25 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N, if (S.SubstTemplateArgumentsInParameterMapping(N.getParameterMapping(), MLTAL, SubstArgs)) return true; + // Sema::CheckTemplateArgumentInfo CTAI; + // auto *TD = + // const_cast(cast(N.getConstraintDecl())); + // if (S.CheckTemplateArgumentList(TD, TD->getLocation(), SubstArgs, + // /*DefaultArguments=*/{}, + // /*PartialTemplateArgs=*/true, CTAI)) + // return true; TemplateArgumentLoc *TempArgs = new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; + // for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) + // TempArgs[I] = S.getTrivialTemplateArgumentLoc(CTAI.SugaredConverted[I], + // QualType(), SourceLocation()); llvm::copy(SubstArgs.arguments(), TempArgs); N.updateParameterMapping( N.mappingOccurenceList(), MutableArrayRef(TempArgs, SubstArgs.size())); + // N.updateParameterMapping(N.mappingOccurenceList(), + // MutableArrayRef( + // TempArgs, CTAI.SugaredConverted.size())); return false; } @@ -1627,12 +1648,10 @@ substituteParameterMappings(Sema &S, ConceptIdConstraint &N, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten) { - { - if (N.getConstraintDecl()) { - substituteParameterMappings( - S, static_cast(N), MLTAL, - ArgsAsWritten); - } + if (N.getConstraintDecl()) { + substituteParameterMappings( + S, static_cast(N), MLTAL, + ArgsAsWritten); } return substituteParameterMappings(S, N.getNormalizedConstraint(), MLTAL, ArgsAsWritten); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8cc73b09c3fac..e215623dd93b4 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5884,6 +5884,17 @@ bool Sema::CheckTemplateArgumentList( return true; } + // For constraint parameter mapping, we have already built a pack in + // TransformTemplateArguments + // if (inParameterMappingSubstitution()) { + // llvm::copy(SugaredArgumentPack, std::back_inserter(CTAI.SugaredConverted)); + // SugaredArgumentPack.clear(); + // llvm::copy(CanonicalArgumentPack, std::back_inserter(CTAI.CanonicalConverted)); + // CanonicalArgumentPack.clear(); + // ++Param; + // continue; + // } + CTAI.SugaredConverted.push_back( TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); SugaredArgumentPack.clear(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c9bd2c5f340d0..23ee442b4f72a 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6974,10 +6974,13 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, break; case Type::UnaryTransform: - if (!OnlyDeduced) - MarkUsedTemplateParameters(Ctx, - cast(T)->getUnderlyingType(), - OnlyDeduced, Depth, Used); + if (!OnlyDeduced) { + auto *UTT = cast(T); + auto Next = UTT->getUnderlyingType(); + if (Next.isNull()) + Next = UTT->getBaseType(); + MarkUsedTemplateParameters(Ctx, Next, OnlyDeduced, Depth, Used); + } break; case Type::PackExpansion: diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 758b243bd537f..07aa76506194c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1521,7 +1521,10 @@ class TemplateInstantiator : public TreeTransform { } bool ShouldPreserveTemplateArgumentsPacks() const { - return PreserveArgumentPacks; + // This is disabled temporarily. + // We need to figure out a way to correctly handle packs outside of + // CheckTemplateArguments + return false && PreserveArgumentPacks; } TemplateArgument @@ -2233,8 +2236,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, if (Arg.getKind() != TemplateArgument::Expression) { assert(SemaRef.inParameterMappingSubstitution()); // FIXME: SourceLocation()? - ExprResult E = SemaRef.BuildExpressionFromNonTypeTemplateArgument( - Arg, SourceLocation()); + ExprResult E = SemaRef.BuildExpressionFromNonTypeTemplateArgument(Arg, SourceLocation()); if (E.isInvalid()) return E; Arg = TemplateArgument(E.get(), /*IsCanonical=*/false); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 968275e322f41..e44b6086df466 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6987,11 +6987,11 @@ QualType TreeTransform::TransformUnaryTransformType( TypeLocBuilder &TLB, UnaryTransformTypeLoc TL) { QualType Result = TL.getType(); + TypeSourceInfo *NewBaseTSI = TL.getUnderlyingTInfo(); if (Result->isDependentType()) { const UnaryTransformType *T = TL.getTypePtr(); - TypeSourceInfo *NewBaseTSI = - getDerived().TransformType(TL.getUnderlyingTInfo()); + NewBaseTSI = getDerived().TransformType(TL.getUnderlyingTInfo()); if (!NewBaseTSI) return QualType(); QualType NewBase = NewBaseTSI->getType(); @@ -7006,7 +7006,7 @@ QualType TreeTransform::TransformUnaryTransformType( UnaryTransformTypeLoc NewTL = TLB.push(Result); NewTL.setKWLoc(TL.getKWLoc()); NewTL.setParensRange(TL.getParensRange()); - NewTL.setUnderlyingTInfo(TL.getUnderlyingTInfo()); + NewTL.setUnderlyingTInfo(NewBaseTSI); return Result; } From ddc280365c045e26430aaaaf245ea37a2d077cf6 Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Mon, 16 Jun 2025 19:18:17 +0800 Subject: [PATCH 2/2] Fix more ByteCode tests Only 5 tests left now: Failed Tests (5): Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: Modules/pr62943.cppm Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/instantiate-template-argument.cpp --- clang/include/clang/Sema/Sema.h | 9 +- clang/include/clang/Sema/SemaConcept.h | 23 +++-- clang/lib/Sema/SemaConcept.cpp | 92 ++++++++++++------- clang/lib/Sema/SemaTemplate.cpp | 16 +++- clang/lib/Sema/SemaTemplateDeduction.cpp | 1 + clang/lib/Sema/SemaTemplateInstantiate.cpp | 15 +-- .../instantiate-template-argument.cpp | 1 + 7 files changed, 104 insertions(+), 53 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 32febc52ada49..5fa0da65285e5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12065,6 +12065,13 @@ class Sema final : public SemaBase { bool UpdateArgsWithConversions = true, bool *ConstraintsNotSatisfied = nullptr); + bool CheckTemplateArgumentList( + TemplateDecl *Template, TemplateParameterList *Params, + SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, + const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, + CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true, + bool *ConstraintsNotSatisfied = nullptr); + bool CheckTemplateTypeArgument( TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, SmallVectorImpl &SugaredConverted, @@ -13402,7 +13409,7 @@ class Sema final : public SemaBase { TemplateArgumentListInfo &Outputs); bool SubstTemplateArgumentsInParameterMapping( - ArrayRef Args, + ArrayRef Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out); diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index 2f5be9d0b0325..29759a730863f 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -69,6 +69,7 @@ struct NormalizedConstraint { unsigned PackSubstitutionIndex : 26; llvm::SmallBitVector Indexes; TemplateArgumentLoc *Args; + TemplateParameterList *ParamList; ExprOrConcept ConstraintExpr; const NamedDecl *ConstraintDecl; }; @@ -81,6 +82,7 @@ struct NormalizedConstraint { unsigned Placeholder : 26; OccurenceList Indexes; TemplateArgumentLoc *Args; + TemplateParameterList *ParamList; const Expr *Pattern; NormalizedConstraint *Constraint; }; @@ -118,6 +120,7 @@ struct NormalizedConstraint { PackIndex.toInternalRepresentation(), /*Indexes=*/{}, /*Args=*/nullptr, + /*ParamList=*/nullptr, ConstraintExpr, ConstraintDecl} {} @@ -128,6 +131,7 @@ struct NormalizedConstraint { /*Placeholder=*/0, /*Indexes=*/{}, /*Args=*/nullptr, + /*ParamList=*/nullptr, Pattern, Constraint} {} @@ -138,7 +142,8 @@ struct NormalizedConstraint { : ConceptId{{llvm::to_underlying(ConstraintKind::ConceptId), /*Placeholder=*/0, PackIndex.toInternalRepresentation(), /*Indexes=*/{}, - /*Args=*/nullptr, ConceptId, ConstraintDecl}, + /*Args=*/nullptr, /*ParamList=*/nullptr, ConceptId, + ConstraintDecl}, SubConstraint} {} NormalizedConstraint(NormalizedConstraint *LHS, CompoundConstraintKind CCK, @@ -160,15 +165,18 @@ struct NormalizedConstraint { return {Atomic.Args, Atomic.Indexes.count()}; } - void InitParameterMapping(TemplateParameterList *TemplateParams, const Expr *, - const ASTTemplateArgumentListInfo *ArgsAsWritten); + TemplateParameterList *getUsedTemplateParamList() const { + return Atomic.ParamList; + } void updateParameterMapping(OccurenceList Indexes, - llvm::MutableArrayRef Args) { + llvm::MutableArrayRef Args, + TemplateParameterList *ParamList) { assert(getKind() != ConstraintKind::Compound); assert(Indexes.count() == Args.size()); Atomic.Indexes = Indexes; Atomic.Args = Args.data(); + Atomic.ParamList = ParamList; } bool hasMatchingParameterMapping(ASTContext &C, @@ -283,6 +291,7 @@ class NormalizedConstraintWithParamMapping : public NormalizedConstraint { using NormalizedConstraint::hasParameterMapping; using NormalizedConstraint::mappingOccurenceList; using NormalizedConstraint::updateParameterMapping; + using NormalizedConstraint::getUsedTemplateParamList; const NamedDecl *getConstraintDecl() const { return Atomic.ConstraintDecl; } @@ -307,12 +316,6 @@ class AtomicConstraint : public NormalizedConstraintWithParamMapping { const Expr *getConstraintExpr() const { return cast(Atomic.ConstraintExpr); } - - void InitParameterMapping(const ASTTemplateArgumentListInfo *ArgsAsWritten) { - NormalizedConstraint::InitParameterMapping( - cast(Atomic.ConstraintDecl)->getTemplateParameters(), - getConstraintExpr(), ArgsAsWritten); - } }; class FoldExpandedConstraint : public NormalizedConstraint { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a7a4c87e3d696..232003f256ee7 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -377,16 +377,18 @@ SubstitutionInTemplateArguments( ? Constraint.getPackSubstitutionIndex() : PackSubstitutionIndex); if (S.SubstTemplateArgumentsInParameterMapping( - Constraint.getParameterMapping(), MLTAL, SubstArgs) || + Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL, + SubstArgs) || Trap.hasErrorOccurred()) return std::nullopt; - // Sema::CheckTemplateArgumentInfo CTAI; - // auto *TD = const_cast( - // cast(Constraint.getConstraintDecl())); - // if (S.CheckTemplateArgumentList(TD, TD->getLocation(), SubstArgs, - // /*DefaultArguments=*/{}, - // /*PartialTemplateArgs=*/true, CTAI)) - // return std::nullopt; + Sema::CheckTemplateArgumentInfo CTAI; + auto *TD = const_cast( + cast(Constraint.getConstraintDecl())); + if (S.CheckTemplateArgumentList(TD, Constraint.getUsedTemplateParamList(), + TD->getLocation(), SubstArgs, + /*DefaultArguments=*/{}, + /*PartialTemplateArgs=*/false, CTAI)) + return std::nullopt; NormalizedConstraint::OccurenceList Used = Constraint.mappingOccurenceList(); SubstitutedOuterMost = @@ -396,8 +398,10 @@ SubstitutionInTemplateArguments( if (Used[I]) // SubstitutedOuterMost[I].dump(); // SubstArgs[MappedIndex].getArgument().dump(); + // Arg = S.Context.getCanonicalTemplateArgument( + // SubstArgs[MappedIndex++].getArgument()); Arg = S.Context.getCanonicalTemplateArgument( - SubstArgs[MappedIndex++].getArgument()); + CTAI.SugaredConverted[MappedIndex++]); if (I < SubstitutedOuterMost.size()) SubstitutedOuterMost[I] = Arg; else @@ -1591,17 +1595,28 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N, } TemplateArgumentLoc *TempArgs = new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; + llvm::SmallVector UsedParams; for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) { SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I ? ArgsAsWritten->arguments()[I].getLocation() : SourceLocation(); - if (OccurringIndices[I]) - new (&(TempArgs)[J++]) TemplateArgumentLoc( - S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I], Loc)); + if (OccurringIndices[I]) { + NamedDecl *Param = TemplateParams->begin()[I]; + new (&(TempArgs)[J]) + TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(Param, Loc)); + UsedParams.push_back(Param); + J++; + } } + auto *UsedList = TemplateParameterList::Create( + S.Context, TemplateParams->getTemplateLoc(), + TemplateParams->getLAngleLoc(), UsedParams, + /*RAngleLoc=*/SourceLocation(), + /*RequiresClause=*/nullptr); N.updateParameterMapping(OccurringIndices, MutableArrayRef{ - TempArgs, OccurringIndices.count()}); + TempArgs, OccurringIndices.count()}, + UsedList); } SourceLocation InstLocBegin = ArgsAsWritten->arguments().empty() @@ -1618,28 +1633,39 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N, {InstLocBegin, InstLocEnd}); if (Inst.isInvalid()) return true; - if (S.SubstTemplateArgumentsInParameterMapping(N.getParameterMapping(), MLTAL, - SubstArgs)) + // TransformTemplateArguments is unable to preserve the source location of a + // pack. The SourceLocation is necessary for the instantiation location. + // FIXME: The BaseLoc will be used as the location of the pack expansion, + // which is wrong. + if (S.SubstTemplateArgumentsInParameterMapping( + N.getParameterMapping(), N.getBeginLoc(), MLTAL, SubstArgs)) + return true; + Sema::CheckTemplateArgumentInfo CTAI; + auto *TD = + const_cast(cast(N.getConstraintDecl())); + if (S.CheckTemplateArgumentList(TD, N.getUsedTemplateParamList(), + TD->getLocation(), SubstArgs, + /*DefaultArguments=*/{}, + /*PartialTemplateArgs=*/false, CTAI)) return true; - // Sema::CheckTemplateArgumentInfo CTAI; - // auto *TD = - // const_cast(cast(N.getConstraintDecl())); - // if (S.CheckTemplateArgumentList(TD, TD->getLocation(), SubstArgs, - // /*DefaultArguments=*/{}, - // /*PartialTemplateArgs=*/true, CTAI)) - // return true; TemplateArgumentLoc *TempArgs = - new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; - // for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) - // TempArgs[I] = S.getTrivialTemplateArgumentLoc(CTAI.SugaredConverted[I], - // QualType(), SourceLocation()); - llvm::copy(SubstArgs.arguments(), TempArgs); - N.updateParameterMapping( - N.mappingOccurenceList(), - MutableArrayRef(TempArgs, SubstArgs.size())); - // N.updateParameterMapping(N.mappingOccurenceList(), - // MutableArrayRef( - // TempArgs, CTAI.SugaredConverted.size())); + new (S.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()]; + for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) { + SourceLocation Loc; + // If this is an empty pack, we have no corresponding SubstArgs. + if (I < SubstArgs.size()) + Loc = SubstArgs.arguments()[I].getLocation(); + TempArgs[I] = S.getTrivialTemplateArgumentLoc(CTAI.SugaredConverted[I], + QualType(), Loc); + } + // llvm::copy(SubstArgs.arguments(), TempArgs); + // N.updateParameterMapping( + // N.mappingOccurenceList(), + // MutableArrayRef(TempArgs, SubstArgs.size())); + N.updateParameterMapping(N.mappingOccurenceList(), + MutableArrayRef( + TempArgs, CTAI.SugaredConverted.size()), + N.getUsedTemplateParamList()); return false; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e215623dd93b4..b7c463d1c3b21 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5682,6 +5682,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; @@ -5691,8 +5705,6 @@ bool Sema::CheckTemplateArgumentList( // template. TemplateArgumentListInfo NewArgs = TemplateArgs; - TemplateParameterList *Params = GetTemplateParameterList(Template); - SourceLocation RAngleLoc = NewArgs.getRAngleLoc(); // C++23 [temp.arg.general]p1: diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 23ee442b4f72a..4d5329dc3f03f 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6634,6 +6634,7 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor { if (auto *NTTP = dyn_cast(E->getDecl())) if (NTTP->getDepth() == Depth) Used[NTTP->getIndex()] = true; + DynamicRecursiveASTVisitor::TraverseType(E->getType()); return true; } }; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 07aa76506194c..3d9d5aff690b1 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1421,8 +1421,9 @@ class TemplateInstantiator : public TreeTransform { } ForParameterMappingSubstitution; TemplateInstantiator(ForParameterMappingSubstitution_t, Sema &SemaRef, + SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs) - : inherited(SemaRef), TemplateArgs(TemplateArgs), + : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), BailOutOnIncomplete(false), PreserveArgumentPacks(true) {} void setEvaluateConstraints(bool B) { EvaluateConstraints = B; } @@ -2235,11 +2236,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, Arg = getTemplateArgumentPackPatternForRewrite(Arg); if (Arg.getKind() != TemplateArgument::Expression) { assert(SemaRef.inParameterMappingSubstitution()); - // FIXME: SourceLocation()? - ExprResult E = SemaRef.BuildExpressionFromNonTypeTemplateArgument(Arg, SourceLocation()); - if (E.isInvalid()) + ExprResult Expr = SemaRef.BuildExpressionFromNonTypeTemplateArgument( + Arg, E->getLocation()); + if (Expr.isInvalid()) return E; - Arg = TemplateArgument(E.get(), /*IsCanonical=*/false); + Arg = TemplateArgument(Expr.get(), /*IsCanonical=*/false); } assert(Arg.getKind() == TemplateArgument::Expression && "unexpected nontype template argument kind in template rewrite"); @@ -4508,11 +4509,11 @@ bool Sema::SubstTemplateArguments( } bool Sema::SubstTemplateArgumentsInParameterMapping( - ArrayRef Args, + ArrayRef Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out) { TemplateInstantiator Instantiator( - TemplateInstantiator::ForParameterMappingSubstitution, *this, + TemplateInstantiator::ForParameterMappingSubstitution, *this, BaseLoc, TemplateArgs); return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(), Out); } diff --git a/clang/test/SemaTemplate/instantiate-template-argument.cpp b/clang/test/SemaTemplate/instantiate-template-argument.cpp index 43d5d00c8cb20..f65642b401bcd 100644 --- a/clang/test/SemaTemplate/instantiate-template-argument.cpp +++ b/clang/test/SemaTemplate/instantiate-template-argument.cpp @@ -17,6 +17,7 @@ template constexpr int foo() requires C1<1, X> && true { return 2; } // sizeof(U) >= 4 [U = X (decltype(1))] +// GCC rejects it: https://godbolt.org/z/MWG756K8c static_assert(foo<'a'>() == 2); template