While looking at a bug report caused by failure to strip all typedefs, I
came across a few latent bugs in the strip_typedefs functions.
First, if we're going to return a TREE_LIST unchanged we need to copy
the pointer before we change the input variable.
Second, if we have a decltype with no typedefs in the argument, we still
need to handle a typedef to that decltype.
Third, when we strip the operands of a TRAIT_EXPR we want to update the
operands of the copy, not the original.
Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit a5bfb34605c5ea629db6ff6db76cdaed0f675670
Author: Jason Merrill <ja...@redhat.com>
Date: Fri May 15 15:28:54 2015 -0400
* tree.c (strip_typedefs_expr) [TRAIT_EXPR]: Fix typo.
(strip_typedefs) [DECLTYPE_TYPE]: Fix typedef of decltype.
[TREE_LIST]: Fix no-change case.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ec9be8c..eebb415 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1265,6 +1265,7 @@ strip_typedefs (tree t, bool *remove_attributes)
{
bool changed = false;
vec<tree,va_gc> *vec = make_tree_vector ();
+ tree r = t;
for (; t; t = TREE_CHAIN (t))
{
gcc_assert (!TREE_PURPOSE (t));
@@ -1273,7 +1274,6 @@ strip_typedefs (tree t, bool *remove_attributes)
changed = true;
vec_safe_push (vec, elt);
}
- tree r = t;
if (changed)
r = build_tree_list_vec (vec);
release_tree_vector (vec);
@@ -1411,7 +1411,7 @@ strip_typedefs (tree t, bool *remove_attributes)
result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t),
remove_attributes);
if (result == DECLTYPE_TYPE_EXPR (t))
- return t;
+ result = NULL_TREE;
else
result = (finish_decltype_type
(result,
@@ -1496,8 +1496,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
&& type2 == TRAIT_EXPR_TYPE2 (t))
return t;
r = copy_node (t);
- TRAIT_EXPR_TYPE1 (t) = type1;
- TRAIT_EXPR_TYPE2 (t) = type2;
+ TRAIT_EXPR_TYPE1 (r) = type1;
+ TRAIT_EXPR_TYPE2 (r) = type2;
return r;
}