[all-commits] [llvm/llvm-project] 3669d2: [Clang] Fix ICE in constraint normalization when s...

I via All-commits all-commits at lists.llvm.org
Wed Mar 11 04:52:52 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 3669d2e4dc2bf21b646a638c6209dea86f94e3d8
      https://github.com/llvm/llvm-project/commit/3669d2e4dc2bf21b646a638c6209dea86f94e3d8
  Author: I <1091761+wx257osn2 at users.noreply.github.com>
  Date:   2026-03-11 (Wed, 11 Mar 2026)

  Changed paths:
    M clang/docs/ReleaseNotes.rst
    M clang/lib/Sema/SemaTemplateInstantiate.cpp
    M clang/test/SemaCXX/cxx2c-template-template-param.cpp

  Log Message:
  -----------
  [Clang] Fix ICE in constraint normalization when substituting concept template parameters (#184406)

23341c3d139b889e8c46867f8d704ab3c22b51f8 introduced
`SubstituteConceptsInConstraintExpression` to substitute non-dependent
concept template arguments into a concept's constraint expression during
normalization, as part of the P2841R7 implementation
([temp.constr.normal]/1.4).

The `ConstraintExprTransformer` added in that commit overrides
`TransformTemplateArgument` to only transform concept-related arguments
and preserve all others. However, `TransformUnresolvedLookupExpr` called
`Sema::SubstExpr`, which creates a separate `TemplateInstantiator` that
performs full substitution bypassing the selective override entirely.

This caused all template parameters in the constraint expression to be
substituted using the concept's MLTAL. For example, given:

```cpp
template <class A, template <typename...> concept C>
concept maybe_cvref = C<std::remove_cvref_t<A>>;

template <maybe_cvref<std::integral> T, typename U>
auto f0(T&& t, U&& u);  // fortunately it passes on Clang 22 due to
                        // maybe_cvref's first template parameter (A) has
                        // same kind (type) of f0's first one (T)

template <typename T, maybe_cvref<std::integral> U>
auto f1(T&& t, U&& u);  // it causes ICE on Clang 22
```

`C<std::remove_cvref_t<A>>` was fully substituted into
`std::integral<std::remove_cvref_t<U>>`, where `U` refers to `f1`'s
parameter at depth 0, index 1. When `SubstituteParameterMappings` later
applied the concept's MLTAL, it resolved `U`
(`clang::TemplateArgument::Type`) at (0,1) to `std::integral`
(`clang::TemplateArgument::Template`) instead of the intended type
parameter, causing an ICE due to argument kind mismatch.

Fix this by resolving the concept declaration directly from the MLTAL
and routing template arguments through `ConstraintExprTransformer`'s own
`TransformTemplateArguments`, preserving non-concept arguments
correctly.



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list