aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/constexpr.c26
-rw-r--r--gcc/doc/invoke.texi12
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-87481.C16
8 files changed, 81 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d85a8fc..aa5530e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+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.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index a597b12..e10baba 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 962973a..0f39ebb 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 61cf384..71f9d67 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+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
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 68e78d0..e92ec55 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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,
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0a94151..4735b0a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2fee0da..febe7b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-87481.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-87481.C
new file mode 100644
index 0000000..fc4decf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-87481.C
@@ -0,0 +1,16 @@
+// 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" }