re PR c++/70906 (ice in add_expr, at tree.c:7925)

PR c++/70906
	PR c++/70933
	* tree-core.h (enum operand_equal_flag): Add OEP_HASH_CHECK.
	* tree.c (inchash::add_expr): If !IS_EXPR_CODE_CLASS (tclass),
	assert flags & OEP_HASH_CHECK, instead of asserting it
	never happens.  Handle TARGET_EXPR.
	* fold-const.c (operand_equal_p): For hash verification,
	or in OEP_HASH_CHECK into flags.

	* g++.dg/opt/pr70906.C: New test.
	* g++.dg/opt/pr70933.C: New test.

From-SVN: r235902
This commit is contained in:
Jakub Jelinek 2016-05-04 22:44:40 +02:00 committed by Jakub Jelinek
parent e4ea422a00
commit 2d1ac15a6a
7 changed files with 130 additions and 4 deletions

View File

@ -1,3 +1,14 @@
2016-05-04 Jakub Jelinek <jakub@redhat.com>
PR c++/70906
PR c++/70933
* tree-core.h (enum operand_equal_flag): Add OEP_HASH_CHECK.
* tree.c (inchash::add_expr): If !IS_EXPR_CODE_CLASS (tclass),
assert flags & OEP_HASH_CHECK, instead of asserting it
never happens. Handle TARGET_EXPR.
* fold-const.c (operand_equal_p): For hash verification,
or in OEP_HASH_CHECK into flags.
2016-05-04 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-coalesce.c (gimple_can_coalesce_p): Fix reference in head

View File

@ -2758,8 +2758,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
if (arg0 != arg1)
{
inchash::hash hstate0 (0), hstate1 (0);
inchash::add_expr (arg0, hstate0, flags);
inchash::add_expr (arg1, hstate1, flags);
inchash::add_expr (arg0, hstate0, flags | OEP_HASH_CHECK);
inchash::add_expr (arg1, hstate1, flags | OEP_HASH_CHECK);
hashval_t h0 = hstate0.end ();
hashval_t h1 = hstate1.end ();
gcc_assert (h0 == h1);

View File

@ -1,5 +1,10 @@
2016-05-04 Jakub Jelinek <jakub@redhat.com>
PR c++/70906
PR c++/70933
* g++.dg/opt/pr70906.C: New test.
* g++.dg/opt/pr70933.C: New test.
* gcc.target/i386/avx512vl-vmovq-1.c: New test.
2016-05-04 Jan Hubicka <hubicka@ucw.cz>

View File

@ -0,0 +1,69 @@
// PR c++/70906
// { dg-do compile { target c++11 } }
// { dg-options "-Wall" }
template <typename> struct B;
template <typename U> struct F { typedef U *t; };
template <class> struct D {};
template <class VP> struct L {
typedef VP np;
typedef typename F<D<VP>>::t cnp;
};
struct P { typedef L<void *> nt; };
template <class N> struct I { typedef typename N::template A<int> t; };
template <class O1> struct Q { typedef typename I<O1>::t t; };
template <class T, class Hook, Hook T::*> struct G;
template <typename P, typename M, M P::*PM>
struct mh {
template <class> struct A { typedef G<P, M, PM> pvt; };
};
template <typename T> struct B<T *> { static T pt(T); };
struct R : public D<void *> { typedef P ht; };
class lmh : public R {};
template <class T, class Hook, Hook T::*P> struct G {
typedef Hook Ht;
typedef typename Ht::ht::nt nt;
typedef T vt;
typedef typename nt::np np;
typedef typename nt::cnp cnp;
static np tnp(T &);
static cnp tnp(const T &p1) {
B<cnp>::pt(static_cast<const Ht &>(p1.*P));
return cnp ();
}
};
template <class T, class S> struct K {
template <S> struct J;
template <class U> static int foo(J<U::tnp> *, int);
static const int c = sizeof(foo<T>(0, 0));
};
template <class V> struct W1 {
typedef typename V::vt vt;
static const bool value = K<V, typename V::np (*)(vt &)>::c == K<V, typename V::cnp (*)(const vt &)>::c;
};
template <class V> struct O {
static const bool svt = W1<V>::value;
};
template <bool> struct M {};
template <class V> class C {
static const bool svt = O<V>::svt;
M<svt> m;
};
template <class V> struct H {
C<V> bar();
};
template <class O1> struct ml {
typedef typename Q<O1>::t po;
typedef H<typename po::pvt> t;
};
template <class O1> class list : public ml<O1>::t {};
struct N {
struct IV { lmh hk; };
typedef list<mh<IV, lmh, &IV::hk>> ISL;
friend void fn1(int &, N const &);
};
void fn1(int &, N const &) {
N::ISL xl;
for (xl.bar();;)
;
}

View File

@ -0,0 +1,29 @@
// PR c++/70933
// { dg-do compile }
// { dg-options "-Wsequence-point" }
struct A
{
A (const char *);
};
template <class T>
struct B
{
typedef T U;
U &baz (const A &);
};
template <class T>
void
bar ()
{
B<T> b;
T &p = b.baz ("p1") = T(4);
}
void
foo ()
{
bar<unsigned> ();
}

View File

@ -767,7 +767,9 @@ enum operand_equal_flag {
OEP_MATCH_SIDE_EFFECTS = 4,
OEP_ADDRESS_OF = 8,
/* Internal within operand_equal_p: */
OEP_NO_HASH_CHECK = 16
OEP_NO_HASH_CHECK = 16,
/* Internal within inchash::add_expr: */
OEP_HASH_CHECK = 32
};
/* Enum and arrays used for tree allocation stats.

View File

@ -7915,9 +7915,12 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
&& integer_zerop (TREE_OPERAND (t, 1)))
inchash::add_expr (TREE_OPERAND (TREE_OPERAND (t, 0), 0),
hstate, flags);
/* Don't ICE on FE specific trees, or their arguments etc.
during operand_equal_p hash verification. */
else if (!IS_EXPR_CODE_CLASS (tclass))
gcc_assert (flags & OEP_HASH_CHECK);
else
{
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
unsigned int sflags = flags;
hstate.add_object (code);
@ -7966,6 +7969,13 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
hstate.add_int (CALL_EXPR_IFN (t));
break;
case TARGET_EXPR:
/* For TARGET_EXPR, just hash on the TARGET_EXPR_SLOT.
Usually different TARGET_EXPRs just should use
different temporaries in their slots. */
inchash::add_expr (TARGET_EXPR_SLOT (t), hstate, flags);
return;
default:
break;
}