summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/ipa/devirt-45.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/ipa/devirt-45.C')
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-45.C42
1 files changed, 42 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-45.C b/gcc/testsuite/g++.dg/ipa/devirt-45.C
new file mode 100644
index 0000000000..4616c951d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/devirt-45.C
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining" } */
+struct A {
+ virtual int foo () {return 1;}
+ int wrapfoo () {foo();}
+ A() {wrapfoo();}
+};
+inline void* operator new(__SIZE_TYPE__ s, void* buf) throw() {
+ return buf;
+}
+struct B:A {virtual int foo () {return 2;}};
+
+void dostuff(struct A *);
+
+static void
+test2 (struct A *a)
+{
+ dostuff (a);
+ if (a->foo ()!= 2)
+ __builtin_abort ();
+}
+
+static void
+test (struct A *a)
+{
+ dostuff (a);
+ static_cast<B*>(a)->~B();
+ new(a) B();
+ test2(a);
+}
+
+main()
+{
+ struct B a;
+ dostuff (&a);
+ test (&a);
+}
+
+/* One invocation is A::foo () other is B::foo () even though the type is destroyed and rebuilt in test() */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*A::foo" 1 "inline" } } */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*B::foo" 1 "inline" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */