aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-03-14 09:13:09 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-03-14 09:13:09 +0100
commit0ee285909bcef729415995e16c68e8713c59996f (patch)
tree9b58ba70a1a25f6b7a582ab1da5e135537361b8c
parent7da0bca130c98fa219b81f58da44f5e1222b321a (diff)
downloadgcc-0ee285909bcef729415995e16c68e8713c59996f.zip
gcc-0ee285909bcef729415995e16c68e8713c59996f.tar.gz
gcc-0ee285909bcef729415995e16c68e8713c59996f.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/constexpr.c30
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C36
4 files changed, 70 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1164652..7c0b4f4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index b2b575d..68e78d0 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b7550a2..73ac51a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C
new file mode 100644
index 0000000..8d0631e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89652.C
@@ -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);