]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: use TREE_VEC for trailing args of variadic built-in traits
authorPatrick Palka <ppalka@redhat.com>
Thu, 20 Apr 2023 19:00:06 +0000 (15:00 -0400)
committerPatrick Palka <ppalka@redhat.com>
Thu, 20 Apr 2023 19:00:06 +0000 (15:00 -0400)
This patch makes us use 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...)

and the main benefit of this representation change is that substituting
into this argument list is now basically free since tsubst_template_args
makes sure we reuse the TREE_VEC of the corresponding ARGUMENT_PACK when
expanding such a pack expansion.  In the previous TREE_LIST representation
we would need need to convert the expanded pack expansion into a TREE_LIST
(via tsubst_tree_list).

Note that an empty set of trailing arguments is now represented as an
empty TREE_VEC instead of NULL_TREE, so now TRAIT_TYPE/EXPR_TYPE2 will
be empty only for unary traits.

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 trailing variadic trait arguments.
* method.cc (constructible_expr): Likewise.
(is_xible_helper): Likewise.
* parser.cc (cp_parser_trait): Represent trailing 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 trailing variadic trait arguments.
* semantics.cc (finish_type_pack_element): Likewise.
(check_trait_type): Likewise.

gcc/cp/constraint.cc
gcc/cp/cxx-pretty-print.cc
gcc/cp/method.cc
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/cp/semantics.cc

index 273d15ab0975b15cbf1256285e54939c2758748c..675299aa4cdc319da2623df884b52e2c86b40a1f 100644 (file)
@@ -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 we can't
+        directly print a TREE_VEC but we 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:
index c33919873f1c23ce40439779b4e72d4cd3e27f42..4cda27f2b308721f2d8d7474a13ad9304cb0ab4a 100644 (file)
@@ -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)
index 225ec456143cdf96c041f09ba606f08521cf3699..00eae56eb5be1ecb7f0e623d6d85784ffdcdb69b 100644 (file)
@@ -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
index ee1497b7071a724c2377419bde1e86640da32096..e5f032f2330b629374b553e87366ccd9aae9bdd9 100644 (file)
@@ -10993,8 +10993,8 @@ cp_parser_trait (cp_parser* parser, enum rid keyword)
   if (kind == CPTK_TYPE_PACK_ELEMENT)
     {
       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
-      tree rest = cp_parser_enclosed_template_argument_list (parser);
-      for (tree elt : tree_vec_range (rest))
+      tree trailing = cp_parser_enclosed_template_argument_list (parser);
+      for (tree elt : tree_vec_range (trailing))
        {
          if (!TYPE_P (elt))
            {
@@ -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 = trailing;
     }
   else if (binary)
     {
@@ -11021,6 +11020,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword)
     }
   else if (variadic)
     {
+      auto_vec<tree, 4> trailing;
       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);
+         trailing.safe_push (elt);
        }
-      type2 = nreverse (type2);
+      type2 = make_tree_vec (trailing.length ());
+      for (int i = 0; i < TREE_VEC_LENGTH (type2); ++i)
+       TREE_VEC_ELT (type2, i) = trailing[i];
     }
 
   location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
index f65f2d58b28b4d98b6a5b2c8fa830a2278c559ce..d393c99ba9e556114aa1cdc6c572e3c263e389d3 100644 (file)
@@ -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;
index a4f30fdac113f630e2d5fc847c0b65d86d74e1f9..9ba316ab3be4176ee1517328e2f9612140069c5c 100644 (file)
@@ -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.