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> 2019-03-22 Bill Schmidt <wschmidt@linux.ibm.com>
* config/rs6000/mmintrin.h (_mm_sub_pi32): Fix typo. * 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> 2019-03-21 Jakub Jelinek <jakub@redhat.com>
* c-common.c (per_file_includes_t): Use false as Lazy in hash_set * c-common.c (per_file_includes_t): Use false as Lazy in hash_set
......
...@@ -1416,6 +1416,10 @@ fconstexpr-loop-limit= ...@@ -1416,6 +1416,10 @@ fconstexpr-loop-limit=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144) C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count. -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 fdebug-cpp
C ObjC C++ ObjC++ C ObjC C++ ObjC++
Emit debug annotations during preprocessing. 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> 2019-03-21 Jakub Jelinek <jakub@redhat.com>
PR c++/71446 PR c++/71446
......
...@@ -1032,6 +1032,11 @@ struct constexpr_ctx { ...@@ -1032,6 +1032,11 @@ struct constexpr_ctx {
tree object; tree object;
/* If inside SWITCH_EXPR. */ /* If inside SWITCH_EXPR. */
constexpr_switch_state *css_state; 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. */ /* Whether we should error on a non-constant expression or fail quietly. */
bool quiet; bool quiet;
/* Whether we are strictly conforming to constant expression rules or /* Whether we are strictly conforming to constant expression rules or
...@@ -4402,6 +4407,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -4402,6 +4407,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return 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); tree_code tcode = TREE_CODE (t);
switch (tcode) switch (tcode)
{ {
...@@ -5238,9 +5257,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, ...@@ -5238,9 +5257,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool non_constant_p = false; bool non_constant_p = false;
bool overflow_p = false; bool overflow_p = false;
hash_map<tree,tree> map; hash_map<tree,tree> map;
HOST_WIDE_INT constexpr_ctx_count = 0;
constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL, 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 }; manifestly_const_eval || !allow_non_constant };
tree type = initialized_type (t); tree type = initialized_type (t);
...@@ -5382,9 +5402,11 @@ is_sub_constant_expr (tree t) ...@@ -5382,9 +5402,11 @@ is_sub_constant_expr (tree t)
bool non_constant_p = false; bool non_constant_p = false;
bool overflow_p = false; bool overflow_p = false;
hash_map <tree, tree> map; hash_map <tree, tree> map;
HOST_WIDE_INT constexpr_ops_count = 0;
constexpr_ctx ctx 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); instantiate_constexpr_fns (t);
cxx_eval_constant_expression (&ctx, t, false, &non_constant_p, cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
......
...@@ -210,7 +210,7 @@ in the following sections. ...@@ -210,7 +210,7 @@ in the following sections.
@gccoptlist{-fabi-version=@var{n} -fno-access-control @gol @gccoptlist{-fabi-version=@var{n} -fno-access-control @gol
-faligned-new=@var{n} -fargs-in-order=@var{n} -fchar8_t -fcheck-new @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 -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-enforce-eh-specs @gol
-fno-gnu-keywords @gol -fno-gnu-keywords @gol
-fno-implicit-templates @gol -fno-implicit-templates @gol
...@@ -2525,6 +2525,16 @@ Set the maximum number of iterations for a loop in C++14 constexpr functions ...@@ -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 to @var{n}. A limit is needed to detect infinite loops during
constant expression evaluation. The default is 262144 (1<<18). 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 @item -fdeduce-init-list
@opindex fdeduce-init-list @opindex fdeduce-init-list
Enable deduction of a template type parameter as 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> 2019-03-22 Simon Wright <simon@pushface.org>
PR ada/89583 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