Commit 928af3bf by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/70001 (Infinity compilation time)

	PR c++/70001
	* constexpr.c (cxx_eval_vec_init_1): Reuse CONSTRUCTOR initializers
	for 1..max even for multi-dimensional arrays.  Call unshare_expr
	on it.

	* g++.dg/cpp0x/constexpr-70001-4.C: New test.
	* g++.dg/cpp1y/pr70001.C: New test.

From-SVN: r234439
parent 61637db3
2016-03-23 Jakub Jelinek <jakub@redhat.com> 2016-03-23 Jakub Jelinek <jakub@redhat.com>
PR c++/70001
* constexpr.c (cxx_eval_vec_init_1): Reuse CONSTRUCTOR initializers
for 1..max even for multi-dimensional arrays. Call unshare_expr
on it.
PR c++/70323 PR c++/70323
* constexpr.c (cxx_eval_constant_expression): Diagnose overflow * constexpr.c (cxx_eval_constant_expression): Diagnose overflow
on TREE_OVERFLOW constants. on TREE_OVERFLOW constants.
......
...@@ -2362,7 +2362,6 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, ...@@ -2362,7 +2362,6 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor); vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
vec_alloc (*p, max + 1); vec_alloc (*p, max + 1);
bool pre_init = false; bool pre_init = false;
tree pre_init_elt = NULL_TREE;
unsigned HOST_WIDE_INT i; unsigned HOST_WIDE_INT i;
/* For the default constructor, build up a call to the default /* For the default constructor, build up a call to the default
...@@ -2392,6 +2391,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, ...@@ -2392,6 +2391,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
{ {
tree idx = build_int_cst (size_type_node, i); tree idx = build_int_cst (size_type_node, i);
tree eltinit; tree eltinit;
bool reuse = false;
constexpr_ctx new_ctx; constexpr_ctx new_ctx;
init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype); init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype);
if (new_ctx.ctor != ctx->ctor) if (new_ctx.ctor != ctx->ctor)
...@@ -2400,7 +2400,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, ...@@ -2400,7 +2400,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
{ {
/* A multidimensional array; recurse. */ /* A multidimensional array; recurse. */
if (value_init || init == NULL_TREE) if (value_init || init == NULL_TREE)
{
eltinit = NULL_TREE; eltinit = NULL_TREE;
reuse = i == 0;
}
else else
eltinit = cp_build_array_ref (input_location, init, idx, eltinit = cp_build_array_ref (input_location, init, idx,
tf_warning_or_error); tf_warning_or_error);
...@@ -2412,18 +2415,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, ...@@ -2412,18 +2415,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
{ {
/* Initializing an element using value or default initialization /* Initializing an element using value or default initialization
we just pre-built above. */ we just pre-built above. */
if (pre_init_elt == NULL_TREE) eltinit = cxx_eval_constant_expression (&new_ctx, init, lval,
pre_init_elt
= cxx_eval_constant_expression (&new_ctx, init, lval,
non_constant_p, overflow_p); non_constant_p, overflow_p);
eltinit = pre_init_elt; reuse = i == 0;
/* Don't reuse the result of cxx_eval_constant_expression
call if it isn't a constant initializer or if it requires
relocations. */
if (initializer_constant_valid_p (pre_init_elt,
TREE_TYPE (pre_init_elt))
!= null_pointer_node)
pre_init_elt = NULL_TREE;
} }
else else
{ {
...@@ -2449,6 +2443,23 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, ...@@ -2449,6 +2443,23 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
} }
else else
CONSTRUCTOR_APPEND_ELT (*p, idx, eltinit); CONSTRUCTOR_APPEND_ELT (*p, idx, eltinit);
/* Reuse the result of cxx_eval_constant_expression call
from the first iteration to all others if it is a constant
initializer that doesn't require relocations. */
if (reuse
&& max > 1
&& (initializer_constant_valid_p (eltinit, TREE_TYPE (eltinit))
== null_pointer_node))
{
if (new_ctx.ctor != ctx->ctor)
eltinit = new_ctx.ctor;
for (i = 1; i < max; ++i)
{
idx = build_int_cst (size_type_node, i);
CONSTRUCTOR_APPEND_ELT (*p, idx, unshare_expr (eltinit));
}
break;
}
} }
if (!*non_constant_p) if (!*non_constant_p)
......
2016-03-23 Jakub Jelinek <jakub@redhat.com> 2016-03-23 Jakub Jelinek <jakub@redhat.com>
PR c++/70001
* g++.dg/cpp0x/constexpr-70001-4.C: New test.
* g++.dg/cpp1y/pr70001.C: New test.
PR c++/70323 PR c++/70323
* g++.dg/cpp0x/constexpr-70323.C: New test. * g++.dg/cpp0x/constexpr-70323.C: New test.
......
// PR c++/70001
// { dg-do compile { target c++11 } }
struct B
{
int a;
constexpr B () : a (0) { }
};
struct A
{
B b[1 << 19][1][1][1];
} c;
// PR c++/70001
// { dg-do compile { target c++14 } }
struct B
{
int a;
constexpr B () : a (0) { }
constexpr B (int x) : a (x) { }
};
struct C
{
B c;
constexpr C () : c (0) { }
};
struct A
{
B b[1 << 4];
};
struct D
{
C d[1 << 4];
};
constexpr int
foo (int a, int b)
{
A c;
c.b[a].a += b;
c.b[b].a += a;
return c.b[0].a + c.b[a].a + c.b[b].a;
}
constexpr int
bar (int a, int b)
{
D c;
c.d[a].c.a += b;
c.d[b].c.a += a;
return c.d[0].c.a + c.d[a].c.a + c.d[b].c.a;
}
constexpr int d = foo (1, 2);
constexpr int e = foo (0, 3);
constexpr int f = foo (2, 4);
constexpr int g = bar (1, 2);
constexpr int h = bar (0, 3);
constexpr int i = bar (2, 4);
static_assert (d == 3 && e == 6 && f == 6, "");
static_assert (g == 3 && h == 6 && i == 6, "");
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