]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR c++/83553 (compiler removes body of the for-loop, although there...
authorJakub Jelinek <jakub@redhat.com>
Mon, 25 Jun 2018 17:10:18 +0000 (19:10 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 25 Jun 2018 17:10:18 +0000 (19:10 +0200)
Backported from mainline
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.

* c-c++-common/torture/pr83553.c: New test.

From-SVN: r262051

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

index 072aa51bc4b3417b1de7d4e769f410e5f7ea5c11..e88bcc28aa124e0f607ab74899a8dd2e7410b94f 100644 (file)
@@ -1,6 +1,16 @@
 2018-06-25  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       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-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/80747
index 0d575d0548ce8438de263cb46b88daebf2bc10c5..5bb4e2acb470d1a3359aa1c022f6ae94e78fc006 100644 (file)
@@ -11529,22 +11529,48 @@ fold_binary_loc (location_t loc,
     } /* 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;
@@ -11557,8 +11583,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 119a8a13787b99e442fcac9844df11ba505618d0..8bc2fb9088cd5370cef197900a01c48a4a56aa80 100644 (file)
@@ -1,6 +1,11 @@
 2018-06-25  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       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;
+}