This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR17913:[4.0 Regression] ICE jumping into statement expression
- From: Gábor Lóki <loki at inf dot u-szeged dot hu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 27 Oct 2004 14:04:10 +0200
- Subject: [PATCH] PR17913:[4.0 Regression] ICE jumping into statement expression
Hi,
The following patch fix PR17913. The patch does the following:
if the first operator of the conditional_expr is constant and
the not relevant side of it contains label, the conditional_expr
can't be reduced.
The patch was bootstraped and regtested without regressions on
i686-linux.
OK?
br,
Gabor Loki
2004-10-27 Gabor Loki <loki@inf.u-szeged.hu>
* c-types.c (build_conditional_expr): Expand the condition of
reducing conditional_expr.
* fold.c (fold): Same.
* tree.c (contains_tree_code): New function.
* tree.h (contains_tree_code): Prototype added.
Index: gcc/gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.640
diff -u -r1.640 tree.h
--- gcc/gcc/tree.h 22 Oct 2004 18:52:19 -0000 1.640
+++ gcc/gcc/tree.h 27 Oct 2004 11:38:36 -0000
@@ -3799,6 +3799,10 @@
extern tree walk_tree (tree*, walk_tree_fn, void*, struct pointer_set_t*);
extern tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
+/* Callback for walk_tree, searching for a specific tree type. */
+
+extern tree contains_tree_code (tree*, int*, void*);
+
/* In tree-dump.c */
/* Different tree dump places. When you add new tree dump places,
Index: gcc/gcc/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.439
diff -u -r1.439 tree.c
--- gcc/gcc/tree.c 21 Oct 2004 16:29:51 -0000 1.439
+++ gcc/gcc/tree.c 27 Oct 2004 11:39:23 -0000
@@ -4829,6 +4829,16 @@
}
}
+/* Callback for walk_tree, look for TREE_CODE which is stored in DATA. */
+
+tree
+contains_tree_code (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+{
+ if (TREE_CODE(*tp) == *((enum tree_code *)data))
+ return *tp;
+ return NULL_TREE;
+}
+
/* Subprogram of following function. Called by walk_tree.
Return *TP if it is an automatic variable or parameter of the
Index: gcc/gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.468
diff -u -r1.468 fold-const.c
--- gcc/gcc/fold-const.c 11 Oct 2004 03:42:00 -0000 1.468
+++ gcc/gcc/fold-const.c 27 Oct 2004 11:40:01 -0000
@@ -8751,12 +8751,20 @@
so all simple results must be passed through pedantic_non_lvalue. */
if (TREE_CODE (arg0) == INTEGER_CST)
{
+ enum tree_code data = LABEL_DECL;
+ tree unused_op = TREE_OPERAND (t, (integer_zerop (arg0) ? 1 : 2));
tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+
+ /* Check that the unused operand conatins LABEL_DECL. */
+ unused_op = walk_tree(&unused_op, contains_tree_code , &data, NULL);
+
/* Only optimize constant conditions when the selected branch
has the same type as the COND_EXPR. This avoids optimizing
- away "c ? x : throw", where the throw has a void type. */
- if (! VOID_TYPE_P (TREE_TYPE (tem))
- || VOID_TYPE_P (type))
+ away "c ? x : throw", where the throw has a void type.
+ Avoid throwing away that operand which contains label. */
+ if (!unused_op
+ && (! VOID_TYPE_P (TREE_TYPE (tem))
+ || VOID_TYPE_P (type)))
return pedantic_non_lvalue (tem);
return t;
}
Index: gcc/gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.392
diff -u -r1.392 c-typeck.c
--- gcc/gcc/c-typeck.c 17 Oct 2004 22:01:19 -0000 1.392
+++ gcc/gcc/c-typeck.c 27 Oct 2004 11:40:39 -0000
@@ -3040,7 +3040,17 @@
op2 = convert_and_check (result_type, op2);
if (TREE_CODE (ifexp) == INTEGER_CST)
- return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
+ {
+ enum tree_code data = LABEL_DECL;
+ tree unused_op = integer_zerop (ifexp) ? op1 : op2;
+
+ /* Check that the unused operand conatins LABEL_DECL. */
+ unused_op = walk_tree(&unused_op, contains_tree_code , &data, NULL);
+
+ /* Avoid throwing away that operand which contains label. */
+ if (!unused_op)
+ return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
+ }
return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2));
}