[1/2] c++: make strip_typedefs generalize strip_typedefs_expr
Commit Message
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
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;
> }
>
@@ -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;
}