aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/ipa/devirt-33.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/ipa/devirt-33.C')
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-33.C78
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-33.C b/gcc/testsuite/g++.dg/ipa/devirt-33.C
new file mode 100644
index 00000000000..970a96b88d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/devirt-33.C
@@ -0,0 +1,78 @@
+/* Verify we do not devirtualize wrongly to __cxa_pure_virtual */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -std=c++11" } */
+
+
+inline void* operator new(__SIZE_TYPE__ s, void* buf) throw() {
+ return buf;
+}
+
+class A {
+
+private:
+ struct Base {
+ virtual ~Base() {}
+ virtual Base *Clone(void *buf) const = 0;
+ virtual float *Allocate(__SIZE_TYPE__ count) = 0;
+ };
+
+ struct Value : Base {
+ virtual ~Value (){}
+ Base *Clone(void* buf) const override {
+ return new (buf) Value();
+ }
+
+ float *Allocate(__SIZE_TYPE__ count) override {
+ return new float[count];
+ }
+ };
+
+public:
+ A() {
+ new (buffer_) Value();
+ }
+ A(const A& other) {
+ other.ptr()->Clone(buffer_);
+ }
+
+ float *Allocate() {
+ return ptr()->Allocate(100);
+ }
+ const Base *ptr() const { return reinterpret_cast<const Base*>(buffer_);}
+ Base *ptr() { return reinterpret_cast< Base*>(buffer_);}
+
+private:
+ alignas(16) char buffer_[1024];
+};
+
+
+struct B {
+ B (const A& a) : a_(a) {
+ buff_ = a_.Allocate();
+ }
+
+ float *buff_;
+ A a_;
+};
+
+struct Dummy {
+ int i;
+};
+
+struct D : public Dummy {
+ __attribute__((noinline)) D( const A&a);
+
+ B b_;
+};
+
+D::D(const A&a) : b_(a) {}
+
+int main()
+{
+ A a;
+ D d(a);
+
+ return 0;
+}
+