[clang] [Clang] Add default arguments to the parameter mapping (PR #192071)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 14 07:46:37 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Corentin Jabot (cor3ntin)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/192071.diff
5 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1-1)
- (modified) clang/include/clang/AST/ASTContext.h (+4)
- (modified) clang/lib/AST/ASTContext.cpp (+2-2)
- (modified) clang/lib/Sema/SemaConcept.cpp (+19)
- (modified) clang/test/SemaTemplate/concepts.cpp (+45)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/192071
More information about the cfe-commits
mailing list