aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-12-23 09:40:19 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-12-23 09:40:19 +0100
commit58ccbd1cdae4238dee5af09183fcf48729830b77 (patch)
tree25950ee9e5606ae3ad5f16ee90324afb8f864ac5
parent3911519ed5b63c98fa5050aef291b19a40f81fcc (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/fold-const.c41
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr83553.c29
4 files changed, 78 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aba9ae7..f8375f7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2017-12-23 Jakub Jelinek <jakub@redhat.com>
+
+ 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.
+
2017-12-22 Jakub Jelinek <jakub@redhat.com>
PR debug/83547
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c736ca2..6e6f67a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-12-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/83553
+ * c-c++-common/torture/pr83553.c: New test.
+
2017-12-22 Jakub Jelinek <jakub@redhat.com>
PR debug/83550
diff --git a/gcc/testsuite/c-c++-common/torture/pr83553.c b/gcc/testsuite/c-c++-common/torture/pr83553.c
new file mode 100644
index 0000000..c12b79b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr83553.c
@@ -0,0 +1,29 @@
+/* PR c++/83553 */
+/* { dg-do run } */
+
+int a[3];
+
+int
+foo (int n)
+{
+ switch (n)
+ {
+ case 0:
+ for (n = 7, a[0]++; 0; a[2] = a[1] + 1)
+ {
+ case 2:
+ a[1] = a[0] + 1;
+ }
+ }
+ return n;
+}
+
+int
+main ()
+{
+ if (foo (0) != 7 || a[0] != 1 || a[1] || a[2])
+ __builtin_abort ();
+ if (foo (2) != 2 || a[0] != 1 || a[1] != 2 || a[2] != 3)
+ __builtin_abort ();
+ return 0;
+}