Here the satisfaction cache is conflating the satisfaction value of the two return-type-requirements because the corresponding constrained 'auto's have level 2, but they capture an empty current_template_parms. This ultimately causes the satisfaction cache to think the type constraint doesn't depend on the deduced type of the expression.
When normalizing the constraints on an 'auto', the assumption made by normalize_placeholder_type_constraints is that the level of the 'auto' is one greater than the captured current_template_parms, an assumption which is not holding here. To fix this, this patch adds a dummy level to current_template_parms to match processing_template_decl when parsing a non-templated return-type-requirement. This patch also makes us verify this assumption upon creation of a constrained 'auto'. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/11? PR c++/100946 gcc/cp/ChangeLog: * parser.c (cp_parser_compound_requirement): When parsing a non-templated return-type-requirement, add a dummy level to current_template_parms. * pt.c (make_constrained_placeholder_type): Verify the depth of current_template_parms is consistent with the level of the 'auto'. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-return-req3.C: New test. --- gcc/cp/parser.c | 12 ++++++++++++ gcc/cp/pt.c | 8 ++++++++ gcc/testsuite/g++.dg/cpp2a/concepts-return-req3.C | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-return-req3.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d59a829d0b9..8278a5608ae 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -29181,6 +29181,18 @@ cp_parser_compound_requirement (cp_parser *parser) cp_lexer_consume_token (parser->lexer); cp_token *tok = cp_lexer_peek_token (parser->lexer); + auto ctp = make_temp_override (current_template_parms); + if (!current_template_parms) + { + /* We're parsing a return-type-requirement within a non-templated + requires-expression. Update current_template_parms to agree with + processing_template_decl so that the normalization context that's + captured by the corresponding constrained 'auto' is sensible. */ + gcc_checking_assert (processing_template_decl == 1); + current_template_parms + = build_tree_list (size_int (1), make_tree_vec (0)); + } + bool saved_result_type_constraint_p = parser->in_result_type_constraint_p; parser->in_result_type_constraint_p = true; /* C++20 allows either a type-id or a type-constraint. Parsing diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b0155a9c370..05679b12973 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -28131,6 +28131,14 @@ make_constrained_placeholder_type (tree type, tree con, tree args) expr = build_concept_check (expr, type, args, tf_warning_or_error); --processing_template_decl; + /* Verify the normalization context is consistent with the level of + this 'auto'. */ + if (TEMPLATE_TYPE_LEVEL (type) == 1) + gcc_checking_assert (!current_template_parms); + else + gcc_checking_assert (1 + TMPL_PARMS_DEPTH (current_template_parms) + == TEMPLATE_TYPE_LEVEL (type)); + PLACEHOLDER_TYPE_CONSTRAINTS_INFO (type) = build_tree_list (current_template_parms, expr); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-return-req3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req3.C new file mode 100644 index 00000000000..a546c6457be --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req3.C @@ -0,0 +1,6 @@ +// PR c++/100946 +// { dg-do compile { target c++20 } } + +template<class T> concept C = __is_same(T, int); +static_assert(requires { { 0 } -> C; }); +static_assert(requires { { true } -> C; }); // { dg-error "failed" } -- 2.32.0.rc2