This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, PR 52939] Gracefully deal with fold_ctor_reference returning NULL during devirtualization
- From: Martin Jambor <mjambor at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Guenther <rguenther at suse dot de>
- Date: Fri, 13 Apr 2012 15:52:36 +0200
- Subject: [PATCH, PR 52939] Gracefully deal with fold_ctor_reference returning NULL during devirtualization
Hi,
currently we ICE when attempting to devirtualize a call to a virtual
method introduced in a descendant but with a base which is an ancestor
which does not have it. This is because fold_ctor_reference returns
constant zero when it cannot find the particular value in the provided
constructor which is something gimple_get_virt_method_for_binfo cannot
cope with. The patch below avoids it by simply testing for that
value and bailing out.
Bootstrapped and tested on x86_64-linux, OK for trunk?
Thanks,
Martin
2012-04-12 Martin Jambor <mjambor@suse.cz>
PR middle-end/52939
* gimple-fold.c (gimple_get_virt_method_for_binfo): Bail out if
fold_ctor_reference returns a zero constant.
* testsuite/g++.dg/ipa/pr52939.C: New test.
Index: src/gcc/gimple-fold.c
===================================================================
--- src.orig/gcc/gimple-fold.c
+++ src/gcc/gimple-fold.c
@@ -3087,7 +3087,7 @@ gimple_get_virt_method_for_binfo (HOST_W
offset += token * size;
fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
offset, size);
- if (!fn)
+ if (!fn || integer_zerop (fn))
return NULL_TREE;
gcc_assert (TREE_CODE (fn) == ADDR_EXPR
|| TREE_CODE (fn) == FDESC_EXPR);
Index: src/gcc/testsuite/g++.dg/ipa/pr52939.C
===================================================================
--- /dev/null
+++ src/gcc/testsuite/g++.dg/ipa/pr52939.C
@@ -0,0 +1,58 @@
+/* Verify that we do not ICE on invalid devirtualizations (which might
+ be OK at run-time because never executed). */
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-early-inlining -fno-inline" } */
+
+extern "C" void abort (void);
+
+class A
+{
+public:
+ int data;
+ virtual int foo (int i);
+};
+
+class B : public A
+{
+public:
+ virtual int foo (int i);
+ virtual int bar (int i);
+};
+
+int A::foo (int i)
+{
+ return i + 1;
+}
+
+int B::foo (int i)
+{
+ return i + 2;
+}
+
+int B::bar (int i)
+{
+ return i + 3;
+}
+
+static int middleman (class A *obj, int i)
+{
+ class B *b = (class B *) obj;
+
+ if (i != 1)
+ return b->bar (i);
+ else
+ return i;
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+ return 1;
+}
+
+int main (int argc, char *argv[])
+{
+ class A o;
+ if (middleman (&o, get_input ()) != 1)
+ abort ();
+ return 0;
+}