From 04b10596fe2fec1aa6652c15fd389087a78a235f Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 2 Mar 2021 07:38:37 -0500 Subject: [PATCH] c++: Some preparatory type canonicalization fixes The patches that follow revealed some latent type canonicalization issues during normalization/satisfaction, due to normalization of some constraint-expressions now being performed in different contexts and more frequently (since the normalization caches get frequently emptied in a checking compiler). The issues are: 1. In tsubst_parameter_mapping, we canonicalize the arguments of a substituted TYPE_ARGUMENT_PACK only if the argument we started with wasn't a TYPE_ARGUMENT_PACK. We should canonicalize a substituted TYPE_ARGUMENT_PACK regardless of what we started with. 2. We currently set DECL_CONTEXT and CONSTRAINT_VAR_P on each of the parameters introduced in a requires expression _after_ we're done processing the requirements. But meanwhile we may have already built and computed the canonical form of a type that uses one of these PARM_DECLs (as say an operand to decltype). But the canonical form depends on the result of cp_tree_equal, which in turn depends on the value of CONSTRAINT_VAR_P and DECL_CONTEXT. So we must set these fields earlier, before processing requirements. 3. In do_auto_deduction, we use the result of finish_decltype_type later as a template argument, so we should canonicalize the result too. (While we're here, we should pass 'complain' to finish_decltype_type, which fixes the testcase auto1.C below.) gcc/cp/ChangeLog: * constraint.cc (tsubst_parameter_mapping): Canonicalize the arguments of a substituted TYPE_ARGUMENT_PACK even if we've started with a TYPE_ARGUMENT_PACK. (finish_requires_expr): Don't set DECL_CONTEXT and CONSTRAINT_VAR_P on each of the introduced parameters here. * parser.c (cp_parser_requirement_parameter_list): Instead set these fields earlier, here. * pt.c (do_auto_deduction): Canonicalize the result of do_auto_deduction. Pass 'complain' to finish_decltype_type. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/auto1.C: New test. --- gcc/cp/constraint.cc | 25 ++++++++----------------- gcc/cp/parser.c | 12 ++++++++++++ gcc/cp/pt.c | 8 ++++++-- gcc/testsuite/g++.dg/cpp1z/auto1.C | 13 +++++++++++++ 4 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/auto1.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 3e599fe8c47..39c97986082 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2319,15 +2319,15 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info) new_arg = tsubst_template_arg (arg, args, complain, in_decl); if (TYPE_P (new_arg)) new_arg = canonicalize_type_argument (new_arg, complain); - if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK) + } + if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK) + { + tree pack_args = ARGUMENT_PACK_ARGS (new_arg); + for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++) { - tree pack_args = ARGUMENT_PACK_ARGS (new_arg); - for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++) - { - tree& pack_arg = TREE_VEC_ELT (pack_args, i); - if (TYPE_P (pack_arg)) - pack_arg = canonicalize_type_argument (pack_arg, complain); - } + tree& pack_arg = TREE_VEC_ELT (pack_args, i); + if (TYPE_P (pack_arg)) + pack_arg = canonicalize_type_argument (pack_arg, complain); } } if (new_arg == error_mark_node) @@ -3253,15 +3253,6 @@ evaluate_concept_check (tree check, tsubst_flags_t complain) tree finish_requires_expr (location_t loc, tree parms, tree reqs) { - /* Modify the declared parameters by removing their context - so they don't refer to the enclosing scope and explicitly - indicating that they are constraint variables. */ - for (tree parm = parms; parm; parm = DECL_CHAIN (parm)) - { - DECL_CONTEXT (parm) = NULL_TREE; - CONSTRAINT_VAR_P (parm) = true; - } - /* Build the node. */ tree r = build_min (REQUIRES_EXPR, boolean_type_node, parms, reqs, NULL_TREE); TREE_SIDE_EFFECTS (r) = false; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bb1499ab741..92de144dc87 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28817,6 +28817,18 @@ cp_parser_requirement_parameter_list (cp_parser *parser) if (!parens.require_close (parser)) return error_mark_node; + /* Modify the declared parameters by removing their context + so they don't refer to the enclosing scope and explicitly + indicating that they are constraint variables. */ + for (tree parm = parms; parm; parm = TREE_CHAIN (parm)) + { + if (parm == void_list_node || parm == explicit_void_list_node) + break; + tree decl = TREE_VALUE (parm); + DECL_CONTEXT (decl) = NULL_TREE; + CONSTRAINT_VAR_P (decl) = true; + } + return parms; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6a2c4f372ef..f324f6a1e1b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29517,9 +29517,13 @@ do_auto_deduction (tree type, tree init, tree auto_node, || ((TREE_CODE (init) == COMPONENT_REF || TREE_CODE (init) == SCOPE_REF) && !REF_PARENTHESIZED_P (init))); + tree deduced = finish_decltype_type (init, id, complain); + deduced = canonicalize_type_argument (deduced, complain); + if (deduced == error_mark_node) + return error_mark_node; targs = make_tree_vec (1); - TREE_VEC_ELT (targs, 0) - = finish_decltype_type (init, id, tf_warning_or_error); + TREE_VEC_ELT (targs, 0) = deduced; + /* FIXME: These errors ought to be diagnosed at parse time. */ if (type != auto_node) { if (complain & tf_error) diff --git a/gcc/testsuite/g++.dg/cpp1z/auto1.C b/gcc/testsuite/g++.dg/cpp1z/auto1.C new file mode 100644 index 00000000000..5cc762a386e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/auto1.C @@ -0,0 +1,13 @@ +// Verify that deduction failure of the decltype(auto) template parameter is +// a SFINAE error. +// { dg-do compile { target c++17 } } + +template void f(); +template void f(int); + +template > void g(); +template void g(); + +int main() { + g(); +}