constrained than the parameter. */
static bool
-is_compatible_template_arg (tree parm, tree arg)
+is_compatible_template_arg (tree parm, tree arg, tree args)
{
tree parm_cons = get_constraints (parm);
{
tree aparms = DECL_INNERMOST_TEMPLATE_PARMS (arg);
new_args = template_parms_level_to_args (aparms);
+ new_args = add_to_template_args (args, new_args);
++processing_template_decl;
parm_cons = tsubst_constraint_info (parm_cons, new_args,
tf_none, NULL_TREE);
// Check that the constraints are compatible before allowing the
// substitution.
if (val != error_mark_node)
- if (!is_compatible_template_arg (parm, arg))
+ if (!is_compatible_template_arg (parm, arg, args))
{
if (in_decl && (complain & tf_error))
{
--- /dev/null
+// PR c++/111485
+// { dg-do compile { target c++20 } }
+
+template<class T> constexpr bool always_true = true;
+
+template<class T> concept C = always_true<T>;
+template<class T> concept D = C<T> || true;
+
+template<template<C> class TT> struct example;
+template<template<D> class UU> using example_t = example<UU>;
+
+template<class T>
+struct A {
+ template<template<C> class TT> struct example;
+
+ template<template<D> class UU> using example_t = example<UU>;
+
+ template<class U>
+ struct B {
+ template<template<D> class UU> using example_t = example<UU>;
+ };
+};
+
+template struct A<int>::B<int>;
--- /dev/null
+// PR c++/111485
+// { dg-do compile { target c++20 } }
+
+template<class T, bool V> constexpr bool always_true = true;
+
+template<class T, bool V> concept C = always_true<T, V>;
+
+template<bool V, template<class T> requires C<T, V> class TT>
+void f();
+
+template<class T> requires C<T, true>
+struct A;
+
+int main() {
+ f<true, A>();
+ f<false, A>(); // { dg-error "no match|constraint mismatch" }
+}