| 1 | // RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -std=c++11 -o - | FileCheck %s |
| 2 | // RUN: %clang_cc1 %s -emit-llvm -triple i686-linux-gnu -std=c++11 -o - | FileCheck %s |
| 3 | // RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -std=c++11 -o - | FileCheck %s |
| 4 | // RUN: %clang_cc1 %s -emit-llvm -triple powerpc64le-unknown-linux-gnu -std=c++11 -o - | FileCheck %s |
| 5 | |
| 6 | struct __attribute__((abi_tag("A", "B"))) A { }; |
| 7 | |
| 8 | struct B: A { }; |
| 9 | |
| 10 | template<class T> |
| 11 | |
| 12 | struct C { |
| 13 | }; |
| 14 | |
| 15 | struct D { A* p; }; |
| 16 | |
| 17 | template<class T> |
| 18 | struct __attribute__((abi_tag("C", "D"))) E { |
| 19 | }; |
| 20 | |
| 21 | struct __attribute__((abi_tag("A", "B"))) F { }; |
| 22 | |
| 23 | A a1; |
| 24 | // CHECK-DAG: @_Z2a1B1AB1B = |
| 25 | |
| 26 | __attribute__((abi_tag("C", "D"))) |
| 27 | A a2; |
| 28 | // CHECK-DAG: @_Z2a2B1AB1BB1CB1D = |
| 29 | |
| 30 | B a3; |
| 31 | // CHECK-DAG: @a3 = |
| 32 | |
| 33 | C<A> a4; |
| 34 | // CHECK-DAG: @_Z2a4B1AB1B = |
| 35 | |
| 36 | D a5; |
| 37 | // CHECK-DAG: @a5 = |
| 38 | |
| 39 | E<int> a6; |
| 40 | // CHECK-DAG: @_Z2a6B1CB1D = |
| 41 | |
| 42 | E<A> a7; |
| 43 | // CHECK-DAG: @_Z2a7B1AB1BB1CB1D = |
| 44 | |
| 45 | template<> |
| 46 | struct E<float> { |
| 47 | static float a8; |
| 48 | }; |
| 49 | float E<float>::a8; |
| 50 | // CHECK-DAG: @_ZN1EB1CB1DIfE2a8E = |
| 51 | |
| 52 | template<> |
| 53 | struct E<F> { |
| 54 | static bool a9; |
| 55 | }; |
| 56 | bool E<F>::a9; |
| 57 | // CHECK-DAG: @_ZN1EB1CB1DI1FB1AB1BE2a9E = |
| 58 | |
| 59 | struct __attribute__((abi_tag("A", "B"))) A10 { |
| 60 | virtual ~A10() {} |
| 61 | } a10; |
| 62 | // vtable |
| 63 | // CHECK-DAG: @_ZTV3A10B1AB1B = |
| 64 | // typeinfo |
| 65 | // CHECK-DAG: @_ZTI3A10B1AB1B = |
| 66 | |
| 67 | struct __attribute__((abi_tag("A"))) B11 { |
| 68 | static A10 b; |
| 69 | }; |
| 70 | A10 B11::b; |
| 71 | // B11[abi:A]::b[abi:B] |
| 72 | // CHECK-DAG: @_ZN3B11B1A1bB1BE = |
| 73 | |
| 74 | __attribute__ ((abi_tag("C", "D"))) |
| 75 | void* f1() { |
| 76 | return 0; |
| 77 | } |
| 78 | // CHECK-DAG: define {{.*}} @_Z2f1B1CB1Dv( |
| 79 | |
| 80 | __attribute__ ((abi_tag("C", "D"))) |
| 81 | A* f2() { |
| 82 | return 0; |
| 83 | } |
| 84 | // CHECK-DAG: define {{.*}} @_Z2f2B1AB1BB1CB1Dv( |
| 85 | |
| 86 | B* f3() { |
| 87 | return 0; |
| 88 | } |
| 89 | // CHECK-DAG: define {{.*}} @_Z2f3v( |
| 90 | |
| 91 | C<A>* f4() { |
| 92 | return 0; |
| 93 | } |
| 94 | // CHECK-DAG: define {{.*}} @_Z2f4B1AB1Bv( |
| 95 | |
| 96 | D* f5() { |
| 97 | return 0; |
| 98 | } |
| 99 | // CHECK-DAG: define {{.*}} @_Z2f5v( |
| 100 | |
| 101 | E<char>* f6() { |
| 102 | return 0; |
| 103 | } |
| 104 | // CHECK-DAG: define {{.*}} @_Z2f6B1CB1Dv( |
| 105 | |
| 106 | E<A>* f7() { |
| 107 | return 0; |
| 108 | } |
| 109 | // CHECK-DAG: define {{.*}} @_Z2f7B1AB1BB1CB1Dv( |
| 110 | |
| 111 | void f8(E<A>*) { |
| 112 | } |
| 113 | // CHECK-DAG: define {{.*}} @_Z2f8P1EB1CB1DI1AB1AB1BE( |
| 114 | |
| 115 | inline namespace Names1 __attribute__((__abi_tag__)) { |
| 116 | class C1 {}; |
| 117 | } |
| 118 | C1 f9() { return C1(); } |
| 119 | // CHECK-DAG: @_Z2f9B6Names1v( |
| 120 | |
| 121 | inline namespace Names2 __attribute__((__abi_tag__("Tag1", "Tag2"))) { |
| 122 | class C2 {}; |
| 123 | } |
| 124 | C2 f10() { return C2(); } |
| 125 | // CHECK-DAG: @_Z3f10B4Tag1B4Tag2v( |
| 126 | |
| 127 | void __attribute__((abi_tag("A"))) f11(A) {} |
| 128 | // f11[abi:A](A[abi:A][abi:B]) |
| 129 | // CHECK-DAG: define {{.*}} @_Z3f11B1A1AB1AB1B( |
| 130 | |
| 131 | A f12(A) { return A(); } |
| 132 | // f12(A[abi:A][abi:B]) |
| 133 | // CHECK-DAG: define {{.*}} @_Z3f121AB1AB1B( |
| 134 | |
| 135 | inline void f13() { |
| 136 | struct L { |
| 137 | static E<int>* foo() { |
| 138 | static A10 a; |
| 139 | return 0; |
| 140 | } |
| 141 | }; |
| 142 | L::foo(); |
| 143 | } |
| 144 | void f13_test() { |
| 145 | f13(); |
| 146 | } |
| 147 | // f13()::L::foo[abi:C][abi:D]() |
| 148 | // CHECK-DAG: define linkonce_odr {{(dso_local )?}}%struct.E* @_ZZ3f13vEN1L3fooB1CB1DEv( |
| 149 | |
| 150 | // f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B] |
| 151 | // CHECK-DAG: @_ZZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B = |
| 152 | |
| 153 | // guard variable for f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B] |
| 154 | // CHECK-DAG: @_ZGVZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B = |
| 155 | |
| 156 | struct __attribute__((abi_tag("TAG"))) A14 { |
| 157 | A14 f14(); |
| 158 | }; |
| 159 | A14 A14::f14() { |
| 160 | return A14(); |
| 161 | } |
| 162 | // A14[abi:TAG]::f14() |
| 163 | // CHECK-DAG: define {{.+}} @_ZN3A14B3TAG3f14Ev( |
| 164 | |
| 165 | template<class T> |
| 166 | T f15() { |
| 167 | return T(); |
| 168 | } |
| 169 | void f15_test() { |
| 170 | f15<A14>(); |
| 171 | } |
| 172 | // A14[abi:TAG] f15<A14[abi:TAG]>() |
| 173 | // CHECK-DAG: define linkonce_odr {{.+}} @_Z3f15I3A14B3TAGET_v( |
| 174 | |
| 175 | template<class T> |
| 176 | A14 f16() { |
| 177 | return A14(); |
| 178 | } |
| 179 | void f16_test() { |
| 180 | f16<int>(); |
| 181 | } |
| 182 | // A14[abi:TAG] f16<int>() |
| 183 | // CHECK-DAG: define linkonce_odr {{.+}} @_Z3f16IiE3A14B3TAGv( |
| 184 | |
| 185 | template<class T> |
| 186 | struct __attribute__((abi_tag("TAG"))) A17 { |
| 187 | A17 operator+(const A17& a) { |
| 188 | return a; |
| 189 | } |
| 190 | }; |
| 191 | void f17_test() { |
| 192 | A17<int> a, b; |
| 193 | a + b; |
| 194 | } |
| 195 | // A17[abi:TAG]<int>::operator+(A17[abi:TAG]<int> const&) |
| 196 | // CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A17B3TAGIiEplERKS0_( |
| 197 | |
| 198 | struct A18 { |
| 199 | operator A() { return A(); } |
| 200 | }; |
| 201 | void f18_test() { |
| 202 | A a = A18(); |
| 203 | } |
| 204 | // A18::operator A[abi:A][abi:B]() but GCC adds the same tags twice! |
| 205 | // CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A18cv1AB1AB1BEv( |
| 206 | |
| 207 | namespace N19 { |
| 208 | class A {}; |
| 209 | class __attribute__((abi_tag("B"))) B {}; |
| 210 | class D {}; |
| 211 | class F {}; |
| 212 | |
| 213 | template<typename T, B F(T, D)> |
| 214 | class C {}; |
| 215 | |
| 216 | B foo(A, D); |
| 217 | } |
| 218 | void f19_test(N19::C<N19::A, &N19::foo>, N19::F, N19::D) { |
| 219 | } |
| 220 | // f19_test(N19::C<N19::A, &N19::foo[abi:B]>, N19::F, N19::D) |
| 221 | // CHECK-DAG: define {{(dso_local )?}}void @_Z8f19_testN3N191CINS_1AEXadL_ZNS_3fooB1BES1_NS_1DEEEEENS_1FES2_( |
| 222 | |
| 223 | namespace pr30440 { |
| 224 | |
| 225 | template<class F> void g(F); |
| 226 | template<class ...A> auto h(A ...a)->decltype (g (0, g < a > (a) ...)) { |
| 227 | } |
| 228 | // CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_( |
| 229 | |
| 230 | void pr30440_test () { |
| 231 | h(); |
| 232 | } |
| 233 | |
| 234 | } |
| 235 | |