Message ID | 20230420135633.2447631-2-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | [1/2] c++: make strip_typedefs generalize strip_typedefs_expr | expand |
On 4/20/23 09:56, Patrick Palka wrote: > This patch makes us use a TREE_VEC instead of TREE_LIST to represent the > trailing arguments of a variadic built-in trait. These built-ins are > typically passed a simple pack expansion as the second argument, e.g. > > __is_constructible(T, Ts...) > > so the main benefit of this representation change means that expanding > such an argument list at substitution time is now basically free, since > argument packs are also TREE_VECs and tsubst_template_args makes sure > we reuse this TREE_VEC when expanding such pack expansions. Previously, > we would perform the expansion via tsubst_tree_list which converts the > expanded pack expansion into a TREE_LIST. > > Note, after this patch an empty set of trailing arguments is now > represented as an empty TREE_VEC instead of NULL_TREE, so > TRAIT_TYPE/EXPR_TYPE2 should be empty only for unary traits now. > > (This patch slightly depends on "c++: make strip_typedefs generalize > strip_typedefs_expr". Without it, strip_typedefs <case TRAIT_TYPE> > would need to conditionally dispatch to strip_typedefs_expr for > non-TYPE_P TRAIT_TYPE_TYPE2 since it could now be a TREE_VEC which > only strip_typedefs_expr handles.) > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? OK. > gcc/cp/ChangeLog: > > * constraint.cc (diagnose_trait_expr): Convert a TREE_VEC > of arguments into a TREE_LIST for sake of pretty printing. > * cxx-pretty-print.cc (pp_cxx_trait): Handle TREE_VEC > instead of TREE_LIST of variadic trait arguments. > * method.cc (constructible_expr): Likewise. > (is_xible_helper): Likewise. > * parser.cc (cp_parser_trait): Represent variadic trait > arguments as a TREE_VEC instead of TREE_LIST. > * pt.cc (value_dependent_expression_p): Handle TREE_VEC > instead of TREE_LIST of variadic trait arguments. > * semantics.cc (finish_type_pack_element): Likewise. > (check_trait_type): Likewise. > --- > gcc/cp/constraint.cc | 10 ++++++++++ > gcc/cp/cxx-pretty-print.cc | 6 +++--- > gcc/cp/method.cc | 17 +++++++++-------- > gcc/cp/parser.cc | 10 ++++++---- > gcc/cp/pt.cc | 9 ++++----- > gcc/cp/semantics.cc | 15 +++++++++------ > 6 files changed, 41 insertions(+), 26 deletions(-) > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > index 273d15ab097..dfead28e8c7 100644 > --- a/gcc/cp/constraint.cc > +++ b/gcc/cp/constraint.cc > @@ -3675,6 +3675,16 @@ diagnose_trait_expr (tree expr, tree args) > > tree t1 = TRAIT_EXPR_TYPE1 (expr); > tree t2 = TRAIT_EXPR_TYPE2 (expr); > + if (t2 && TREE_CODE (t2) == TREE_VEC) > + { > + /* Convert the TREE_VEC of arguments into a TREE_LIST, since the > + pretty printer cannot directly print a TREE_VEC but it can a > + TREE_LIST via the E format specifier. */ > + tree list = NULL_TREE; > + for (tree t : tree_vec_range (t2)) > + list = tree_cons (NULL_TREE, t, list); > + t2 = nreverse (list); > + } > switch (TRAIT_EXPR_KIND (expr)) > { > case CPTK_HAS_NOTHROW_ASSIGN: > diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc > index c33919873f1..4cda27f2b30 100644 > --- a/gcc/cp/cxx-pretty-print.cc > +++ b/gcc/cp/cxx-pretty-print.cc > @@ -2640,16 +2640,16 @@ pp_cxx_trait (cxx_pretty_printer *pp, tree t) > } > if (type2) > { > - if (TREE_CODE (type2) != TREE_LIST) > + if (TREE_CODE (type2) != TREE_VEC) > { > pp_cxx_separate_with (pp, ','); > pp->type_id (type2); > } > else > - for (tree arg = type2; arg; arg = TREE_CHAIN (arg)) > + for (tree arg : tree_vec_range (type2)) > { > pp_cxx_separate_with (pp, ','); > - pp->type_id (TREE_VALUE (arg)); > + pp->type_id (arg); > } > } > if (kind == CPTK_TYPE_PACK_ELEMENT) > diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc > index 225ec456143..00eae56eb5b 100644 > --- a/gcc/cp/method.cc > +++ b/gcc/cp/method.cc > @@ -2075,8 +2075,9 @@ constructible_expr (tree to, tree from) > if (!TYPE_REF_P (to)) > to = cp_build_reference_type (to, /*rval*/false); > tree ob = build_stub_object (to); > - for (; from; from = TREE_CHAIN (from)) > - vec_safe_push (args, build_stub_object (TREE_VALUE (from))); > + vec_alloc (args, TREE_VEC_LENGTH (from)); > + for (tree arg : tree_vec_range (from)) > + args->quick_push (build_stub_object (arg)); > expr = build_special_member_call (ob, complete_ctor_identifier, &args, > ctype, LOOKUP_NORMAL, tf_none); > if (expr == error_mark_node) > @@ -2096,9 +2097,9 @@ constructible_expr (tree to, tree from) > } > else > { > - if (from == NULL_TREE) > + const int len = TREE_VEC_LENGTH (from); > + if (len == 0) > return build_value_init (strip_array_types (to), tf_none); > - const int len = list_length (from); > if (len > 1) > { > if (cxx_dialect < cxx20) > @@ -2112,9 +2113,9 @@ constructible_expr (tree to, tree from) > should be true. */ > vec<constructor_elt, va_gc> *v; > vec_alloc (v, len); > - for (tree t = from; t; t = TREE_CHAIN (t)) > + for (tree arg : tree_vec_range (from)) > { > - tree stub = build_stub_object (TREE_VALUE (t)); > + tree stub = build_stub_object (arg); > constructor_elt elt = { NULL_TREE, stub }; > v->quick_push (elt); > } > @@ -2123,7 +2124,7 @@ constructible_expr (tree to, tree from) > CONSTRUCTOR_IS_PAREN_INIT (from) = true; > } > else > - from = build_stub_object (TREE_VALUE (from)); > + from = build_stub_object (TREE_VEC_ELT (from, 0)); > expr = perform_direct_initialization_if_possible (to, from, > /*cast*/false, > tf_none); > @@ -2160,7 +2161,7 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial) > tree expr; > if (code == MODIFY_EXPR) > expr = assignable_expr (to, from); > - else if (trivial && from && TREE_CHAIN (from) > + else if (trivial && TREE_VEC_LENGTH (from) > 1 > && cxx_dialect < cxx20) > return error_mark_node; // only 0- and 1-argument ctors can be trivial > // before C++20 aggregate paren init > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index ee1497b7071..7ecf97b937b 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -11003,9 +11003,8 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > "is not a type"); > return error_mark_node; > } > - type2 = tree_cons (NULL_TREE, elt, type2); > } > - type2 = nreverse (type2); > + type2 = rest; > } > else if (binary) > { > @@ -11021,6 +11020,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > } > else if (variadic) > { > + auto_vec<tree, 4> rest; > while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) > { > cp_lexer_consume_token (parser->lexer); > @@ -11032,9 +11032,11 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > } > if (elt == error_mark_node) > return error_mark_node; > - type2 = tree_cons (NULL_TREE, elt, type2); > + rest.safe_push (elt); > } > - type2 = nreverse (type2); > + type2 = make_tree_vec (rest.length ()); > + for (int i = 0; i < TREE_VEC_LENGTH (type2); ++i) > + TREE_VEC_ELT (type2, i) = rest[i]; > } > > location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index f65f2d58b28..d393c99ba9e 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -28065,19 +28065,18 @@ value_dependent_expression_p (tree expression) > > case TRAIT_EXPR: > { > - tree type2 = TRAIT_EXPR_TYPE2 (expression); > - > if (dependent_type_p (TRAIT_EXPR_TYPE1 (expression))) > return true; > > + tree type2 = TRAIT_EXPR_TYPE2 (expression); > if (!type2) > return false; > > - if (TREE_CODE (type2) != TREE_LIST) > + if (TREE_CODE (type2) != TREE_VEC) > return dependent_type_p (type2); > > - for (; type2; type2 = TREE_CHAIN (type2)) > - if (dependent_type_p (TREE_VALUE (type2))) > + for (tree arg : tree_vec_range (type2)) > + if (dependent_type_p (arg)) > return true; > > return false; > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index a4f30fdac11..9ba316ab3be 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -4490,14 +4490,13 @@ finish_type_pack_element (tree idx, tree types, tsubst_flags_t complain) > error ("%<__type_pack_element%> index is negative"); > return error_mark_node; > } > - tree result = chain_index (val, types); > - if (!result) > + if (val >= TREE_VEC_LENGTH (types)) > { > if (complain & tf_error) > error ("%<__type_pack_element%> index is out of range"); > return error_mark_node; > } > - return TREE_VALUE (result); > + return TREE_VEC_ELT (types, val); > } > > /* Implement the __direct_bases keyword: Return the direct base classes > @@ -12121,9 +12120,13 @@ check_trait_type (tree type, int kind = 1) > if (type == NULL_TREE) > return true; > > - if (TREE_CODE (type) == TREE_LIST) > - return (check_trait_type (TREE_VALUE (type)) > - && check_trait_type (TREE_CHAIN (type))); > + if (TREE_CODE (type) == TREE_VEC) > + { > + for (tree arg : tree_vec_range (type)) > + if (!check_trait_type (arg, kind)) > + return false; > + return true; > + } > > if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) > return true; // Array of unknown bound. Don't care about completeness.
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 273d15ab097..dfead28e8c7 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3675,6 +3675,16 @@ diagnose_trait_expr (tree expr, tree args) tree t1 = TRAIT_EXPR_TYPE1 (expr); tree t2 = TRAIT_EXPR_TYPE2 (expr); + if (t2 && TREE_CODE (t2) == TREE_VEC) + { + /* Convert the TREE_VEC of arguments into a TREE_LIST, since the + pretty printer cannot directly print a TREE_VEC but it can a + TREE_LIST via the E format specifier. */ + tree list = NULL_TREE; + for (tree t : tree_vec_range (t2)) + list = tree_cons (NULL_TREE, t, list); + t2 = nreverse (list); + } switch (TRAIT_EXPR_KIND (expr)) { case CPTK_HAS_NOTHROW_ASSIGN: diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc index c33919873f1..4cda27f2b30 100644 --- a/gcc/cp/cxx-pretty-print.cc +++ b/gcc/cp/cxx-pretty-print.cc @@ -2640,16 +2640,16 @@ pp_cxx_trait (cxx_pretty_printer *pp, tree t) } if (type2) { - if (TREE_CODE (type2) != TREE_LIST) + if (TREE_CODE (type2) != TREE_VEC) { pp_cxx_separate_with (pp, ','); pp->type_id (type2); } else - for (tree arg = type2; arg; arg = TREE_CHAIN (arg)) + for (tree arg : tree_vec_range (type2)) { pp_cxx_separate_with (pp, ','); - pp->type_id (TREE_VALUE (arg)); + pp->type_id (arg); } } if (kind == CPTK_TYPE_PACK_ELEMENT) diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 225ec456143..00eae56eb5b 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -2075,8 +2075,9 @@ constructible_expr (tree to, tree from) if (!TYPE_REF_P (to)) to = cp_build_reference_type (to, /*rval*/false); tree ob = build_stub_object (to); - for (; from; from = TREE_CHAIN (from)) - vec_safe_push (args, build_stub_object (TREE_VALUE (from))); + vec_alloc (args, TREE_VEC_LENGTH (from)); + for (tree arg : tree_vec_range (from)) + args->quick_push (build_stub_object (arg)); expr = build_special_member_call (ob, complete_ctor_identifier, &args, ctype, LOOKUP_NORMAL, tf_none); if (expr == error_mark_node) @@ -2096,9 +2097,9 @@ constructible_expr (tree to, tree from) } else { - if (from == NULL_TREE) + const int len = TREE_VEC_LENGTH (from); + if (len == 0) return build_value_init (strip_array_types (to), tf_none); - const int len = list_length (from); if (len > 1) { if (cxx_dialect < cxx20) @@ -2112,9 +2113,9 @@ constructible_expr (tree to, tree from) should be true. */ vec<constructor_elt, va_gc> *v; vec_alloc (v, len); - for (tree t = from; t; t = TREE_CHAIN (t)) + for (tree arg : tree_vec_range (from)) { - tree stub = build_stub_object (TREE_VALUE (t)); + tree stub = build_stub_object (arg); constructor_elt elt = { NULL_TREE, stub }; v->quick_push (elt); } @@ -2123,7 +2124,7 @@ constructible_expr (tree to, tree from) CONSTRUCTOR_IS_PAREN_INIT (from) = true; } else - from = build_stub_object (TREE_VALUE (from)); + from = build_stub_object (TREE_VEC_ELT (from, 0)); expr = perform_direct_initialization_if_possible (to, from, /*cast*/false, tf_none); @@ -2160,7 +2161,7 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial) tree expr; if (code == MODIFY_EXPR) expr = assignable_expr (to, from); - else if (trivial && from && TREE_CHAIN (from) + else if (trivial && TREE_VEC_LENGTH (from) > 1 && cxx_dialect < cxx20) return error_mark_node; // only 0- and 1-argument ctors can be trivial // before C++20 aggregate paren init diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index ee1497b7071..7ecf97b937b 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11003,9 +11003,8 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) "is not a type"); return error_mark_node; } - type2 = tree_cons (NULL_TREE, elt, type2); } - type2 = nreverse (type2); + type2 = rest; } else if (binary) { @@ -11021,6 +11020,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) } else if (variadic) { + auto_vec<tree, 4> rest; while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) { cp_lexer_consume_token (parser->lexer); @@ -11032,9 +11032,11 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) } if (elt == error_mark_node) return error_mark_node; - type2 = tree_cons (NULL_TREE, elt, type2); + rest.safe_push (elt); } - type2 = nreverse (type2); + type2 = make_tree_vec (rest.length ()); + for (int i = 0; i < TREE_VEC_LENGTH (type2); ++i) + TREE_VEC_ELT (type2, i) = rest[i]; } location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index f65f2d58b28..d393c99ba9e 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -28065,19 +28065,18 @@ value_dependent_expression_p (tree expression) case TRAIT_EXPR: { - tree type2 = TRAIT_EXPR_TYPE2 (expression); - if (dependent_type_p (TRAIT_EXPR_TYPE1 (expression))) return true; + tree type2 = TRAIT_EXPR_TYPE2 (expression); if (!type2) return false; - if (TREE_CODE (type2) != TREE_LIST) + if (TREE_CODE (type2) != TREE_VEC) return dependent_type_p (type2); - for (; type2; type2 = TREE_CHAIN (type2)) - if (dependent_type_p (TREE_VALUE (type2))) + for (tree arg : tree_vec_range (type2)) + if (dependent_type_p (arg)) return true; return false; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index a4f30fdac11..9ba316ab3be 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -4490,14 +4490,13 @@ finish_type_pack_element (tree idx, tree types, tsubst_flags_t complain) error ("%<__type_pack_element%> index is negative"); return error_mark_node; } - tree result = chain_index (val, types); - if (!result) + if (val >= TREE_VEC_LENGTH (types)) { if (complain & tf_error) error ("%<__type_pack_element%> index is out of range"); return error_mark_node; } - return TREE_VALUE (result); + return TREE_VEC_ELT (types, val); } /* Implement the __direct_bases keyword: Return the direct base classes @@ -12121,9 +12120,13 @@ check_trait_type (tree type, int kind = 1) if (type == NULL_TREE) return true; - if (TREE_CODE (type) == TREE_LIST) - return (check_trait_type (TREE_VALUE (type)) - && check_trait_type (TREE_CHAIN (type))); + if (TREE_CODE (type) == TREE_VEC) + { + for (tree arg : tree_vec_range (type)) + if (!check_trait_type (arg, kind)) + return false; + return true; + } if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) return true; // Array of unknown bound. Don't care about completeness.