This PR points out infinite looping in constexpr evaluation for e.g.

  for (...)
    {
      continue;
      while (1);
    }

where we tried to evaluate the while despite the continue.  The problem
started with r240591 and its cxx_eval_statement_list changes.  This
patch fixes it by handling continue in such a way that we skip stmts that
are not meant to be evaluated.

Bootstrapped/regtested on x86_64-linux, ok for trunk/8.3?

2018-08-06  Marek Polacek  <pola...@redhat.com>

        PR c++/86767
        * constexpr.c (cxx_eval_statement_list): Handle continue.

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

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 365296d6e3b..79039ff2b79 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -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,
diff --git gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C 
gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
index e69de29bb2d..2ad71d507d1 100644
--- gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
@@ -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, "");

        Marek

Reply via email to