This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix ICE in ipa-devirt


Hi,
the two testcases show somewhat crazy layout of C++ object that goes
in order base1,base2,virtual_base_of_base1
this confuses the walk in get_binfo_at_offset while looking for
virtual_base_of_base1 to look into base2 instead of base1.

It seems that in the case of virtual inheritance we simply want to do
fully recursive search for the given binfo - it is not that expensiv ebecause
bases are not many.

Bootstrapped/regtested x86_64-linux.  Will commit it today after rebuilding
firefox.

	PR IPA/60871
	PR IPA/64139
	* tree.c (lookup_binfo_at_offset): New function.
	(get_binfo_at_offset): Use it.

	* g++.dg/torture/pr64139.C: New testcase.
	* g++.dg/torture/pr60871.C: Likewise.
Index: tree.c
===================================================================
--- tree.c	(revision 220142)
+++ tree.c	(working copy)
@@ -11990,6 +11990,23 @@ type_in_anonymous_namespace_p (const_tre
   return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)));
 }
 
+/* Lookup sub-BINFO of BINFO of TYPE at offset POS.  */
+
+tree
+lookup_binfo_at_offset (tree binfo, tree type, HOST_WIDE_INT pos)
+{
+  unsigned int i;
+  tree base_binfo, b;
+
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+    if (pos == tree_to_shwi (BINFO_OFFSET (base_binfo))
+	&& types_same_for_odr (TREE_TYPE (base_binfo), type))
+      return base_binfo;
+    else if ((b = lookup_binfo_at_offset (base_binfo, type, pos)) != NULL)
+      return b;
+  return NULL;
+}
+
 /* Try to find a base info of BINFO that would have its field decl at offset
    OFFSET within the BINFO type and which is of EXPECTED_TYPE.  If it can be
    found, return, otherwise return NULL_TREE.  */
@@ -12027,42 +12044,22 @@ get_binfo_at_offset (tree binfo, HOST_WI
 	 represented in the binfo for the derived class.  */
       else if (offset != 0)
 	{
-	  tree base_binfo, binfo2 = binfo;
-
-	  /* Find BINFO corresponding to FLD.  This is bit harder
-	     by a fact that in virtual inheritance we may need to walk down
-	     the non-virtual inheritance chain.  */
-	  while (true)
-	    {
-	      tree containing_binfo = NULL, found_binfo = NULL;
-	      for (i = 0; BINFO_BASE_ITERATE (binfo2, i, base_binfo); i++)
-		if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
-		  {
-		    found_binfo = base_binfo;
-		    break;
-		  }
-		else
-		  if ((tree_to_shwi (BINFO_OFFSET (base_binfo)) 
-		       - tree_to_shwi (BINFO_OFFSET (binfo)))
-		      * BITS_PER_UNIT < pos
-		      /* Rule out types with no virtual methods or we can get confused
-			 here by zero sized bases.  */
-		      && TYPE_BINFO (BINFO_TYPE (base_binfo))
-		      && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (base_binfo)))
-		      && (!containing_binfo
-			  || (tree_to_shwi (BINFO_OFFSET (containing_binfo))
-			      < tree_to_shwi (BINFO_OFFSET (base_binfo)))))
-		    containing_binfo = base_binfo;
-	      if (found_binfo)
-		{
-		  binfo = found_binfo;
-		  break;
-		}
-	      if (!containing_binfo)
-		return NULL_TREE;
-	      binfo2 = containing_binfo;
-	    }
-	}
+	  tree found_binfo = NULL, base_binfo;
+	  int offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
+			/ BITS_PER_UNIT);
+
+	  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+	    if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == offset
+		&& types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
+	      {
+		found_binfo = base_binfo;
+		break;
+	      }
+	  if (found_binfo)
+	    binfo = found_binfo;
+	  else
+	    binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld), offset);
+	 }
 
       type = TREE_TYPE (fld);
       offset -= pos;
Index: testsuite/g++.dg/torture/pr64139.C
===================================================================
--- testsuite/g++.dg/torture/pr64139.C	(revision 0)
+++ testsuite/g++.dg/torture/pr64139.C	(revision 0)
@@ -0,0 +1,34 @@
+// { dg-do compile }
+class IObject {
+public:
+  virtual ~IObject();
+};
+class A {
+  virtual int m_fn1();
+};
+class B {
+public:
+  virtual int m_fn2(B) const;
+};
+class D : IObject, public virtual B {};
+class G : public D, A {
+public:
+  G(A);
+};
+class F : B {
+  friend class C;
+};
+class C {
+  void m_fn3(const IObject &, int &);
+  void m_fn4(const B &, int &);
+};
+A a;
+void C::m_fn3(const IObject &, int &p2) {
+  G r(a);
+  m_fn4(r, p2);
+}
+void C::m_fn4(const B &p1, int &) {
+  F b;
+  p1.m_fn2(b);
+}
+
Index: testsuite/g++.dg/torture/pr60871.C
===================================================================
--- testsuite/g++.dg/torture/pr60871.C	(revision 0)
+++ testsuite/g++.dg/torture/pr60871.C	(revision 0)
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+struct A
+{
+  virtual void m_fn1 ();
+  int m_local;
+};
+class C : virtual public A
+{
+};
+struct B
+{
+  A *m_g;
+
+  B (A *p1) : m_g (p1) { m_g->m_fn1 (); }
+};
+struct C7
+{
+  virtual ~C7 ();
+};
+class D : public C, C7
+{
+};
+struct F : D
+{
+  F (int);
+
+  static void m_fn2 ()
+  {
+    F a (0);
+    B b (&a);
+  }
+};
+void fn1 () { F::m_fn2 (); }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]