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
This commit is contained in:
parent
61637db3f2
commit
928af3bfe2
@ -1,5 +1,10 @@
|
||||
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
|
||||
* constexpr.c (cxx_eval_constant_expression): Diagnose overflow
|
||||
on TREE_OVERFLOW constants.
|
||||
|
@ -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_alloc (*p, max + 1);
|
||||
bool pre_init = false;
|
||||
tree pre_init_elt = NULL_TREE;
|
||||
unsigned HOST_WIDE_INT i;
|
||||
|
||||
/* 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,
|
||||
{
|
||||
tree idx = build_int_cst (size_type_node, i);
|
||||
tree eltinit;
|
||||
bool reuse = false;
|
||||
constexpr_ctx new_ctx;
|
||||
init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype);
|
||||
if (new_ctx.ctor != ctx->ctor)
|
||||
@ -2400,7 +2400,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
|
||||
{
|
||||
/* A multidimensional array; recurse. */
|
||||
if (value_init || init == NULL_TREE)
|
||||
eltinit = NULL_TREE;
|
||||
{
|
||||
eltinit = NULL_TREE;
|
||||
reuse = i == 0;
|
||||
}
|
||||
else
|
||||
eltinit = cp_build_array_ref (input_location, init, idx,
|
||||
tf_warning_or_error);
|
||||
@ -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
|
||||
we just pre-built above. */
|
||||
if (pre_init_elt == NULL_TREE)
|
||||
pre_init_elt
|
||||
= cxx_eval_constant_expression (&new_ctx, init, lval,
|
||||
non_constant_p, overflow_p);
|
||||
eltinit = pre_init_elt;
|
||||
/* 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;
|
||||
eltinit = cxx_eval_constant_expression (&new_ctx, init, lval,
|
||||
non_constant_p, overflow_p);
|
||||
reuse = i == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2449,6 +2443,23 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
|
||||
}
|
||||
else
|
||||
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)
|
||||
|
@ -1,5 +1,9 @@
|
||||
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
|
||||
* g++.dg/cpp0x/constexpr-70323.C: New test.
|
||||
|
||||
|
13
gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C
Normal file
13
gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C
Normal file
@ -0,0 +1,13 @@
|
||||
// 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;
|
49
gcc/testsuite/g++.dg/cpp1y/pr70001.C
Normal file
49
gcc/testsuite/g++.dg/cpp1y/pr70001.C
Normal file
@ -0,0 +1,49 @@
|
||||
// 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, "");
|
Loading…
Reference in New Issue
Block a user