Commit a15ffa22 by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/87481 (Endless loop with optimisation in C++17)

	PR c++/87481
	* doc/invoke.texi (-fconstexpr-ops-limit=): Document.

	* c.opt (-fconstexpr-ops-limit=): New option.

	* constexpr.c (struct constexpr_ctx): Add constexpr_ops_count member.
	(cxx_eval_constant_expression): When not skipping, not constant class
	or location wrapper, increment *ctx->constexpr_ops_count and if it is
	above constexpr_loop_nest_limit, diagnose failure.
	(cxx_eval_outermost_constant_expr): Add constexpr_ops_count and
	initialize ctx.constexpr_ops_count to its address.
	(is_sub_constant_expr): Likewise.

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

From-SVN: r269874
parent 29e0246c
2019-03-22 Jakub Jelinek <jakub@redhat.com>
PR c++/87481
* doc/invoke.texi (-fconstexpr-ops-limit=): Document.
2019-03-22 Bill Schmidt <wschmidt@linux.ibm.com>
* config/rs6000/mmintrin.h (_mm_sub_pi32): Fix typo.
......
2019-03-22 Jakub Jelinek <jakub@redhat.com>
PR c++/87481
* c.opt (-fconstexpr-ops-limit=): New option.
2019-03-21 Jakub Jelinek <jakub@redhat.com>
* c-common.c (per_file_includes_t): Use false as Lazy in hash_set
......
......@@ -1416,6 +1416,10 @@ fconstexpr-loop-limit=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count.
fconstexpr-ops-limit=
C++ ObjC++ Joined RejectNegative Host_Wide_Int Var(constexpr_ops_limit) Init(33554432)
-fconstexpr-ops-limit=<number> Specify maximum number of constexpr operations during a single constexpr evaluation.
fdebug-cpp
C ObjC C++ ObjC++
Emit debug annotations during preprocessing.
......
2019-03-22 Jakub Jelinek <jakub@redhat.com>
PR c++/87481
* constexpr.c (struct constexpr_ctx): Add constexpr_ops_count member.
(cxx_eval_constant_expression): When not skipping, not constant class
or location wrapper, increment *ctx->constexpr_ops_count and if it is
above constexpr_loop_nest_limit, diagnose failure.
(cxx_eval_outermost_constant_expr): Add constexpr_ops_count and
initialize ctx.constexpr_ops_count to its address.
(is_sub_constant_expr): Likewise.
2019-03-21 Jakub Jelinek <jakub@redhat.com>
PR c++/71446
......
......@@ -1032,6 +1032,11 @@ struct constexpr_ctx {
tree object;
/* If inside SWITCH_EXPR. */
constexpr_switch_state *css_state;
/* Number of cxx_eval_constant_expression calls (except skipped ones,
on simple constants or location wrappers) encountered during current
cxx_eval_outermost_constant_expr call. */
HOST_WIDE_INT *constexpr_ops_count;
/* Whether we should error on a non-constant expression or fail quietly. */
bool quiet;
/* Whether we are strictly conforming to constant expression rules or
......@@ -4402,6 +4407,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return t;
}
/* Avoid excessively long constexpr evaluations. */
if (!location_wrapper_p (t)
&& ++*ctx->constexpr_ops_count >= constexpr_ops_limit)
{
if (!ctx->quiet)
error_at (cp_expr_loc_or_loc (t, input_location),
"%<constexpr%> evaluation operation count exceeds limit of "
"%wd (use -fconstexpr-ops-limit= to increase the limit)",
constexpr_ops_limit);
*ctx->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
*non_constant_p = true;
return t;
}
tree_code tcode = TREE_CODE (t);
switch (tcode)
{
......@@ -5238,9 +5257,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool non_constant_p = false;
bool overflow_p = false;
hash_map<tree,tree> map;
HOST_WIDE_INT constexpr_ctx_count = 0;
constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL,
allow_non_constant, strict,
&constexpr_ctx_count, allow_non_constant, strict,
manifestly_const_eval || !allow_non_constant };
tree type = initialized_type (t);
......@@ -5382,9 +5402,11 @@ is_sub_constant_expr (tree t)
bool non_constant_p = false;
bool overflow_p = false;
hash_map <tree, tree> map;
HOST_WIDE_INT constexpr_ops_count = 0;
constexpr_ctx ctx
= { NULL, &map, NULL, NULL, NULL, NULL, true, true, false };
= { NULL, &map, NULL, NULL, NULL, NULL, &constexpr_ops_count,
true, true, false };
instantiate_constexpr_fns (t);
cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
......
......@@ -210,7 +210,7 @@ in the following sections.
@gccoptlist{-fabi-version=@var{n} -fno-access-control @gol
-faligned-new=@var{n} -fargs-in-order=@var{n} -fchar8_t -fcheck-new @gol
-fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol
-fno-elide-constructors @gol
-fconstexpr-ops-limit=@var{n} -fno-elide-constructors @gol
-fno-enforce-eh-specs @gol
-fno-gnu-keywords @gol
-fno-implicit-templates @gol
......@@ -2525,6 +2525,16 @@ 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 -fconstexpr-ops-limit=@var{n}
@opindex fconstexpr-ops-limit
Set the maximum number of operations during a single constexpr evaluation.
Even when number of iterations of a single loop is limited with the above limit,
if there are several nested loops and each of them has many iterations but still
smaller than the above limit, or if in a body of some loop or even outside
of a loop too many expressions need to be evaluated, the resulting constexpr
evaluation might take too long.
The default is 33554432 (1<<25).
@item -fdeduce-init-list
@opindex fdeduce-init-list
Enable deduction of a template type parameter as
2019-03-22 Jakub Jelinek <jakub@redhat.com>
PR c++/87481
* g++.dg/cpp1y/constexpr-87481.C: New test.
2019-03-22 Simon Wright <simon@pushface.org>
PR ada/89583
......
// PR c++/87481
// { dg-do compile { target c++14 } }
// { dg-options "-fconstexpr-loop-limit=98304 -fconstexpr-ops-limit=131072" } */
constexpr unsigned
foo ()
{
unsigned int r = 0;
for (int i = 0; i < 65536; i++)
for (int j = 0; j < 65536; j++)
for (int k = 0; k < 65536; k++) // { dg-error "'constexpr' evaluation operation count exceeds limit of 131072" "" { target *-*-* } 0 }
r += (i + j + k);
return r;
}
constexpr auto x = foo (); // { dg-message "in 'constexpr' expansion of" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment