re PR c++/89652 (ICE during constexpr evaluation)
PR c++/89652 * constexpr.c (struct constexpr_ctx): Change save_exprs type from hash_set<tree> to vec<tree>. (cxx_eval_call_expression): Adjust for save_exprs being a vec instead of hash_set. (cxx_eval_loop_expr): Likewise. Truncate the vector after each removal of SAVE_EXPRs from values. (cxx_eval_constant_expression) <case SAVE_EXPR>: Call safe_push method on save_exprs instead of add. * g++.dg/cpp1y/constexpr-89652.C: New test. From-SVN: r269671
This commit is contained in:
parent
7da0bca130
commit
0ee285909b
@ -1,3 +1,15 @@
|
||||
2019-03-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/89652
|
||||
* constexpr.c (struct constexpr_ctx): Change save_exprs type from
|
||||
hash_set<tree> to vec<tree>.
|
||||
(cxx_eval_call_expression): Adjust for save_exprs being a vec instead
|
||||
of hash_set.
|
||||
(cxx_eval_loop_expr): Likewise. Truncate the vector after each
|
||||
removal of SAVE_EXPRs from values.
|
||||
(cxx_eval_constant_expression) <case SAVE_EXPR>: Call safe_push
|
||||
method on save_exprs instead of add.
|
||||
|
||||
2019-03-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/86521 - C++17 copy elision in initialization by constructor.
|
||||
|
@ -1024,7 +1024,7 @@ struct constexpr_ctx {
|
||||
hash_map<tree,tree> *values;
|
||||
/* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we
|
||||
aren't inside a loop. */
|
||||
hash_set<tree> *save_exprs;
|
||||
vec<tree> *save_exprs;
|
||||
/* The CONSTRUCTOR we're currently building up for an aggregate
|
||||
initializer. */
|
||||
tree ctor;
|
||||
@ -1831,7 +1831,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||
/* Track the callee's evaluated SAVE_EXPRs so that we can forget
|
||||
their values after the call. */
|
||||
constexpr_ctx ctx_with_save_exprs = *ctx;
|
||||
hash_set<tree> save_exprs;
|
||||
auto_vec<tree, 10> save_exprs;
|
||||
ctx_with_save_exprs.save_exprs = &save_exprs;
|
||||
ctx_with_save_exprs.call = &new_call;
|
||||
|
||||
@ -1862,9 +1862,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||
}
|
||||
|
||||
/* Forget the saved values of the callee's SAVE_EXPRs. */
|
||||
for (hash_set<tree>::iterator iter = save_exprs.begin();
|
||||
iter != save_exprs.end(); ++iter)
|
||||
ctx_with_save_exprs.values->remove (*iter);
|
||||
unsigned int i;
|
||||
tree save_expr;
|
||||
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
|
||||
ctx_with_save_exprs.values->remove (save_expr);
|
||||
|
||||
/* Remove the parms/result from the values map. Is it worth
|
||||
bothering to do this when the map itself is only live for
|
||||
@ -4190,7 +4191,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
hash_set<tree> save_exprs;
|
||||
auto_vec<tree, 10> save_exprs;
|
||||
new_ctx.save_exprs = &save_exprs;
|
||||
do
|
||||
{
|
||||
@ -4234,9 +4235,11 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||
}
|
||||
|
||||
/* Forget saved values of SAVE_EXPRs. */
|
||||
for (hash_set<tree>::iterator iter = save_exprs.begin();
|
||||
iter != save_exprs.end(); ++iter)
|
||||
new_ctx.values->remove (*iter);
|
||||
unsigned int i;
|
||||
tree save_expr;
|
||||
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
|
||||
new_ctx.values->remove (save_expr);
|
||||
save_exprs.truncate (0);
|
||||
|
||||
if (++count >= constexpr_loop_limit)
|
||||
{
|
||||
@ -4256,9 +4259,10 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||
&& !*non_constant_p);
|
||||
|
||||
/* Forget saved values of SAVE_EXPRs. */
|
||||
for (hash_set<tree>::iterator iter = save_exprs.begin();
|
||||
iter != save_exprs.end(); ++iter)
|
||||
new_ctx.values->remove (*iter);
|
||||
unsigned int i;
|
||||
tree save_expr;
|
||||
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
|
||||
new_ctx.values->remove (save_expr);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
@ -4616,7 +4620,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||
non_constant_p, overflow_p);
|
||||
ctx->values->put (t, r);
|
||||
if (ctx->save_exprs)
|
||||
ctx->save_exprs->add (t);
|
||||
ctx->save_exprs->safe_push (t);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-03-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/89652
|
||||
* g++.dg/cpp1y/constexpr-89652.C: New test.
|
||||
|
||||
2019-03-13 Harald Anlauf <anlauf@gmx.de>
|
||||
|
||||
PR fortran/87045
|
||||
|
36
gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C
Normal file
36
gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C
Normal file
@ -0,0 +1,36 @@
|
||||
// PR c++/89652
|
||||
// { dg-do compile { target c++14 } }
|
||||
// { dg-options "" }
|
||||
|
||||
template <typename T> constexpr auto foo (T &e) { return e.foo (); }
|
||||
template <typename T> constexpr auto bar (T &e) { return foo (e); }
|
||||
template <typename T, int N> struct A { typedef T a[N]; };
|
||||
template <typename T, unsigned long N> struct B {
|
||||
typedef T *b;
|
||||
typename A<T, N>::a d;
|
||||
constexpr b foo () { return d; }
|
||||
};
|
||||
template <typename> struct C { long m; };
|
||||
struct D { long n; };
|
||||
template <typename, unsigned long> struct E {
|
||||
B<C<int>, 1>::b p;
|
||||
constexpr D operator* () { return {p->m}; }
|
||||
constexpr E operator++ (int) { auto a{*this}; ++p; return a; }
|
||||
};
|
||||
template <typename T, unsigned long N>
|
||||
constexpr bool operator!= (E<T, N> a, E<T, N>) { return a.p; }
|
||||
template <unsigned long N, typename T, unsigned long M>
|
||||
constexpr auto baz (B<T, M> s, B<D, N>)
|
||||
{
|
||||
B<D, M> t{};
|
||||
auto q{foo (t)};
|
||||
using u = E<T, M>;
|
||||
auto v = u{bar (s)};
|
||||
auto w = u{};
|
||||
while (v != w)
|
||||
*q++ = *v++;
|
||||
return t;
|
||||
}
|
||||
constexpr auto a = B<C<int>, 5>{};
|
||||
auto b = B<D, 0>{};
|
||||
auto c = baz (a, b);
|
Loading…
x
Reference in New Issue
Block a user