summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/vtable-key-function-arm.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-01-25 22:31:03 +0000
committerJohn McCall <rjmccall@apple.com>2013-01-25 22:31:03 +0000
commitd5617eeafc93209a26b9f88276c88cf997c3a0a7 (patch)
tree43c9295b24bd0ef8787299fa08681e041ef4697b /test/CodeGenCXX/vtable-key-function-arm.cpp
parentb8b2c9da87e7d70a1679db026f40548b3192b705 (diff)
The standard ARM C++ ABI dictates that inline functions are
never key functions. We did not implement that rule for the iOS ABI, which was driven by what was implemented in gcc-4.2. However, implement it now for other ARM-based platforms. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173515 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/vtable-key-function-arm.cpp')
-rw-r--r--test/CodeGenCXX/vtable-key-function-arm.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/test/CodeGenCXX/vtable-key-function-arm.cpp b/test/CodeGenCXX/vtable-key-function-arm.cpp
new file mode 100644
index 0000000000..08efe8a141
--- /dev/null
+++ b/test/CodeGenCXX/vtable-key-function-arm.cpp
@@ -0,0 +1,307 @@
+// RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s
+
+// The 'a' variants ask for the v-table first.
+// The 'b' variants ask for the v-table second.
+// The 'c' variants ask for the v-table third.
+// We do a separate CHECK-LATE pass because the RTTI defintion gets
+// changed after the fact, which causes reordering of the globals.
+
+// These are not separated into namespaces because the way that Sema
+// currently reports namespaces to IR-generation (i.e., en masse for
+// the entire namespace at once) subverts the ordering that we're
+// trying to test.
+
+namespace std { class type_info; }
+extern void use(const std::type_info &rtti);
+
+/*** Test0a ******************************************************************/
+
+struct Test0a {
+ Test0a();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// V-table should be defined externally.
+Test0a::Test0a() { use(typeid(Test0a)); }
+// CHECK: @_ZTV6Test0a = external unnamed_addr constant
+// CHECK: @_ZTI6Test0a = external constant
+
+// This is still not a key function.
+void Test0a::foo() {}
+
+/*** Test0b ******************************************************************/
+
+struct Test0b {
+ Test0b();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// This is still not a key function.
+void Test0b::foo() {}
+
+// V-table should be defined externally.
+Test0b::Test0b() { use(typeid(Test0b)); }
+// CHECK: @_ZTV6Test0b = external unnamed_addr constant
+// CHECK: @_ZTI6Test0b = external constant
+
+/*** Test1a ******************************************************************/
+
+struct Test1a {
+ Test1a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined externally.
+Test1a::Test1a() { use(typeid(Test1a)); }
+// CHECK: @_ZTV6Test1a = external unnamed_addr constant
+// CHECK: @_ZTI6Test1a = external constant
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+inline void Test1a::foo() {}
+
+/*** Test1b ******************************************************************/
+
+struct Test1b {
+ Test1b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+inline void Test1b::foo() {}
+
+// V-table should be defined externally.
+Test1b::Test1b() { use(typeid(Test1b)); }
+// CHECK: @_ZTV6Test1b = external unnamed_addr constant
+// CHECK: @_ZTI6Test1b = external constant
+
+/*** Test2a ******************************************************************/
+
+struct Test2a {
+ Test2a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with strong linkage.
+Test2a::Test2a() { use(typeid(Test2a)); }
+// CHECK: @_ZTV6Test2a = unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2a = constant
+// CHECK-LATE: @_ZTI6Test2a = unnamed_addr constant
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2a::bar() {}
+inline void Test2a::foo() {}
+
+/*** Test2b ******************************************************************/
+
+struct Test2b {
+ Test2b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2b::bar() {}
+
+// V-table should be defined with strong linkage.
+Test2b::Test2b() { use(typeid(Test2b)); }
+// CHECK: @_ZTV6Test2b = unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2b = constant
+// CHECK-LATE: @_ZTI6Test2b = unnamed_addr constant
+
+inline void Test2b::foo() {}
+
+/*** Test2c ******************************************************************/
+
+struct Test2c {
+ Test2c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2c::bar() {}
+inline void Test2c::foo() {}
+
+// V-table should be defined with strong linkage.
+Test2c::Test2c() { use(typeid(Test2c)); }
+// CHECK: @_ZTV6Test2c = unnamed_addr constant
+// CHECK: @_ZTS6Test2c = constant
+// CHECK: @_ZTI6Test2c = unnamed_addr constant
+
+/*** Test3a ******************************************************************/
+
+struct Test3a {
+ Test3a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+Test3a::Test3a() { use(typeid(Test3a)); }
+// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+inline void Test3a::bar() {}
+inline void Test3a::foo() {}
+
+/*** Test3b ******************************************************************/
+
+struct Test3b {
+ Test3b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+inline void Test3b::bar() {}
+
+// V-table should be defined with weak linkage.
+Test3b::Test3b() { use(typeid(Test3b)); }
+// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant
+
+inline void Test3b::foo() {}
+
+/*** Test3c ******************************************************************/
+
+struct Test3c {
+ Test3c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+inline void Test3c::bar() {}
+inline void Test3c::foo() {}
+
+// V-table should be defined with weak linkage.
+Test3c::Test3c() { use(typeid(Test3c)); }
+// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test3c = linkonce_odr constant
+// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant
+
+/*** Test4a ******************************************************************/
+
+template <class T> struct Test4a {
+ Test4a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+template <> Test4a<int>::Test4a() { use(typeid(Test4a)); }
+// CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4aIiE = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4a<int>::bar() {}
+template <> inline void Test4a<int>::foo() {}
+
+/*** Test4b ******************************************************************/
+
+template <class T> struct Test4b {
+ Test4b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4b<int>::bar() {}
+
+// V-table should be defined with weak linkage.
+template <> Test4b<int>::Test4b() { use(typeid(Test4b)); }
+// CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4bIiE = linkonce_odr unnamed_addr constant
+
+template <> inline void Test4b<int>::foo() {}
+
+/*** Test4c ******************************************************************/
+
+template <class T> struct Test4c {
+ Test4c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4c<int>::bar() {}
+template <> inline void Test4c<int>::foo() {}
+
+// V-table should be defined with weak linkage.
+template <> Test4c<int>::Test4c() { use(typeid(Test4c)); }
+// CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4cIiE = linkonce_odr unnamed_addr constant
+
+/*** Test5a ******************************************************************/
+
+template <class T> struct Test5a {
+ Test5a();
+ virtual void foo();
+ virtual void bar();
+};
+
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5a<int>::foo();
+
+// V-table should be defined with weak linkage.
+template <> Test5a<int>::Test5a() { use(typeid(Test5a)); }
+// CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5aIiE = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar() {}
+template <> inline void Test5a<int>::foo() {}
+
+/*** Test5b ******************************************************************/
+
+template <class T> struct Test5b {
+ Test5b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5b<int>::bar() {}
+
+// V-table should be defined with weak linkage.
+template <> Test5b<int>::Test5b() { use(typeid(Test5b)); }
+// CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5bIiE = linkonce_odr unnamed_addr constant
+
+template <> inline void Test5a<int>::foo();
+template <> inline void Test5b<int>::foo() {}
+
+/*** Test5c ******************************************************************/
+
+template <class T> struct Test5c {
+ Test5c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5a<int>::foo();
+template <> inline void Test5c<int>::bar() {}
+template <> inline void Test5c<int>::foo() {}
+
+// V-table should be defined with weak linkage.
+template <> Test5c<int>::Test5c() { use(typeid(Test5c)); }
+// CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5cIiE = linkonce_odr unnamed_addr constant