| Issue |
182671
|
| Summary |
error: template template argument 'A' is more constrained than template template parameter 'T'
|
| Labels |
clang:frontend,
regression:19
|
| Assignees |
|
| Reporter |
yijan4845
|
Compiler Explorer: [https://godbolt.org/z/qj7vEx8bq](https://godbolt.org/z/qj7vEx8bq)
This seems to be a regression in clang 19 and the bug is very similar(maybe duplicate) to [162023](https://github.com/llvm/llvm-project/issues/162023).
## Vulnerable code location(s)
- `clang/lib/Sema/SemaConcept.cpp`, lines 216–279 — `AdjustConstraints` class only overrides `TransformTemplateTypeParmType`; no override exists for `NonTypeTemplateParmDecl` or `TemplateTemplateParmDecl` depth adjustment.
- `clang/lib/Sema/SemaConcept.cpp`, lines 2538–2543 — Call site where `AdjustConstraints` is applied before `IsAtLeastAsConstrained` comparison.
## Vulnerable code analysis
`AdjustConstraints` is a `TreeTransform` subclass used to shift template parameter depths when comparing constraints between declarations at different nesting levels. It only overrides `TransformTemplateTypeParmType` (adjusting type parameter depths by `TemplateDepth`). Non-type template parameters (`NonTypeTemplateParmDecl`) and template template parameters (`TemplateTemplateParmDecl`) are never adjusted — the base `TreeTransform::TransformDecl` returns them unchanged, and `TransformDeclRefExpr` short-circuits when the decl pointer hasn't changed.
This causes a depth mismatch when `IsAtLeastAsConstrained` compares a file-scope template (depth 0) against a `TemplateTemplateParmDecl` nested inside another template (depth > 0). The constraint expressions end up with inconsistent parameter depths, so subsumption checking fails and Clang incorrectly reports "template template argument 'A' is more constrained than template template parameter 'T'".
The equivalent code using type parameters instead of NTTPs compiles correctly, confirming the bug is specific to the missing depth adjustment for non-type parameters. GCC 11.4+ accepts both variants.
This is the PoC and it compiles successfully in GCC:
```cpp
template<int N> concept Positive = N > 0;
template<int N> requires Positive<N> struct A {};
template<template<int N> requires Positive<N> typename T> struct Wrapper {};
using X = Wrapper<A>;
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs