Commit 0ee28590 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 7da0bca1
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> 2019-03-13 Jason Merrill <jason@redhat.com>
PR c++/86521 - C++17 copy elision in initialization by constructor. PR c++/86521 - C++17 copy elision in initialization by constructor.
......
...@@ -1024,7 +1024,7 @@ struct constexpr_ctx { ...@@ -1024,7 +1024,7 @@ struct constexpr_ctx {
hash_map<tree,tree> *values; hash_map<tree,tree> *values;
/* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we /* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we
aren't inside a loop. */ aren't inside a loop. */
hash_set<tree> *save_exprs; vec<tree> *save_exprs;
/* The CONSTRUCTOR we're currently building up for an aggregate /* The CONSTRUCTOR we're currently building up for an aggregate
initializer. */ initializer. */
tree ctor; tree ctor;
...@@ -1831,7 +1831,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, ...@@ -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 /* Track the callee's evaluated SAVE_EXPRs so that we can forget
their values after the call. */ their values after the call. */
constexpr_ctx ctx_with_save_exprs = *ctx; 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.save_exprs = &save_exprs;
ctx_with_save_exprs.call = &new_call; ctx_with_save_exprs.call = &new_call;
...@@ -1862,9 +1862,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, ...@@ -1862,9 +1862,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
} }
/* Forget the saved values of the callee's SAVE_EXPRs. */ /* Forget the saved values of the callee's SAVE_EXPRs. */
for (hash_set<tree>::iterator iter = save_exprs.begin(); unsigned int i;
iter != save_exprs.end(); ++iter) tree save_expr;
ctx_with_save_exprs.values->remove (*iter); 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 /* Remove the parms/result from the values map. Is it worth
bothering to do this when the map itself is only live for 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, ...@@ -4190,7 +4191,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
hash_set<tree> save_exprs; auto_vec<tree, 10> save_exprs;
new_ctx.save_exprs = &save_exprs; new_ctx.save_exprs = &save_exprs;
do do
{ {
...@@ -4234,9 +4235,11 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, ...@@ -4234,9 +4235,11 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
} }
/* Forget saved values of SAVE_EXPRs. */ /* Forget saved values of SAVE_EXPRs. */
for (hash_set<tree>::iterator iter = save_exprs.begin(); unsigned int i;
iter != save_exprs.end(); ++iter) tree save_expr;
new_ctx.values->remove (*iter); FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
new_ctx.values->remove (save_expr);
save_exprs.truncate (0);
if (++count >= constexpr_loop_limit) if (++count >= constexpr_loop_limit)
{ {
...@@ -4256,9 +4259,10 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, ...@@ -4256,9 +4259,10 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
&& !*non_constant_p); && !*non_constant_p);
/* Forget saved values of SAVE_EXPRs. */ /* Forget saved values of SAVE_EXPRs. */
for (hash_set<tree>::iterator iter = save_exprs.begin(); unsigned int i;
iter != save_exprs.end(); ++iter) tree save_expr;
new_ctx.values->remove (*iter); FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
new_ctx.values->remove (save_expr);
return NULL_TREE; return NULL_TREE;
} }
...@@ -4616,7 +4620,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -4616,7 +4620,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p); non_constant_p, overflow_p);
ctx->values->put (t, r); ctx->values->put (t, r);
if (ctx->save_exprs) if (ctx->save_exprs)
ctx->save_exprs->add (t); ctx->save_exprs->safe_push (t);
} }
break; break;
......
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> 2019-03-13 Harald Anlauf <anlauf@gmx.de>
PR fortran/87045 PR fortran/87045
......
// 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);
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