https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/192071
We were not adding default argument to the parameter mapping as such, two constraint which only differed by the mapping of a parameter only referenced in a default argument were considered identical. Fixes #188640 >From 072f6d7ee17ef7520bb53dcd7f06afad17a78995 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Tue, 14 Apr 2026 16:38:16 +0200 Subject: [PATCH] [Clang] Add default arguments to the parameter mapping. We were not adding default argument to the parameter mapping as such, two constraint which only differed by the mapping of a parameter only referenced in a default argument were considered identical. Fixes #188640 --- clang/docs/ReleaseNotes.rst | 2 +- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 4 +-- clang/lib/Sema/SemaConcept.cpp | 19 ++++++++++++ clang/test/SemaTemplate/concepts.cpp | 45 ++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3e2d287d1eb1f..63c8a8ec19b4e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -386,7 +386,7 @@ Bug Fixes in This Version ------------------------- - Fixed atomic boolean compound assignment; the conversion back to atomic bool would be miscompiled. (#GH33210) - +- Correctly handle default template argument when establishing subsumption. (#GH188640) - Fixed a failed assertion in the preprocessor when ``__has_embed`` parameters are missing parentheses. (#GH175088) - Fix lifetime extension of temporaries in for-range-initializers in templates. (#GH165182) - Fixed a preprocessor crash in ``__has_cpp_attribute`` on incomplete scoped attributes. (#GH178098) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ba1b58489c327..a412ef91ef16d 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3071,6 +3071,10 @@ class ASTContext : public RefCountedBase<ASTContext> { TemplateName getCanonicalTemplateName(TemplateName Name, bool IgnoreDeduced = false) const; + /// Return the default argument of a template parameter, if one exists. + const TemplateArgument * + getDefaultTemplateArgumentOrNone(const NamedDecl *P) const; + /// Determine whether the given template names refer to the same /// template. bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ee7f823b014b2..f73f613a2d35a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7305,8 +7305,8 @@ ASTContext::getNameForTemplate(TemplateName Name, llvm_unreachable("bad template name kind!"); } -static const TemplateArgument * -getDefaultTemplateArgumentOrNone(const NamedDecl *P) { +const TemplateArgument * +ASTContext::getDefaultTemplateArgumentOrNone(const NamedDecl *P) const { auto handleParam = [](auto *TP) -> const TemplateArgument * { if (!TP->hasDefaultArgument()) return nullptr; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 3f04922a5647e..dfab7c919a303 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -2105,6 +2105,25 @@ void SubstituteParameterMappings::buildParameterMapping( SemaRef.MarkUsedTemplateParameters(Args->arguments(), /*Depth=*/0, OccurringIndices); } + + // If a parameter is only referenced in a default template argument, + // we need to add it to the mapping explicitly. + { + llvm::SmallVector<TemplateArgument> DefaultArgs; + for (unsigned I = TemplateParams->getMinRequiredArguments(); + I < TemplateParams->size(); I++) { + const NamedDecl *Param = TemplateParams->getParam(I); + if (Param->isParameterPack()) + break; + const TemplateArgument *Arg = + SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param); + assert(Arg && "expected a default argument"); + DefaultArgs.emplace_back(std::move(*Arg)); + } + SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0, + OccurringIndices); + } + unsigned Size = OccurringIndices.count(); // When the constraint is independent of any template parameters, // we build an empty mapping so that we can distinguish these cases diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index ac80d16b4ccf8..c8b5cbac82f89 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1835,3 +1835,48 @@ namespace GH191016 { }; void test(){ S<int> s; } } + + +namespace GH188640 { + +namespace Ex1 { +template <typename T> constexpr bool CC = true; + +template <typename V, typename U = V> +concept C = CC<U>; + +template <typename T> +constexpr int f() + requires C<T> && C<T *> +{ + return 21; +} + +template <typename T> +void f() + requires C<T>; + +void g() { static_assert(f<void>() == 21); } + +} // namespace Ex1 + +namespace VAR { +template <auto N> constexpr bool CC = true; +template <auto V, auto U = V> +concept C = CC<U>; + +template <auto V> +constexpr int f() + requires C<V> && C<V + 1> +{ + return 42; +} + +template <auto N> +int f() + requires C<N>; + +void g() { static_assert(f<1>() == 42); } +} // namespace VAR + +} // namespace GH188640 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
