From d0739e110d5a356fd0280ed867c99b6da265ff4b Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Mon, 15 Sep 2025 14:07:26 +0800 Subject: [PATCH] Use ordinary substitution for parameter mapping --- clang/lib/AST/TemplateBase.cpp | 7 ++----- clang/lib/Sema/SemaConcept.cpp | 3 --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 21 +++++++++++---------- clang/test/SemaTemplate/concepts.cpp | 8 ++++++++ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index d8d6a4f3b08fe..76f96fb8c5dcc 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -606,11 +606,8 @@ TemplateArgumentLoc::TemplateArgumentLoc(ASTContext &Ctx, LocInfo(Ctx, TemplateKWLoc, QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); - // We can't assume QualifierLoc.getNestedNameSpecifier() == - // Argument.getAsTemplateOrTemplatePattern().getQualifier() at this point, - // because in template rewriting, we may substitute a DependentTemplateName - // (which has a NNSLoc) into a template template parameter (which - // doesn't have a NNSLoc). + assert(QualifierLoc.getNestedNameSpecifier() == + Argument.getAsTemplateOrTemplatePattern().getQualifier()); } NestedNameSpecifierLoc TemplateArgumentLoc::getTemplateQualifierLoc() const { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index cf063a3788649..8c7176008f1db 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -2173,9 +2173,6 @@ bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) { /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); - // Don't build Subst* nodes to model lambda expressions. - // The transform of Subst* is oblivious to the lambda type. - MLTAL.setKind(TemplateSubstitutionKind::Rewrite); return SubstituteParameterMappings( SemaRef, &MLTAL, CSE->getTemplateArgsAsWritten(), InFoldExpr) .substitute(CC.getNormalizedConstraint()); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index ed3dddf8c6367..35ce977582f5e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2268,15 +2268,6 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, // We're rewriting the template parameter as a reference to another // template parameter. Arg = getTemplateArgumentPackPatternForRewrite(Arg); - if (Arg.getKind() != TemplateArgument::Expression) { - assert(SemaRef.inParameterMappingSubstitution() || - SemaRef.inConstraintSubstitution()); - ExprResult Expr = SemaRef.BuildExpressionFromNonTypeTemplateArgument( - Arg, E->getLocation()); - if (Expr.isInvalid()) - return E; - Arg = TemplateArgument(Expr.get(), /*IsCanonical=*/false); - } assert(Arg.getKind() == TemplateArgument::Expression && "unexpected nontype template argument kind in template rewrite"); // FIXME: This can lead to the same subexpression appearing multiple times @@ -2498,11 +2489,21 @@ ExprResult TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { ExprResult SubstReplacement = E->getReplacement(); + QualType ParamType = E->getParameterType(getSema().Context); + bool WasDependentLambda = false; + if (auto *RT = dyn_cast(ParamType); + RT && RT->getAsCXXRecordDecl()) + WasDependentLambda = RT->getAsCXXRecordDecl()->isDependentLambda(); if (!isa(SubstReplacement.get())) SubstReplacement = TransformExpr(E->getReplacement()); if (SubstReplacement.isInvalid()) return true; - QualType SubstType = TransformType(E->getParameterType(getSema().Context)); + // FIXME: This transform cannot find the instantiated lambda declaration + // because lambdas are instantiated in a unique scope. + QualType SubstType = + WasDependentLambda + ? SubstReplacement.get()->getType().getUnqualifiedType() + : TransformType(ParamType); if (SubstType.isNull()) return true; // The type may have been previously dependent and not now, which means we diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 5ff747cdb70c8..ab1518bf3cf99 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1287,4 +1287,12 @@ struct __completion_domain_or_none_ : __mdefer_<__mtransform<>> {}; } +namespace case2 { + +template concept C = Q.template operator()

(); +template concept E = C<[]{ return false; }, P>; +static_assert(!E); + +} + }