PR c++/65970 - constexpr infinite loop
authorJason Merrill <jason@redhat.com>
Mon, 25 Jul 2016 18:32:13 +0000 (14:32 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 25 Jul 2016 18:32:13 +0000 (14:32 -0400)
gcc/c-family/
* c.opt (fconstexpr-loop-limit): New.
gcc/cp/
* constexpr.c (cxx_eval_loop_expr): Count iterations.
* cp-gimplify.c (genericize_cp_loop): Use start_locus even for
infinite loops.

From-SVN: r238730

gcc/c-family/ChangeLog
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/cp-gimplify.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C [new file with mode: 0644]

index 5c1930518247d61e40485289e0160700f0d7e38d..72ccd035c99af19837eb40556513e0d9b2b7ba5a 100644 (file)
@@ -1,3 +1,8 @@
+2016-07-25  Jason Merrill  <jason@redhat.com>
+
+       PR c++/65970
+       * c.opt (fconstexpr-loop-limit): New.
+
 2016-07-22 Martin Sebor  <msebor@redhat.com>
 
        PR c++/71675
index 8c701523c3871ebd5c35ba1690bd0d1a9302804d..a5358ededb30119e3922fb99e44f16dd6f2b1590 100644 (file)
@@ -1174,6 +1174,10 @@ fconstexpr-depth=
 C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512)
 -fconstexpr-depth=<number>     Specify maximum constexpr recursion depth.
 
+fconstexpr-loop-limit=
+C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
+-fconstexpr-loop-limit=<number>        Specify maximum constexpr loop iteration count.
+
 fdebug-cpp
 C ObjC C++ ObjC++
 Emit debug annotations during preprocessing.
index a540d31133ba977472dd75bbc960297f747bf32c..5854205b3b7582f255e24c6aa72e7ecf785b5c54 100644 (file)
@@ -1,5 +1,10 @@
 2016-07-25  Jason Merrill  <jason@redhat.com>
 
+       PR c++/65970
+       * constexpr.c (cxx_eval_loop_expr): Count iterations.
+       * cp-gimplify.c (genericize_cp_loop): Use start_locus even for
+       infinite loops.
+
        PR c++/71972
        * constexpr.c (cxx_eval_array_reference): Handle looking for the
        value of an element we're currently modifying.
index 47fb39b42430c8dfee60a93eaa33b8a52993ec03..6bcb41ae8254b70eae841085362184a998ed95aa 100644 (file)
@@ -3468,6 +3468,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
   constexpr_ctx new_ctx = *ctx;
 
   tree body = TREE_OPERAND (t, 0);
+  int count = 0;
   do
     {
       hash_set<tree> save_exprs;
@@ -3480,6 +3481,16 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
       for (hash_set<tree>::iterator iter = save_exprs.begin();
           iter != save_exprs.end(); ++iter)
        new_ctx.values->remove (*iter);
+      if (++count >= constexpr_loop_limit)
+       {
+         if (!ctx->quiet)
+           error_at (EXPR_LOC_OR_LOC (t, input_location),
+                     "constexpr loop iteration count exceeds limit of %d "
+                     "(use -fconstexpr-loop-limit= to increase the limit)",
+                     constexpr_loop_limit);
+         *non_constant_p = true;
+         break;
+       }
     }
   while (!returns (jump_target) && !breaks (jump_target) && !*non_constant_p);
 
index 59953a6ee04376969051acb710456be0667f24f4..d9f7ceaed5024607652fa0c1897f123c6b8aa1d5 100644 (file)
@@ -264,14 +264,7 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
        loop = stmt_list;
     }
   else
-    {
-      location_t loc = start_locus;
-      if (!cond || integer_nonzerop (cond))
-       loc = EXPR_LOCATION (expr_first (body));
-      if (loc == UNKNOWN_LOCATION)
-       loc = start_locus;
-      loop = build1_loc (loc, LOOP_EXPR, void_type_node, stmt_list);
-    }
+    loop = build1_loc (start_locus, LOOP_EXPR, void_type_node, stmt_list);
 
   stmt_list = NULL;
   append_to_statement_list (loop, &stmt_list);
index 9e0f07eb54272b2f1d6f6fb474103a3059fc94ae..79c842df6b327632f704614216e878becea2eb4f 100644 (file)
@@ -191,7 +191,8 @@ in the following sections.
 @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
 @gccoptlist{-fabi-version=@var{n}  -fno-access-control @gol
 -fargs-in-order=@var{n} -fcheck-new @gol
--fconstexpr-depth=@var{n}  -ffriend-injection @gol
+-fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol
+-ffriend-injection @gol
 -fno-elide-constructors @gol
 -fno-enforce-eh-specs @gol
 -ffor-scope  -fno-for-scope  -fno-gnu-keywords @gol
@@ -2265,6 +2266,12 @@ to @var{n}.  A limit is needed to detect endless recursion during
 constant expression evaluation.  The minimum specified by the standard
 is 512.
 
+@item -fconstexpr-loop-limit=@var{n}
+@opindex fconstexpr-loop-limit
+Set the maximum number of iterations for a loop in C++14 constexpr functions
+to @var{n}.  A limit is needed to detect infinite loops during
+constant expression evaluation.  The default is 262144 (1<<18).
+
 @item -fdeduce-init-list
 @opindex fdeduce-init-list
 Enable deduction of a template type parameter as
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop6.C
new file mode 100644 (file)
index 0000000..e49e531
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/65970
+// { dg-do compile { target c++14 } }
+// { dg-options -fconstexpr-loop-limit=5 }
+
+constexpr int foo() {
+  while (true)                 // { dg-error "-fconstexpr-loop-limit" }
+    ;
+  return 0;
+}
+
+constexpr int i = foo();       // { dg-message "" }