re PR c++/86767 (continue statements in constexpr functions causes unbounded looping)
authorMarek Polacek <polacek@redhat.com>
Mon, 6 Aug 2018 16:46:13 +0000 (16:46 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 6 Aug 2018 16:46:13 +0000 (16:46 +0000)
PR c++/86767
* constexpr.c (cxx_eval_statement_list): Handle continue.

* g++.dg/cpp1y/constexpr-86767.C: New test.

From-SVN: r263340

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C [new file with mode: 0644]

index 90af73d48102bb312b1d11cba000fbd88e377ca2..7cf87f8b68d2f0f9fc9cbd4d62dae1cfc1c61735 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-06  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/86767
+       * constexpr.c (cxx_eval_statement_list): Handle continue.
+
 2018-08-03  David Malcolm  <dmalcolm@redhat.com>
            Jonathan Wakely  <jwakely@redhat.com>
 
index 365296d6e3be936ac9c08bb885aad78c4cefae4a..79039ff2b791aea3f05eaa664a90b1820d8fb314 100644 (file)
@@ -3950,6 +3950,16 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
   for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
     {
       tree stmt = tsi_stmt (i);
+      /* We've found a continue, so skip everything until we reach
+        the label its jumping to.  */
+      if (continues (jump_target))
+       {
+         if (label_matches (ctx, jump_target, stmt))
+           /* Found it.  */
+           *jump_target = NULL_TREE;
+         else
+           continue;
+       }
       if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
        continue;
       r = cxx_eval_constant_expression (ctx, stmt, false,
index 71e3ad7b441056119acd2061573ade17ae215fd3..eec7461275d04f8c6cd90e2deadb15c237bc159b 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-06  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/86767
+       * g++.dg/cpp1y/constexpr-86767.C: New test.
+
 2018-08-06  Uros Bizjak  <ubizjak@gmail.com>
 
        * g++.dg/torture/pr86763.C (dg-additional-options): Add -lrt
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
new file mode 100644 (file)
index 0000000..2ad71d5
--- /dev/null
@@ -0,0 +1,119 @@
+// PR c++/86767
+// { dg-do compile { target c++14 } }
+
+constexpr int
+fn0 () noexcept
+{
+  int r = 0;
+  for (int i = 0; i < 10; ++i)
+    {
+      continue;
+      r++;
+      for (int j = 0; j < 10; ++j )
+       {
+       }
+    }
+  return r;
+}
+static_assert (fn0 () == 0, "");
+
+constexpr int
+fn1 () noexcept
+{
+  int r = 0;
+  for (int i = 0; i < 10; ++i)
+    for (int j = 0; j < 10; ++j)
+      {
+       continue;
+       r++;
+      }
+  return r;
+}
+static_assert (fn1 () == 0, "");
+
+constexpr int
+fn2 () noexcept
+{
+  int r = 0;
+  for (int i = 0; i < 10; ++i)
+    {
+      continue;
+      r++;
+    }
+  return r;
+}
+static_assert (fn2 () == 0, "");
+
+constexpr int
+fn3 () noexcept
+{
+  int r = 0;
+  for (int i = 0; i < 10; ++i)
+    {
+      continue;
+      r++;
+      while (1)
+       {
+       }
+    }
+  return r;
+}
+static_assert (fn3 () == 0, "");
+
+constexpr int
+fn4 () noexcept
+{
+  for (int i = 0; i < 10; ++i)
+    {
+      switch (i)
+       {
+       case 5:
+         return i;
+       default:
+         continue;
+       }
+      while (1)
+       {
+       }
+    }
+  return 0;
+}
+static_assert (fn4 () == 5, "");
+
+constexpr int
+fn5 () noexcept
+{
+  for (int i = 0; i < 10; ++i)
+    {
+      switch (i)
+       {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+         continue;
+       default:
+         return i;
+       }
+      while (1)
+       {
+       }
+    }
+  return 0;
+}
+static_assert (fn5 () == 5, "");
+
+constexpr int
+fn6 () noexcept
+{
+  int r = 0;
+  for (int i = 0; i < 10; ++i)
+    {
+      continue;
+      for (int j = 0; j < 10; ++j )
+       r++;
+    }
+  return r;
+}
+static_assert (fn6 () == 0, "");