From 952eddef9aff85b1e92626e89baaf7a360e2ac85 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Sun, 22 Dec 2013 00:07:40 +0000
Subject: Vendor import of clang release_34 branch r197841 (effectively, 3.4
 RC3): https://llvm.org/svn/llvm-project/cfe/branches/release_34@197841

---
 test/CodeGenCXX/ctor-dtor-alias.cpp | 163 ++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)
 create mode 100644 test/CodeGenCXX/ctor-dtor-alias.cpp

(limited to 'test/CodeGenCXX/ctor-dtor-alias.cpp')

diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
new file mode 100644
index 0000000..235d165
--- /dev/null
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
+
+// RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \
+// RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s
+
+namespace test1 {
+// test that we don't produce an alias when the destructor is weak_odr. The
+// reason to avoid it that another TU might have no explicit template
+// instantiation definition or declaration, causing it to to output only
+// one of the destructors as linkonce_odr, producing a different comdat.
+
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC1Ev
+
+template <typename T> struct foobar {
+  foobar() {}
+};
+
+template struct foobar<void>;
+}
+
+namespace test2 {
+// test that when the destrucor is linkonce_odr we just replace every use of
+// C1 with C2.
+
+// CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev(
+// CHECK-DAG: call void @_ZN5test26foobarIvEC2Ev
+void g();
+template <typename T> struct foobar {
+  foobar() { g(); }
+};
+foobar<void> x;
+}
+
+namespace test3 {
+// test that instead of an internal alias we just use the other destructor
+// directly.
+
+// CHECK-DAG: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
+// CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
+namespace {
+struct A {
+  ~A() {}
+};
+
+struct B : public A {};
+}
+
+B x;
+}
+
+namespace test4 {
+  // Test that we don't produce aliases from B to A. We cannot because we cannot
+  // guarantee that they will be present in every TU. Instead, we just call
+  // A's destructor directly.
+
+  // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev(
+  // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
+
+  // test that we don't do this optimization at -O0 so that the debugger can
+  // see both destructors.
+  // NOOPT-DAG: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
+  // NOOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev
+  struct A {
+    virtual ~A() {}
+  };
+  struct B : public A{
+    ~B() {}
+  };
+  B X;
+}
+
+namespace test5 {
+  // similar to test4, but with an internal B.
+
+  // CHECK-DAG: define linkonce_odr void @_ZN5test51AD2Ev(
+  // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
+  struct A {
+    virtual ~A() {}
+  };
+  namespace {
+  struct B : public A{
+    ~B() {}
+  };
+  }
+  B X;
+}
+
+namespace test6 {
+  // Test that we use ~A directly, even when ~A is not defined. The symbol for
+  // ~B would have been internal and still contain a reference to ~A.
+  struct A {
+    virtual ~A();
+  };
+  namespace {
+  struct B : public A {
+    ~B() {}
+  };
+  }
+  B X;
+  // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
+}
+
+namespace test7 {
+  // Test that we don't produce an alias from ~B to ~A<int> (or crash figuring
+  // out if we should).
+  // pr17875.
+  // CHECK-DAG: define void @_ZN5test71BD2Ev
+  template <typename> struct A {
+    ~A() {}
+  };
+  class B : A<int> {
+    ~B();
+  };
+  template class A<int>;
+  B::~B() {}
+}
+
+namespace test8 {
+  // Test that we replace ~zed with ~bar which is an alias to ~foo.
+  // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
+  // CHECK-DAG: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
+  struct foo {
+    ~foo();
+  };
+  foo::~foo() {}
+  struct bar : public foo {
+    ~bar();
+  };
+  bar::~bar() {}
+  struct zed : public bar {};
+  zed foo;
+}
+
+// CHECK-RAUW: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
+// r194296 replaced C::~C with B::~B without emitting the later.
+
+class A {
+public:
+  A(int);
+  virtual ~A();
+};
+
+template <class>
+class B : A {
+public:
+  B()
+      : A(0) {
+  }
+  __attribute__((always_inline)) ~B() {
+  }
+};
+
+extern template class B<char>;
+
+class C : B<char> {
+};
+
+void
+fn1() {
+  new C;
+}
-- 
cgit v1.1