re PR c++/83553 (compiler removes body of the for-loop, although there is a case...
authorJakub Jelinek <jakub@redhat.com>
Sat, 23 Dec 2017 08:40:19 +0000 (09:40 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 23 Dec 2017 08:40:19 +0000 (09:40 +0100)
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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/torture/pr83553.c [new file with mode: 0644]

index aba9ae7ea5a4bb3b4ebb08a37a06c83c3524b178..f8375f7f66d4e9ae9e0dc900bc844ab26e0e2259 100644 (file)
@@ -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
index b21f35a37360f9df33371dcc232eee0963aaf1a7..10a67b2e5f98be628e5a09f8a690ef8949286b6f 100644 (file)
@@ -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
index c736ca24258c4861aff08e199aec7cea4ca58df4..6e6f67ab71c3129d9c3f9700ff151cc2246eae94 100644 (file)
@@ -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 (file)
index 0000000..c12b79b
--- /dev/null
@@ -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;
+}