diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ffdd2bbff2a..ab0ce03d03f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-05-10 Gabor Loki + + PR c/17913 + * c-typeck.c (build_conditional_expr): Remove reducing cond_expr. + * fold-const.c (fold): Expand the condition of reducing cond_expr. + (contains_label_1, contains_label_p): New functions for checking + labels in a sub-tree. + 2005-05-10 Joseph S. Myers PR c/21342 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d3b1c957020..806a20ade96 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3105,10 +3105,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) if (result_type != TREE_TYPE (op2)) op2 = convert_and_check (result_type, op2); - if (TREE_CODE (ifexp) == INTEGER_CST) - return non_lvalue (integer_zerop (ifexp) ? op2 : op1); - - return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2)); + return fold_build3 (COND_EXPR, result_type, ifexp, op1, op2); } /* Return a compound expression that performs two expressions and diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 140f940af27..0f3c8dd29e7 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9905,6 +9905,37 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } /* switch (code) */ } +/* Callback for walk_tree, looking for LABEL_EXPR. + Returns tree TP if it is LABEL_EXPR. Otherwise it returns NULL_TREE. + Do not check the sub-tree of GOTO_EXPR. */ + +static tree +contains_label_1 (tree *tp, + int *walk_subtrees, + void *data ATTRIBUTE_UNUSED) +{ + switch (TREE_CODE (*tp)) + { + case LABEL_EXPR: + return *tp; + case GOTO_EXPR: + *walk_subtrees = 0; + /* no break */ + default: + return NULL_TREE; + } +} + +/* Checks wheter the sub-tree ST contains a label LABEL_EXPR which is + accessible from outside the sub-tree. Returns NULL_TREE if no + addressable label is found. */ + +static bool +contains_label_p (tree st) +{ + return (walk_tree (&st, contains_label_1 , NULL, NULL) != NULL_TREE); +} + /* Fold a ternary expression of code CODE and type TYPE with operands OP0, OP1, and OP2. Return the folded expression if folding is successful. Otherwise, return NULL_TREE. */ @@ -9958,12 +9989,16 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2) so all simple results must be passed through pedantic_non_lvalue. */ if (TREE_CODE (arg0) == INTEGER_CST) { + tree unused_op = integer_zerop (arg0) ? op1 : op2; tem = integer_zerop (arg0) ? op2 : op1; /* 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 ((!TREE_SIDE_EFFECTS (unused_op) + || !contains_label_p (unused_op)) + && (! VOID_TYPE_P (TREE_TYPE (tem)) + || VOID_TYPE_P (type))) return pedantic_non_lvalue (tem); return NULL_TREE; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7dd2e1970d9..6b8ce931eb3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-05-10 Gabor Loki + + PR c/17913 + * gcc.c-torture/compile/pr17913.c: Computed jump test for PR17913 + 2005-05-10 Joseph S. Myers PR c/21342 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr17913.c b/gcc/testsuite/gcc.c-torture/compile/pr17913.c new file mode 100644 index 00000000000..30654a395d6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr17913.c @@ -0,0 +1,7 @@ +/* Test for computed jump into cond_expr: bug 17913. */ +void f (void) +{ + void *p = &&a; + 1 ? 1 : ({ a : 1; }); + goto *p; +}