diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-12-23 09:40:19 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-12-23 09:40:19 +0100 |
commit | 58ccbd1cdae4238dee5af09183fcf48729830b77 (patch) | |
tree | 25950ee9e5606ae3ad5f16ee90324afb8f864ac5 /gcc/fold-const.c | |
parent | 3911519ed5b63c98fa5050aef291b19a40f81fcc (diff) | |
download | gcc-58ccbd1cdae4238dee5af09183fcf48729830b77.zip gcc-58ccbd1cdae4238dee5af09183fcf48729830b77.tar.gz gcc-58ccbd1cdae4238dee5af09183fcf48729830b77.tar.bz2 |
re PR c++/83553 (compiler removes body of the for-loop, although there is a case label inside)
PR c++/83553
* fold-const.c (struct contains_label_data): New type.
(contains_label_1): Return non-NULL even for CASE_LABEL_EXPR, unless
inside of a SWITCH_BODY seen during the walk.
(contains_label_p): Use walk_tree instead of
walk_tree_without_duplicates, prepare data for contains_label_1 and
provide own pset.
* c-c++-common/torture/pr83553.c: New test.
From-SVN: r255987
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index b21f35a..10a67b2 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11218,22 +11218,48 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type, } /* switch (code) */ } +/* Used by contains_label_[p1]. */ + +struct contains_label_data +{ + hash_set<tree> *pset; + bool inside_switch_p; +}; + /* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is - a LABEL_EXPR; otherwise return NULL_TREE. Do not check the subtrees - of GOTO_EXPR. */ + a LABEL_EXPR or CASE_LABEL_EXPR not inside of another SWITCH_EXPR; otherwise + return NULL_TREE. Do not check the subtrees of GOTO_EXPR. */ static tree -contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) +contains_label_1 (tree *tp, int *walk_subtrees, void *data) { + contains_label_data *d = (contains_label_data *) data; switch (TREE_CODE (*tp)) { case LABEL_EXPR: return *tp; + case CASE_LABEL_EXPR: + if (!d->inside_switch_p) + return *tp; + return NULL_TREE; + + case SWITCH_EXPR: + if (!d->inside_switch_p) + { + if (walk_tree (&SWITCH_COND (*tp), contains_label_1, data, d->pset)) + return *tp; + d->inside_switch_p = true; + if (walk_tree (&SWITCH_BODY (*tp), contains_label_1, data, d->pset)) + return *tp; + d->inside_switch_p = false; + *walk_subtrees = 0; + } + return NULL_TREE; + case GOTO_EXPR: *walk_subtrees = 0; - - /* fall through */ + return NULL_TREE; default: return NULL_TREE; @@ -11246,8 +11272,9 @@ contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) static bool contains_label_p (tree st) { - return - (walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE); + hash_set<tree> pset; + contains_label_data data = { &pset, false }; + return walk_tree (&st, contains_label_1, &data, &pset) != NULL_TREE; } /* Fold a ternary expression of code CODE and type TYPE with operands |