c++: Set the constraints of a class type sooner [PR96229]
In the testcase below, during processing (at parse time) of Y's base class X<Y>, convert_template_argument calls is_compatible_template_arg to check if the template argument Y is no more constrained than the parameter P. But at this point we haven't yet set Y's constraints, so get_normalized_constraints_from_decl yields NULL_TREE as the normal form and caches this result into the normalized_map. We set Y's constraints later in cp_parser_class_specifier_1 but the stale normal form in the normalized_map remains. This ultimately causes us to miss the constraint failure for Y<Z> because according to the cached normal form, Y is not constrained. This patch fixes this issue by moving up the call to associate_classtype_constraints so that we set constraints before we start processing a class's bases. gcc/cp/ChangeLog: PR c++/96229 * parser.c (cp_parser_class_specifier_1): Move call to associate_classtype_constraints from here to ... (cp_parser_class_head): ... here. * pt.c (is_compatible_template_arg): Correct documentation to say "argument is _no_ more constrained than the parameter". gcc/testsuite/ChangeLog: PR c++/96229 * g++.dg/cpp2a/concepts-class2.C: New test.
This commit is contained in:
parent
6caec77e3b
commit
6b1b5c255f
@ -24044,10 +24044,6 @@ cp_parser_class_specifier_1 (cp_parser* parser)
|
||||
= parser->in_unbraced_linkage_specification_p;
|
||||
parser->in_unbraced_linkage_specification_p = false;
|
||||
|
||||
// Associate constraints with the type.
|
||||
if (flag_concepts)
|
||||
type = associate_classtype_constraints (type);
|
||||
|
||||
/* Start the class. */
|
||||
if (nested_name_specifier_p)
|
||||
{
|
||||
@ -24815,6 +24811,10 @@ cp_parser_class_head (cp_parser* parser,
|
||||
fixup_attribute_variants (type);
|
||||
}
|
||||
|
||||
/* Associate constraints with the type. */
|
||||
if (flag_concepts)
|
||||
type = associate_classtype_constraints (type);
|
||||
|
||||
/* We will have entered the scope containing the class; the names of
|
||||
base classes should be looked up in that context. For example:
|
||||
|
||||
|
@ -8127,9 +8127,10 @@ canonicalize_expr_argument (tree arg, tsubst_flags_t complain)
|
||||
return canon;
|
||||
}
|
||||
|
||||
// A template declaration can be substituted for a constrained
|
||||
// template template parameter only when the argument is more
|
||||
// constrained than the parameter.
|
||||
/* A template declaration can be substituted for a constrained
|
||||
template template parameter only when the argument is no more
|
||||
constrained than the parameter. */
|
||||
|
||||
static bool
|
||||
is_compatible_template_arg (tree parm, tree arg)
|
||||
{
|
||||
|
11
gcc/testsuite/g++.dg/cpp2a/concepts-class2.C
Normal file
11
gcc/testsuite/g++.dg/cpp2a/concepts-class2.C
Normal file
@ -0,0 +1,11 @@
|
||||
// PR c++/96229
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template <class T> concept Int = requires { T{0}; };
|
||||
template <template <Int> class P> struct X { };
|
||||
template <Int> struct Y : X<Y> { };
|
||||
struct Z { };
|
||||
struct W { int i; };
|
||||
|
||||
Y<Z> z; // { dg-error "constraint" }
|
||||
Y<W> w;
|
Loading…
Reference in New Issue
Block a user