tree: introduce range adaptor for TREE_VEC

Message ID 20220511192008.1917896-1-ppalka@redhat.com
State New
Headers
Series tree: introduce range adaptor for TREE_VEC |

Commit Message

Patrick Palka May 11, 2022, 7:20 p.m. UTC
  This patch implements a simple tree wrapper, named tree_vec_range, which
lets us idiomatically iterate over all the elements of a TREE_VEC using
a C++11 range-based for loop:

  // v is a TREE_VEC
  for (tree e : tree_vec_range (v))
    ...

This is similar to the existing tree-based range adaptors ovl_range and
lkp_range added to the C++ frontend by r12-340-g3307b9a07a3c51.

This patch also converts some existing loops over TREE_VEC within the
C++ frontend to use tree_vec_range and range-for.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
useful?

gcc/cp/ChangeLog:

	* constraint.cc (tsubst_parameter_mapping): Convert loop over
	TREE_VEC into a range-based for loop using tree_vec_range.
	* pt.cc (iterative_hash_template_arg): Likewise.
	(template_parms_level_to_args): Likewise (and simplify).
	(deducible_template_args): Likewise.
	(check_undeduced_parms): Likewise.
	(dependent_type_p_r): Likewise.
	(value_dependent_expression_p) <case NONTYPE_ARGUMENT_PACK>:
	Likewise.
	(dependent_template_arg_p): Likewise.
	* tree.cc (cp_walk_subtrees) <case NONTYPE_ARGUMENT_PACK>:
	Likewise.

gcc/ChangeLog:

	* tree.h (TREE_VEC_BEGIN): Define.
	(TREE_VEC_END): Correct access of length member.
	(class tree_vec_range): Define.
---
 gcc/cp/constraint.cc |  9 +++----
 gcc/cp/pt.cc         | 57 +++++++++++++++++---------------------------
 gcc/cp/tree.cc       |  5 ++--
 gcc/tree.h           | 15 +++++++++++-
 4 files changed, 41 insertions(+), 45 deletions(-)
  

Comments

Jason Merrill May 11, 2022, 7:29 p.m. UTC | #1
On 5/11/22 15:20, Patrick Palka wrote:
> This patch implements a simple tree wrapper, named tree_vec_range, which
> lets us idiomatically iterate over all the elements of a TREE_VEC using
> a C++11 range-based for loop:
> 
>    // v is a TREE_VEC
>    for (tree e : tree_vec_range (v))
>      ...
> 
> This is similar to the existing tree-based range adaptors ovl_range and
> lkp_range added to the C++ frontend by r12-340-g3307b9a07a3c51.
> 
> This patch also converts some existing loops over TREE_VEC within the
> C++ frontend to use tree_vec_range and range-for.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> useful?

OK.

> gcc/cp/ChangeLog:
> 
> 	* constraint.cc (tsubst_parameter_mapping): Convert loop over
> 	TREE_VEC into a range-based for loop using tree_vec_range.
> 	* pt.cc (iterative_hash_template_arg): Likewise.
> 	(template_parms_level_to_args): Likewise (and simplify).
> 	(deducible_template_args): Likewise.
> 	(check_undeduced_parms): Likewise.
> 	(dependent_type_p_r): Likewise.
> 	(value_dependent_expression_p) <case NONTYPE_ARGUMENT_PACK>:
> 	Likewise.
> 	(dependent_template_arg_p): Likewise.
> 	* tree.cc (cp_walk_subtrees) <case NONTYPE_ARGUMENT_PACK>:
> 	Likewise.
> 
> gcc/ChangeLog:
> 
> 	* tree.h (TREE_VEC_BEGIN): Define.
> 	(TREE_VEC_END): Correct access of length member.
> 	(class tree_vec_range): Define.
> ---
>   gcc/cp/constraint.cc |  9 +++----
>   gcc/cp/pt.cc         | 57 +++++++++++++++++---------------------------
>   gcc/cp/tree.cc       |  5 ++--
>   gcc/tree.h           | 15 +++++++++++-
>   4 files changed, 41 insertions(+), 45 deletions(-)
> 
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 94f6222b436..591155cee22 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -2348,12 +2348,9 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info)
>         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_arg = TREE_VEC_ELT (pack_args, i);
> -	      if (TYPE_P (pack_arg))
> -		pack_arg = canonicalize_type_argument (pack_arg, complain);
> -	    }
> +	  for (tree& pack_arg : tree_vec_range (pack_args))
> +	    if (TYPE_P (pack_arg))
> +	      pack_arg = canonicalize_type_argument (pack_arg, complain);
>   	}
>         if (new_arg == error_mark_node)
>   	return error_mark_node;
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 9932d861af6..2c7c5f8bb5d 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -1811,8 +1811,8 @@ iterative_hash_template_arg (tree arg, hashval_t val)
>         return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
>   
>       case TREE_VEC:
> -      for (int i = 0, len = TREE_VEC_LENGTH (arg); i < len; ++i)
> -	val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
> +      for (tree elt : tree_vec_range (arg))
> +	val = iterative_hash_template_arg (elt, val);
>         return val;
>   
>       case TYPE_PACK_EXPANSION:
> @@ -4883,15 +4883,15 @@ template_parm_to_arg (tree t)
>   tree
>   template_parms_level_to_args (tree parms)
>   {
> -  tree a = copy_node (parms);
> -  TREE_TYPE (a) = NULL_TREE;
> -  for (int i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
> -    TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
> +  parms = copy_node (parms);
> +  TREE_TYPE (parms) = NULL_TREE;
> +  for (tree& parm : tree_vec_range (parms))
> +    parm = template_parm_to_arg (parm);
>   
>     if (CHECKING_P)
> -    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
> +    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (parms, TREE_VEC_LENGTH (parms));
>   
> -  return a;
> +  return parms;
>   }
>   
>   /* Given a set of template parameters, return them as a set of template
> @@ -22470,10 +22470,9 @@ deducible_array_bound (tree domain)
>   static bool
>   deducible_template_args (tree args)
>   {
> -  for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
> +  for (tree elt : tree_vec_range (args))
>       {
>         bool deducible;
> -      tree elt = TREE_VEC_ELT (args, i);
>         if (ARGUMENT_PACK_P (elt))
>   	deducible = deducible_template_args (ARGUMENT_PACK_ARGS (elt));
>         else
> @@ -24844,12 +24843,11 @@ static bool
>   check_undeduced_parms (tree targs, tree args, tree end)
>   {
>     bool found = false;
> -  int i;
> -  for (i = TREE_VEC_LENGTH (targs) - 1; i >= 0; --i)
> -    if (TREE_VEC_ELT (targs, i) == NULL_TREE)
> +  for (tree& targ : tree_vec_range (targs))
> +    if (targ == NULL_TREE)
>         {
>   	found = true;
> -	TREE_VEC_ELT (targs, i) = error_mark_node;
> +	targ = error_mark_node;
>         }
>     if (found)
>       {
> @@ -27288,10 +27286,9 @@ dependent_type_p_r (tree type)
>     if (TREE_CODE (type) == TYPE_ARGUMENT_PACK)
>       {
>         tree args = ARGUMENT_PACK_ARGS (type);
> -      int i, len = TREE_VEC_LENGTH (args);
> -      for (i = 0; i < len; ++i)
> -        if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
> -          return true;
> +      for (tree arg : tree_vec_range (args))
> +	if (dependent_template_arg_p (arg))
> +	  return true;
>       }
>   
>     /* All TYPE_PACK_EXPANSIONs are dependent, because parameter packs must
> @@ -27574,16 +27571,10 @@ value_dependent_expression_p (tree expression)
>       case NONTYPE_ARGUMENT_PACK:
>         /* A NONTYPE_ARGUMENT_PACK is value-dependent if any packed argument
>            is value-dependent.  */
> -      {
> -        tree values = ARGUMENT_PACK_ARGS (expression);
> -        int i, len = TREE_VEC_LENGTH (values);
> -
> -        for (i = 0; i < len; ++i)
> -          if (value_dependent_expression_p (TREE_VEC_ELT (values, i)))
> -            return true;
> -
> -        return false;
> -      }
> +      for (tree arg : tree_vec_range (ARGUMENT_PACK_ARGS (expression)))
> +	if (value_dependent_expression_p (arg))
> +	  return true;
> +      return false;
>   
>       case TRAIT_EXPR:
>         {
> @@ -28209,13 +28200,9 @@ dependent_template_arg_p (tree arg)
>     else if (ARGUMENT_PACK_P (arg))
>       {
>         tree args = ARGUMENT_PACK_ARGS (arg);
> -      int i, len = TREE_VEC_LENGTH (args);
> -      for (i = 0; i < len; ++i)
> -        {
> -          if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
> -            return true;
> -        }
> -
> +      for (tree arg : tree_vec_range (args))
> +	if (dependent_template_arg_p (arg))
> +	  return true;
>         return false;
>       }
>     else if (TYPE_P (arg))
> diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> index 633cc164a3a..bc38c8fbdbe 100644
> --- a/gcc/cp/tree.cc
> +++ b/gcc/cp/tree.cc
> @@ -5414,9 +5414,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
>       case NONTYPE_ARGUMENT_PACK:
>         {
>           tree args = ARGUMENT_PACK_ARGS (*tp);
> -        int i, len = TREE_VEC_LENGTH (args);
> -        for (i = 0; i < len; i++)
> -          WALK_SUBTREE (TREE_VEC_ELT (args, i));
> +	for (tree arg : tree_vec_range (args))
> +	  WALK_SUBTREE (arg);
>         }
>         break;
>   
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 82eb8ba39d2..0c12c60ee7e 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -1107,8 +1107,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
>   
>   /* In a TREE_VEC node.  */
>   #define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->base.u.length)
> +#define TREE_VEC_BEGIN(NODE) (&TREE_VEC_CHECK (NODE)->vec.a[0])
>   #define TREE_VEC_END(NODE) \
> -  ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->vec.base.u.length]))
> +  ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->base.u.length]))
>   
>   #define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I)
>   
> @@ -4481,6 +4482,18 @@ extern tree make_tree_vec (int CXX_MEM_STAT_INFO);
>   
>   extern tree grow_tree_vec (tree v, int CXX_MEM_STAT_INFO);
>   
> +/* Treat a TREE_VEC as an range of trees, e.g.
> +   for (tree e : tree_vec_range (v)) { ... }  */
> +
> +class tree_vec_range
> +{
> +  tree v;
> +public:
> +  tree_vec_range(tree v) : v(v) { }
> +  tree *begin() { return TREE_VEC_BEGIN (v); }
> +  tree *end() { return TREE_VEC_END (v); }
> +};
> +
>   /* Construct various types of nodes.  */
>   
>   extern tree build_nt (enum tree_code, ...);
  

Patch

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 94f6222b436..591155cee22 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2348,12 +2348,9 @@  tsubst_parameter_mapping (tree map, tree args, subst_info info)
       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_arg = TREE_VEC_ELT (pack_args, i);
-	      if (TYPE_P (pack_arg))
-		pack_arg = canonicalize_type_argument (pack_arg, complain);
-	    }
+	  for (tree& pack_arg : tree_vec_range (pack_args))
+	    if (TYPE_P (pack_arg))
+	      pack_arg = canonicalize_type_argument (pack_arg, complain);
 	}
       if (new_arg == error_mark_node)
 	return error_mark_node;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 9932d861af6..2c7c5f8bb5d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1811,8 +1811,8 @@  iterative_hash_template_arg (tree arg, hashval_t val)
       return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
 
     case TREE_VEC:
-      for (int i = 0, len = TREE_VEC_LENGTH (arg); i < len; ++i)
-	val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
+      for (tree elt : tree_vec_range (arg))
+	val = iterative_hash_template_arg (elt, val);
       return val;
 
     case TYPE_PACK_EXPANSION:
@@ -4883,15 +4883,15 @@  template_parm_to_arg (tree t)
 tree
 template_parms_level_to_args (tree parms)
 {
-  tree a = copy_node (parms);
-  TREE_TYPE (a) = NULL_TREE;
-  for (int i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-    TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
+  parms = copy_node (parms);
+  TREE_TYPE (parms) = NULL_TREE;
+  for (tree& parm : tree_vec_range (parms))
+    parm = template_parm_to_arg (parm);
 
   if (CHECKING_P)
-    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
+    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (parms, TREE_VEC_LENGTH (parms));
 
-  return a;
+  return parms;
 }
 
 /* Given a set of template parameters, return them as a set of template
@@ -22470,10 +22470,9 @@  deducible_array_bound (tree domain)
 static bool
 deducible_template_args (tree args)
 {
-  for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
+  for (tree elt : tree_vec_range (args))
     {
       bool deducible;
-      tree elt = TREE_VEC_ELT (args, i);
       if (ARGUMENT_PACK_P (elt))
 	deducible = deducible_template_args (ARGUMENT_PACK_ARGS (elt));
       else
@@ -24844,12 +24843,11 @@  static bool
 check_undeduced_parms (tree targs, tree args, tree end)
 {
   bool found = false;
-  int i;
-  for (i = TREE_VEC_LENGTH (targs) - 1; i >= 0; --i)
-    if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+  for (tree& targ : tree_vec_range (targs))
+    if (targ == NULL_TREE)
       {
 	found = true;
-	TREE_VEC_ELT (targs, i) = error_mark_node;
+	targ = error_mark_node;
       }
   if (found)
     {
@@ -27288,10 +27286,9 @@  dependent_type_p_r (tree type)
   if (TREE_CODE (type) == TYPE_ARGUMENT_PACK)
     {
       tree args = ARGUMENT_PACK_ARGS (type);
-      int i, len = TREE_VEC_LENGTH (args);
-      for (i = 0; i < len; ++i)
-        if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
-          return true;
+      for (tree arg : tree_vec_range (args))
+	if (dependent_template_arg_p (arg))
+	  return true;
     }
 
   /* All TYPE_PACK_EXPANSIONs are dependent, because parameter packs must
@@ -27574,16 +27571,10 @@  value_dependent_expression_p (tree expression)
     case NONTYPE_ARGUMENT_PACK:
       /* A NONTYPE_ARGUMENT_PACK is value-dependent if any packed argument
          is value-dependent.  */
-      {
-        tree values = ARGUMENT_PACK_ARGS (expression);
-        int i, len = TREE_VEC_LENGTH (values);
-
-        for (i = 0; i < len; ++i)
-          if (value_dependent_expression_p (TREE_VEC_ELT (values, i)))
-            return true;
-
-        return false;
-      }
+      for (tree arg : tree_vec_range (ARGUMENT_PACK_ARGS (expression)))
+	if (value_dependent_expression_p (arg))
+	  return true;
+      return false;
 
     case TRAIT_EXPR:
       {
@@ -28209,13 +28200,9 @@  dependent_template_arg_p (tree arg)
   else if (ARGUMENT_PACK_P (arg))
     {
       tree args = ARGUMENT_PACK_ARGS (arg);
-      int i, len = TREE_VEC_LENGTH (args);
-      for (i = 0; i < len; ++i)
-        {
-          if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
-            return true;
-        }
-
+      for (tree arg : tree_vec_range (args))
+	if (dependent_template_arg_p (arg))
+	  return true;
       return false;
     }
   else if (TYPE_P (arg))
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 633cc164a3a..bc38c8fbdbe 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5414,9 +5414,8 @@  cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
     case NONTYPE_ARGUMENT_PACK:
       {
         tree args = ARGUMENT_PACK_ARGS (*tp);
-        int i, len = TREE_VEC_LENGTH (args);
-        for (i = 0; i < len; i++)
-          WALK_SUBTREE (TREE_VEC_ELT (args, i));
+	for (tree arg : tree_vec_range (args))
+	  WALK_SUBTREE (arg);
       }
       break;
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 82eb8ba39d2..0c12c60ee7e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1107,8 +1107,9 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
 
 /* In a TREE_VEC node.  */
 #define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->base.u.length)
+#define TREE_VEC_BEGIN(NODE) (&TREE_VEC_CHECK (NODE)->vec.a[0])
 #define TREE_VEC_END(NODE) \
-  ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->vec.base.u.length]))
+  ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->base.u.length]))
 
 #define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I)
 
@@ -4481,6 +4482,18 @@  extern tree make_tree_vec (int CXX_MEM_STAT_INFO);
 
 extern tree grow_tree_vec (tree v, int CXX_MEM_STAT_INFO);
 
+/* Treat a TREE_VEC as an range of trees, e.g.
+   for (tree e : tree_vec_range (v)) { ... }  */
+
+class tree_vec_range
+{
+  tree v;
+public:
+  tree_vec_range(tree v) : v(v) { }
+  tree *begin() { return TREE_VEC_BEGIN (v); }
+  tree *end() { return TREE_VEC_END (v); }
+};
+
 /* Construct various types of nodes.  */
 
 extern tree build_nt (enum tree_code, ...);