Message ID | 20210208190352.1475602-2-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | [1/4] c++: Avoid building garbage trees from tsubst_requires_expr | expand |
On 2/8/21 2:03 PM, Patrick Palka wrote: > The subsequent patches revealed some latent type canonicalization > issues during normalization and satisfaction: > > 1. In tsubst_parameter_mapping, we're canonicalizing the arguments of a > TYPE_ARGUMENT_PACK only if 'arg' wasn't a TYPE_ARGUMENT_PACK to begin > 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 > computed the canonical form of a type that depends on one of these > PARM_DECLs, which depends on the result of cp_tree_equal, which > depends on CONSTRAINT_VAR_P and DECL_CONTEXT. So we must set these > fields earlier, before processing the 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 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. > > 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 5da8670f0e2..fef10b9661d 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -28779,6 +28779,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 3605b67e424..bceb942e79a 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -29478,9 +29478,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. */ Perhaps in grokdeclarator. The patch is OK. > 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 <class> void f(); > +template <class> void f(int); > + > +template <class T = int, decltype(auto) = &f<T>> void g(); > +template <class = int> void g(); > + > +int main() { > + g(); > +} >
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 5da8670f0e2..fef10b9661d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28779,6 +28779,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 3605b67e424..bceb942e79a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29478,9 +29478,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 <class> void f(); +template <class> void f(int); + +template <class T = int, decltype(auto) = &f<T>> void g(); +template <class = int> void g(); + +int main() { + g(); +}