Author: Younan Zhang
Date: 2026-07-10T20:17:38+08:00
New Revision: f114842d9eab1e53bf25d6e7af7c34001b3b22a4

URL: 
https://github.com/llvm/llvm-project/commit/f114842d9eab1e53bf25d6e7af7c34001b3b22a4
DIFF: 
https://github.com/llvm/llvm-project/commit/f114842d9eab1e53bf25d6e7af7c34001b3b22a4.diff

LOG: [Clang] Fix a bug in parameter mapping substitution (#208663)

When building parameter mapping, both substitution and
CheckTemplateArguments were marked as ParameterMappingSubstitution,
while CheckTemplateArguments could also substitute into default
arguments eagerly such that some type constraints were transformed too
early.

It turned out that we don't have to enforce that rebuild in
SubstTypeConstraint, so this reverts that behavior.

Fixes https://github.com/llvm/llvm-project/issues/197597

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaTemplateInstantiate.cpp
    clang/test/SemaTemplate/concepts-no-early-substitution.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 449a3792eb4ba..d0a70ac2fc6fb 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -839,6 +839,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Fixed a preprocessor assertion failure triggered when parsing an invalid 
template-id starting with `::template operator`. (#GH186582)
 - Fixed a crash when a function template is defined as a non-template friend 
with a global scope qualifier. (#GH185341)
 - Clang now rejects constant template parameters with block pointer types, 
since these are not implemented anyway and would lead to crashes. (#GH189247)
+- Fixed some concept bugs introduced in Clang 22 (#GH197597)
 - Clang no longer reject call expressions whose type is a not-yet-deduced auto 
type. (#GH207565)
 - Fixed a crash on error recovery when dealing with invalid templates. 
(#GH183075)
 - Fixed a crash when instantiating `requires` expressions involving 
substitution failures in C++ concepts. (#GH176402)

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 4ba9414cfcdad..990e52eb27d39 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3078,7 +3078,7 @@ bool Sema::SubstTypeConstraint(
   const ASTTemplateArgumentListInfo *TemplArgInfo =
       TC->getTemplateArgsAsWritten();
 
-  if (!EvaluateConstraints && !inParameterMappingSubstitution()) {
+  if (!EvaluateConstraints) {
     UnsignedOrNone Index = TC->getArgPackSubstIndex();
     bool ContainsUnexpandedPack =
         TemplArgInfo &&

diff  --git a/clang/test/SemaTemplate/concepts-no-early-substitution.cpp 
b/clang/test/SemaTemplate/concepts-no-early-substitution.cpp
index 9e576f16a263b..37f8b9485c3e2 100644
--- a/clang/test/SemaTemplate/concepts-no-early-substitution.cpp
+++ b/clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -31,3 +31,61 @@ struct View {
 
 struct Subrange : View<void> {};
 static_assert(Concept<Subrange>);
+
+namespace GH197597 {
+
+template <class> struct iterator_traits;
+template <class _Tp> struct iterator_traits<_Tp *> {
+  typedef _Tp value_type;
+};
+template <class _Ip>
+concept contiguous_iterator =
+    requires { typename iterator_traits<_Ip>::value_type; };
+template <class _CharT> class basic_format_context;
+template <class _Tp, class _Context,
+          class = _Context::template formatter_type<_Tp>>
+concept __formattable_with = requires(_Context __fc) { __fc; };
+template <class _Tp, class _CharT>
+concept formattable = __formattable_with<_Tp, basic_format_context<_CharT>>;
+template <class _CharT> struct __retarget_buffer {
+  struct __iterator {
+    __retarget_buffer *__buffer_;
+  };
+  template <contiguous_iterator _Iterator> void __transform(_Iterator);
+};
+template <class> struct formatter;
+template <class _Context> struct __basic_format_arg_value {
+  struct __handle {
+    template <class _Tp>
+    __handle(_Tp)
+        : __format_([](_Context &__ctx) {
+            typename _Context::template formatter_type<_Tp>{}.format(__ctx);
+          }) {}
+    void (*__format_)(_Context &);
+  } __handle;
+};
+template <class _Args> struct __format_arg_store {
+  __format_arg_store(_Args __args) {
+    (void)__basic_format_arg_value<basic_format_context<char>>{__args};
+  }
+};
+template <class _CharT> struct basic_format_context {
+  template <class _Tp> using formatter_type = formatter<_Tp>;
+  __retarget_buffer<_CharT>::__iterator out();
+};
+void __transform(auto __out_it) {
+  char __transform___first;
+  __out_it.__buffer_->__transform(&__transform___first);
+}
+struct __formatter_integer {
+  template <class _FormatContext> void format(_FormatContext __ctx) {
+    __transform(__ctx.out());
+  }
+};
+template <> struct formatter<int> : __formatter_integer {};
+template <formattable<char> T> void fmt(T);
+void test() {
+  fmt(0);
+  __format_arg_store<int>{0};
+}
+} // namespace GH197597


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to