[1/2] c++: make strip_typedefs generalize strip_typedefs_expr

Message ID 20230420135633.2447631-1-ppalka@redhat.com
State New
Headers
Series [1/2] c++: make strip_typedefs generalize strip_typedefs_expr |

Commit Message

Patrick Palka April 20, 2023, 1:56 p.m. UTC
  If we have a TREE_VEC of types that we want to strip of typedefs, we
unintuitively need to call strip_typedefs_expr instead of strip_typedefs
since only strip_typedefs_expr handles TREE_VEC, and it also dispatches
to strip_typedefs when given a type.  But this seems backwards: arguably
strip_typedefs_expr should be the more specialized function, which
strip_typedefs dispatches to (and thus generalizes).

This patch makes strip_typedefs generalize strip_typedefs_expr, which
allows for some simplifications.

gcc/cp/ChangeLog:

	* tree.cc (strip_typedefs): Move TREE_LIST handling to
	strip_typedefs_expr.  Dispatch to strip_typedefs_expr
	for a non-type 't'.
	<case TYPENAME_TYPE>: Remove manual dispatching to
	strip_typedefs_expr.
	<case TRAIT_TYPE>: Likewise.
	(strip_typedefs_expr): Replaces calls to strip_typedefs_expr
	with strip_typedefs throughout.  Don't dispatch to strip_typedefs
	for a type 't'.
	<case TREE_LIST>: Replace this with the better version from
	strip_typedefs.
---
 gcc/cp/tree.cc | 83 +++++++++++++++-----------------------------------
 1 file changed, 24 insertions(+), 59 deletions(-)
  

Comments

Jason Merrill April 20, 2023, 4:58 p.m. UTC | #1
On 4/20/23 09:56, Patrick Palka wrote:
> If we have a TREE_VEC of types that we want to strip of typedefs, we
> unintuitively need to call strip_typedefs_expr instead of strip_typedefs
> since only strip_typedefs_expr handles TREE_VEC, and it also dispatches
> to strip_typedefs when given a type.  But this seems backwards: arguably
> strip_typedefs_expr should be the more specialized function, which
> strip_typedefs dispatches to (and thus generalizes).
> 
> This patch makes strip_typedefs generalize strip_typedefs_expr, which
> allows for some simplifications.

OK.

> gcc/cp/ChangeLog:
> 
> 	* tree.cc (strip_typedefs): Move TREE_LIST handling to
> 	strip_typedefs_expr.  Dispatch to strip_typedefs_expr
> 	for a non-type 't'.
> 	<case TYPENAME_TYPE>: Remove manual dispatching to
> 	strip_typedefs_expr.
> 	<case TRAIT_TYPE>: Likewise.
> 	(strip_typedefs_expr): Replaces calls to strip_typedefs_expr
> 	with strip_typedefs throughout.  Don't dispatch to strip_typedefs
> 	for a type 't'.
> 	<case TREE_LIST>: Replace this with the better version from
> 	strip_typedefs.
> ---
>   gcc/cp/tree.cc | 83 +++++++++++++++-----------------------------------
>   1 file changed, 24 insertions(+), 59 deletions(-)
> 
> diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> index 2c22fac17ee..f0fb78fe69d 100644
> --- a/gcc/cp/tree.cc
> +++ b/gcc/cp/tree.cc
> @@ -1562,7 +1562,8 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
>   
>   /* Builds a qualified variant of T that is either not a typedef variant
>      (the default behavior) or not a typedef variant of a user-facing type
> -   (if FLAGS contains STF_USER_FACING).
> +   (if FLAGS contains STF_USER_FACING).  If T is not a type, then this
> +   just calls strip_typedefs_expr.
>   
>      E.g. consider the following declarations:
>        typedef const int ConstInt;
> @@ -1596,25 +1597,8 @@ strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
>     if (!t || t == error_mark_node)
>       return t;
>   
> -  if (TREE_CODE (t) == TREE_LIST)
> -    {
> -      bool changed = false;
> -      releasing_vec vec;
> -      tree r = t;
> -      for (; t; t = TREE_CHAIN (t))
> -	{
> -	  gcc_assert (!TREE_PURPOSE (t));
> -	  tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags);
> -	  if (elt != TREE_VALUE (t))
> -	    changed = true;
> -	  vec_safe_push (vec, elt);
> -	}
> -      if (changed)
> -	r = build_tree_list_vec (vec);
> -      return r;
> -    }
> -
> -  gcc_assert (TYPE_P (t));
> +  if (!TYPE_P (t))
> +    return strip_typedefs_expr (t, remove_attributes, flags);
>   
>     if (t == TYPE_CANONICAL (t))
>       return t;
> @@ -1747,12 +1731,7 @@ strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
>   	    for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
>   	      {
>   		tree arg = TREE_VEC_ELT (args, i);
> -		tree strip_arg;
> -		if (TYPE_P (arg))
> -		  strip_arg = strip_typedefs (arg, remove_attributes, flags);
> -		else
> -		  strip_arg = strip_typedefs_expr (arg, remove_attributes,
> -						   flags);
> +		tree strip_arg = strip_typedefs (arg, remove_attributes, flags);
>   		TREE_VEC_ELT (new_args, i) = strip_arg;
>   		if (strip_arg != arg)
>   		  changed = true;
> @@ -1792,11 +1771,8 @@ strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
>         break;
>       case TRAIT_TYPE:
>         {
> -	tree type1 = TRAIT_TYPE_TYPE1 (t);
> -	if (TYPE_P (type1))
> -	  type1 = strip_typedefs (type1, remove_attributes, flags);
> -	else
> -	  type1 = strip_typedefs_expr (type1, remove_attributes, flags);
> +	tree type1 = strip_typedefs (TRAIT_TYPE_TYPE1 (t),
> +				     remove_attributes, flags);
>   	tree type2 = strip_typedefs (TRAIT_TYPE_TYPE2 (t),
>   				     remove_attributes, flags);
>   	if (type1 == TRAIT_TYPE_TYPE1 (t) && type2 == TRAIT_TYPE_TYPE2 (t))
> @@ -1883,7 +1859,8 @@ strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
>     return cp_build_qualified_type (result, cp_type_quals (t));
>   }
>   
> -/* Like strip_typedefs above, but works on expressions, so that in
> +/* Like strip_typedefs above, but works on expressions (and other non-types
> +   such as TREE_VEC), so that in
>   
>      template<class T> struct A
>      {
> @@ -1908,11 +1885,6 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
>     if (DECL_P (t) || CONSTANT_CLASS_P (t))
>       return t;
>   
> -  /* Some expressions have type operands, so let's handle types here rather
> -     than check TYPE_P in multiple places below.  */
> -  if (TYPE_P (t))
> -    return strip_typedefs (t, remove_attributes, flags);
> -
>     code = TREE_CODE (t);
>     switch (code)
>       {
> @@ -1940,26 +1912,19 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
>   
>       case TREE_LIST:
>         {
> -	releasing_vec vec;
>   	bool changed = false;
> -	tree it;
> -	for (it = t; it; it = TREE_CHAIN (it))
> +	releasing_vec vec;
> +	r = t;
> +	for (; t; t = TREE_CHAIN (t))
>   	  {
> -	    tree val = strip_typedefs_expr (TREE_VALUE (it),
> -					    remove_attributes, flags);
> -	    vec_safe_push (vec, val);
> -	    if (val != TREE_VALUE (it))
> +	    gcc_assert (!TREE_PURPOSE (t));
> +	    tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags);
> +	    if (elt != TREE_VALUE (t))
>   	      changed = true;
> -	    gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
> +	    vec_safe_push (vec, elt);
>   	  }
>   	if (changed)
> -	  {
> -	    r = NULL_TREE;
> -	    FOR_EACH_VEC_ELT_REVERSE (*vec, i, it)
> -	      r = tree_cons (NULL_TREE, it, r);
> -	  }
> -	else
> -	  r = t;
> +	  r = build_tree_list_vec (vec);
>   	return r;
>         }
>   
> @@ -1971,8 +1936,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
>   	vec_safe_reserve (vec, n);
>   	for (i = 0; i < n; ++i)
>   	  {
> -	    tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i),
> -					   remove_attributes, flags);
> +	    tree op = strip_typedefs (TREE_VEC_ELT (t, i),
> +				      remove_attributes, flags);
>   	    vec->quick_push (op);
>   	    if (op != TREE_VEC_ELT (t, i))
>   	      changed = true;
> @@ -2000,15 +1965,15 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
>   	for (i = 0; i < n; ++i)
>   	  {
>   	    constructor_elt *e = &(*vec)[i];
> -	    tree op = strip_typedefs_expr (e->value, remove_attributes, flags);
> +	    tree op = strip_typedefs (e->value, remove_attributes, flags);
>   	    if (op != e->value)
>   	      {
>   		changed = true;
>   		e->value = op;
>   	      }
>   	    gcc_checking_assert
> -	      (e->index == strip_typedefs_expr (e->index, remove_attributes,
> -						flags));
> +	      (e->index == strip_typedefs (e->index, remove_attributes,
> +					   flags));
>   	  }
>   
>   	if (!changed && type == TREE_TYPE (t))
> @@ -2057,8 +2022,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
>   
>       default:
>         for (i = 0; i < n; ++i)
> -	ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i),
> -				      remove_attributes, flags);
> +	ops[i] = strip_typedefs (TREE_OPERAND (t, i),
> +				 remove_attributes, flags);
>         break;
>       }
>
  

Patch

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 2c22fac17ee..f0fb78fe69d 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -1562,7 +1562,8 @@  apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
 
 /* Builds a qualified variant of T that is either not a typedef variant
    (the default behavior) or not a typedef variant of a user-facing type
-   (if FLAGS contains STF_USER_FACING).
+   (if FLAGS contains STF_USER_FACING).  If T is not a type, then this
+   just calls strip_typedefs_expr.
 
    E.g. consider the following declarations:
      typedef const int ConstInt;
@@ -1596,25 +1597,8 @@  strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
   if (!t || t == error_mark_node)
     return t;
 
-  if (TREE_CODE (t) == TREE_LIST)
-    {
-      bool changed = false;
-      releasing_vec vec;
-      tree r = t;
-      for (; t; t = TREE_CHAIN (t))
-	{
-	  gcc_assert (!TREE_PURPOSE (t));
-	  tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags);
-	  if (elt != TREE_VALUE (t))
-	    changed = true;
-	  vec_safe_push (vec, elt);
-	}
-      if (changed)
-	r = build_tree_list_vec (vec);
-      return r;
-    }
-
-  gcc_assert (TYPE_P (t));
+  if (!TYPE_P (t))
+    return strip_typedefs_expr (t, remove_attributes, flags);
 
   if (t == TYPE_CANONICAL (t))
     return t;
@@ -1747,12 +1731,7 @@  strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
 	    for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
 	      {
 		tree arg = TREE_VEC_ELT (args, i);
-		tree strip_arg;
-		if (TYPE_P (arg))
-		  strip_arg = strip_typedefs (arg, remove_attributes, flags);
-		else
-		  strip_arg = strip_typedefs_expr (arg, remove_attributes,
-						   flags);
+		tree strip_arg = strip_typedefs (arg, remove_attributes, flags);
 		TREE_VEC_ELT (new_args, i) = strip_arg;
 		if (strip_arg != arg)
 		  changed = true;
@@ -1792,11 +1771,8 @@  strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
       break;
     case TRAIT_TYPE:
       {
-	tree type1 = TRAIT_TYPE_TYPE1 (t);
-	if (TYPE_P (type1))
-	  type1 = strip_typedefs (type1, remove_attributes, flags);
-	else
-	  type1 = strip_typedefs_expr (type1, remove_attributes, flags);
+	tree type1 = strip_typedefs (TRAIT_TYPE_TYPE1 (t),
+				     remove_attributes, flags);
 	tree type2 = strip_typedefs (TRAIT_TYPE_TYPE2 (t),
 				     remove_attributes, flags);
 	if (type1 == TRAIT_TYPE_TYPE1 (t) && type2 == TRAIT_TYPE_TYPE2 (t))
@@ -1883,7 +1859,8 @@  strip_typedefs (tree t, bool *remove_attributes /* = NULL */,
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Like strip_typedefs above, but works on expressions, so that in
+/* Like strip_typedefs above, but works on expressions (and other non-types
+   such as TREE_VEC), so that in
 
    template<class T> struct A
    {
@@ -1908,11 +1885,6 @@  strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
   if (DECL_P (t) || CONSTANT_CLASS_P (t))
     return t;
 
-  /* Some expressions have type operands, so let's handle types here rather
-     than check TYPE_P in multiple places below.  */
-  if (TYPE_P (t))
-    return strip_typedefs (t, remove_attributes, flags);
-
   code = TREE_CODE (t);
   switch (code)
     {
@@ -1940,26 +1912,19 @@  strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
 
     case TREE_LIST:
       {
-	releasing_vec vec;
 	bool changed = false;
-	tree it;
-	for (it = t; it; it = TREE_CHAIN (it))
+	releasing_vec vec;
+	r = t;
+	for (; t; t = TREE_CHAIN (t))
 	  {
-	    tree val = strip_typedefs_expr (TREE_VALUE (it),
-					    remove_attributes, flags);
-	    vec_safe_push (vec, val);
-	    if (val != TREE_VALUE (it))
+	    gcc_assert (!TREE_PURPOSE (t));
+	    tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags);
+	    if (elt != TREE_VALUE (t))
 	      changed = true;
-	    gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
+	    vec_safe_push (vec, elt);
 	  }
 	if (changed)
-	  {
-	    r = NULL_TREE;
-	    FOR_EACH_VEC_ELT_REVERSE (*vec, i, it)
-	      r = tree_cons (NULL_TREE, it, r);
-	  }
-	else
-	  r = t;
+	  r = build_tree_list_vec (vec);
 	return r;
       }
 
@@ -1971,8 +1936,8 @@  strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
 	vec_safe_reserve (vec, n);
 	for (i = 0; i < n; ++i)
 	  {
-	    tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i),
-					   remove_attributes, flags);
+	    tree op = strip_typedefs (TREE_VEC_ELT (t, i),
+				      remove_attributes, flags);
 	    vec->quick_push (op);
 	    if (op != TREE_VEC_ELT (t, i))
 	      changed = true;
@@ -2000,15 +1965,15 @@  strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
 	for (i = 0; i < n; ++i)
 	  {
 	    constructor_elt *e = &(*vec)[i];
-	    tree op = strip_typedefs_expr (e->value, remove_attributes, flags);
+	    tree op = strip_typedefs (e->value, remove_attributes, flags);
 	    if (op != e->value)
 	      {
 		changed = true;
 		e->value = op;
 	      }
 	    gcc_checking_assert
-	      (e->index == strip_typedefs_expr (e->index, remove_attributes,
-						flags));
+	      (e->index == strip_typedefs (e->index, remove_attributes,
+					   flags));
 	  }
 
 	if (!changed && type == TREE_TYPE (t))
@@ -2057,8 +2022,8 @@  strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
 
     default:
       for (i = 0; i < n; ++i)
-	ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i),
-				      remove_attributes, flags);
+	ops[i] = strip_typedefs (TREE_OPERAND (t, i),
+				 remove_attributes, flags);
       break;
     }