re PR c++/70906 (ice in add_expr, at tree.c:7925)
authorJakub Jelinek <jakub@redhat.com>
Wed, 4 May 2016 20:44:40 +0000 (22:44 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 4 May 2016 20:44:40 +0000 (22:44 +0200)
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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr70906.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/pr70933.C [new file with mode: 0644]
gcc/tree-core.h
gcc/tree.c

index 898de7ee914f57e6e1ebf9273787bd9a6d40d0ce..d1745531864390ecaecc86201309299675f71242 100644 (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
index 416ec5d7a840fc944b01aa2dcfa747b7d23b633a..9ef43bf22590a0ce3b225dcaf304a4e68ece7eaf 100644 (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);
index ee63d45bd9ceda2346a1ab2ed8cddd4af8b017aa..ea73617155fcb2606782ac535e76f8f801e10358 100644 (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>
diff --git a/gcc/testsuite/g++.dg/opt/pr70906.C b/gcc/testsuite/g++.dg/opt/pr70906.C
new file mode 100644 (file)
index 0000000..19c91cd
--- /dev/null
@@ -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();;)
+    ;
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr70933.C b/gcc/testsuite/g++.dg/opt/pr70933.C
new file mode 100644 (file)
index 0000000..f664d45
--- /dev/null
@@ -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> ();
+}
index 6d573d7b6d290874945eff0e18249b0895a84525..ea832fa5344ebad466bfab02054fb090212b8f7b 100644 (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.
index ebec112d4b1560372179f10357ad7e8b2dd1be07..c5653372f18d212ee48c691e1344c3c3a2a27a11 100644 (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;
            }