| 1 | // RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 -std=c++98 | FileCheck %s |
| 2 | // RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s |
| 3 | // RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=aarch64-pc-win32 -std=c++98 -DARM | FileCheck -check-prefixes=X64,ARM %s |
| 4 | |
| 5 | int a; |
| 6 | // CHECK-DAG: @"?a@@3HA" |
| 7 | |
| 8 | extern "C++" { |
| 9 | static int __attribute__((used)) ignore_transparent_context; |
| 10 | // CHECK-DAG: @ignore_transparent_context |
| 11 | } |
| 12 | |
| 13 | namespace N { |
| 14 | int b; |
| 15 | // CHECK-DAG: @"?b@N@@3HA" |
| 16 | |
| 17 | namespace { |
| 18 | int anonymous; |
| 19 | // CHECK-DAG: @"?anonymous@?A0x{{[^@]*}}@N@@3HA" |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | static int c; |
| 24 | // CHECK-DAG: @c |
| 25 | |
| 26 | int _c(void) {return N::anonymous + c;} |
| 27 | // CHECK-DAG: @"?_c@@YAHXZ" |
| 28 | // X64-DAG: @"?_c@@YAHXZ" |
| 29 | |
| 30 | const int &NeedsReferenceTemporary = 2; |
| 31 | // CHECK-DAG: @"?NeedsReferenceTemporary@@3ABHB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3ABHB" |
| 32 | // X64-DAG: @"?NeedsReferenceTemporary@@3AEBHEB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3AEBHEB" |
| 33 | |
| 34 | class foo { |
| 35 | static const short d; |
| 36 | // CHECK-DAG: @"?d@foo@@0FB" |
| 37 | protected: |
| 38 | static volatile long e; |
| 39 | // CHECK-DAG: @"?e@foo@@1JC" |
| 40 | public: |
| 41 | static const volatile char f; |
| 42 | // CHECK-DAG: @"?f@foo@@2DD" |
| 43 | int operator+(int a); |
| 44 | foo(){} |
| 45 | // CHECK-DAG: @"??0foo@@QAE@XZ" |
| 46 | // X64-DAG: @"??0foo@@QEAA@XZ" |
| 47 | |
| 48 | ~foo(){} |
| 49 | // CHECK-DAG: @"??1foo@@QAE@XZ" |
| 50 | // X64-DAG: @"??1foo@@QEAA@XZ |
| 51 | |
| 52 | foo(int i){} |
| 53 | // CHECK-DAG: @"??0foo@@QAE@H@Z" |
| 54 | // X64-DAG: @"??0foo@@QEAA@H@Z" |
| 55 | |
| 56 | foo(char *q){} |
| 57 | // CHECK-DAG: @"??0foo@@QAE@PAD@Z" |
| 58 | // X64-DAG: @"??0foo@@QEAA@PEAD@Z" |
| 59 | |
| 60 | static foo* static_method() { return 0; } |
| 61 | |
| 62 | }f,s1(1),s2((char*)0); |
| 63 | |
| 64 | typedef foo (foo2); |
| 65 | |
| 66 | struct bar { |
| 67 | static int g; |
| 68 | }; |
| 69 | |
| 70 | union baz { |
| 71 | int a; |
| 72 | char b; |
| 73 | double c; |
| 74 | }; |
| 75 | |
| 76 | enum quux { |
| 77 | qone, |
| 78 | qtwo, |
| 79 | qthree |
| 80 | }; |
| 81 | |
| 82 | foo bar() { return foo(); } |
| 83 | // CHECK-DAG: @"?bar@@YA?AVfoo@@XZ" |
| 84 | // X64-DAG: @"?bar@@YA?AVfoo@@XZ" |
| 85 | |
| 86 | int foo::operator+(int a) { |
| 87 | // CHECK-DAG: @"??Hfoo@@QAEHH@Z" |
| 88 | // X64-DAG: @"??Hfoo@@QEAAHH@Z" |
| 89 | |
| 90 | foo::static_method(); |
| 91 | // CHECK-DAG: @"?static_method@foo@@SAPAV1@XZ" |
| 92 | // X64-DAG: @"?static_method@foo@@SAPEAV1@XZ" |
| 93 | bar(); |
| 94 | return a; |
| 95 | } |
| 96 | |
| 97 | const short foo::d = 0; |
| 98 | volatile long foo::e; |
| 99 | const volatile char foo::f = 'C'; |
| 100 | |
| 101 | int bar::g; |
| 102 | // CHECK-DAG: @"?g@bar@@2HA" |
| 103 | |
| 104 | extern int * const h1 = &a; |
| 105 | // CHECK-DAG: @"?h1@@3QAHA" |
| 106 | extern const int * const h2 = &a; |
| 107 | // CHECK-DAG: @"?h2@@3QBHB" |
| 108 | extern int * const __restrict h3 = &a; |
| 109 | // CHECK-DAG: @"?h3@@3QIAHIA" |
| 110 | // X64-DAG: @"?h3@@3QEIAHEIA" |
| 111 | |
| 112 | int i[10][20]; |
| 113 | // CHECK-DAG: @"?i@@3PAY0BE@HA" |
| 114 | |
| 115 | typedef int (*FunT)(int, int); |
| 116 | FunT FunArr[10][20]; |
| 117 | // CHECK-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA" |
| 118 | // X64-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA" |
| 119 | |
| 120 | int (__stdcall *j)(signed char, unsigned char); |
| 121 | // CHECK-DAG: @"?j@@3P6GHCE@ZA" |
| 122 | |
| 123 | const volatile char foo2::*k; |
| 124 | // CHECK-DAG: @"?k@@3PTfoo@@DT1@" |
| 125 | // X64-DAG: @"?k@@3PETfoo@@DET1@" |
| 126 | |
| 127 | int (foo2::*l)(int); |
| 128 | // CHECK-DAG: @"?l@@3P8foo@@AEHH@ZQ1@" |
| 129 | |
| 130 | // Ensure typedef CV qualifiers are mangled correctly |
| 131 | typedef const int cInt; |
| 132 | typedef volatile int vInt; |
| 133 | typedef const volatile int cvInt; |
| 134 | |
| 135 | extern cInt g_cInt = 1; |
| 136 | vInt g_vInt = 2; |
| 137 | cvInt g_cvInt = 3; |
| 138 | |
| 139 | // CHECK-DAG: @"?g_cInt@@3HB" |
| 140 | // CHECK-DAG: @"?g_vInt@@3HC" |
| 141 | // CHECK-DAG: @"?g_cvInt@@3HD" |
| 142 | |
| 143 | // Static functions are mangled, too. |
| 144 | // Also make sure calling conventions, arglists, and throw specs work. |
| 145 | static void __stdcall alpha(float a, double b) throw() {} |
| 146 | bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) { |
| 147 | // CHECK-DAG: @"?beta@@YI_N_J_W@Z" |
| 148 | // X64-DAG: @"?beta@@YA_N_J_W@Z" |
| 149 | alpha(0.f, 0.0); |
| 150 | return false; |
| 151 | } |
| 152 | |
| 153 | // CHECK-DAG: @"?alpha@@YGXMN@Z" |
| 154 | // X64-DAG: @"?alpha@@YAXMN@Z" |
| 155 | |
| 156 | // Make sure tag-type mangling works. |
| 157 | void gamma(class foo, struct bar, union baz, enum quux) {} |
| 158 | // CHECK-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z" |
| 159 | // X64-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z" |
| 160 | |
| 161 | // Make sure pointer/reference-type mangling works. |
| 162 | void delta(int * const a, const long &) {} |
| 163 | // CHECK-DAG: @"?delta@@YAXQAHABJ@Z" |
| 164 | // X64-DAG: @"?delta@@YAXQEAHAEBJ@Z" |
| 165 | |
| 166 | // Array mangling. |
| 167 | void epsilon(int a[][10][20]) {} |
| 168 | // CHECK-DAG: @"?epsilon@@YAXQAY19BE@H@Z" |
| 169 | // X64-DAG: @"?epsilon@@YAXQEAY19BE@H@Z" |
| 170 | |
| 171 | void zeta(int (*)(int, int)) {} |
| 172 | // CHECK-DAG: @"?zeta@@YAXP6AHHH@Z@Z" |
| 173 | // X64-DAG: @"?zeta@@YAXP6AHHH@Z@Z" |
| 174 | |
| 175 | // Blocks mangling (Clang extension). A block should be mangled slightly |
| 176 | // differently from a similar function pointer. |
| 177 | void eta(int (^)(int, int)) {} |
| 178 | // CHECK-DAG: @"?eta@@YAXP_EAHHH@Z@Z" |
| 179 | |
| 180 | typedef int theta_arg(int,int); |
| 181 | void theta(theta_arg^ block) {} |
| 182 | // CHECK-DAG: @"?theta@@YAXP_EAHHH@Z@Z" |
| 183 | |
| 184 | void operator_new_delete() { |
| 185 | char *ptr = new char; |
| 186 | // CHECK-DAG: @"??2@YAPAXI@Z" |
| 187 | |
| 188 | delete ptr; |
| 189 | // CHECK-DAG: @"??3@YAXPAX@Z" |
| 190 | |
| 191 | char *array = new char[42]; |
| 192 | // CHECK-DAG: @"??_U@YAPAXI@Z" |
| 193 | |
| 194 | delete [] array; |
| 195 | // CHECK-DAG: @"??_V@YAXPAX@Z" |
| 196 | } |
| 197 | |
| 198 | // PR13022 |
| 199 | void (redundant_parens)(); |
| 200 | void redundant_parens_use() { redundant_parens(); } |
| 201 | // CHECK-DAG: @"?redundant_parens@@YAXXZ" |
| 202 | // X64-DAG: @"?redundant_parens@@YAXXZ" |
| 203 | |
| 204 | // PR13047 |
| 205 | typedef double RGB[3]; |
| 206 | RGB color1; |
| 207 | // CHECK-DAG: @"?color1@@3PANA" |
| 208 | extern const RGB color2 = {}; |
| 209 | // CHECK-DAG: @"?color2@@3QBNB" |
| 210 | extern RGB const color3[5] = {}; |
| 211 | // CHECK-DAG: @"?color3@@3QAY02$$CBNA" |
| 212 | extern RGB const ((color4)[5]) = {}; |
| 213 | // CHECK-DAG: @"?color4@@3QAY02$$CBNA" |
| 214 | |
| 215 | struct B; |
| 216 | volatile int B::* volatile memptr1; |
| 217 | // X64-DAG: @"?memptr1@@3RESB@@HES1@" |
| 218 | volatile int B::* memptr2; |
| 219 | // X64-DAG: @"?memptr2@@3PESB@@HES1@" |
| 220 | int B::* volatile memptr3; |
| 221 | // X64-DAG: @"?memptr3@@3REQB@@HEQ1@" |
| 222 | typedef int (*fun)(); |
| 223 | volatile fun B::* volatile funmemptr1; |
| 224 | // X64-DAG: @"?funmemptr1@@3RESB@@R6AHXZES1@" |
| 225 | volatile fun B::* funmemptr2; |
| 226 | // X64-DAG: @"?funmemptr2@@3PESB@@R6AHXZES1@" |
| 227 | fun B::* volatile funmemptr3; |
| 228 | // X64-DAG: @"?funmemptr3@@3REQB@@P6AHXZEQ1@" |
| 229 | void (B::* volatile memptrtofun1)(); |
| 230 | // X64-DAG: @"?memptrtofun1@@3R8B@@EAAXXZEQ1@" |
| 231 | const void (B::* memptrtofun2)(); |
| 232 | // X64-DAG: @"?memptrtofun2@@3P8B@@EAAXXZEQ1@" |
| 233 | volatile void (B::* memptrtofun3)(); |
| 234 | // X64-DAG: @"?memptrtofun3@@3P8B@@EAAXXZEQ1@" |
| 235 | int (B::* volatile memptrtofun4)(); |
| 236 | // X64-DAG: @"?memptrtofun4@@3R8B@@EAAHXZEQ1@" |
| 237 | volatile int (B::* memptrtofun5)(); |
| 238 | // X64-DAG: @"?memptrtofun5@@3P8B@@EAA?CHXZEQ1@" |
| 239 | const int (B::* memptrtofun6)(); |
| 240 | // X64-DAG: @"?memptrtofun6@@3P8B@@EAA?BHXZEQ1@" |
| 241 | fun (B::* volatile memptrtofun7)(); |
| 242 | // X64-DAG: @"?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@" |
| 243 | volatile fun (B::* memptrtofun8)(); |
| 244 | // X64-DAG: @"?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@" |
| 245 | const fun (B::* memptrtofun9)(); |
| 246 | // X64-DAG: @"?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@" |
| 247 | |
| 248 | // PR12603 |
| 249 | enum E {}; |
| 250 | // CHECK-DAG: "?fooE@@YA?AW4E@@XZ" |
| 251 | // X64-DAG: "?fooE@@YA?AW4E@@XZ" |
| 252 | E fooE() { return E(); } |
| 253 | |
| 254 | class X {}; |
| 255 | // CHECK-DAG: "?fooX@@YA?AVX@@XZ" |
| 256 | // X64-DAG: "?fooX@@YA?AVX@@XZ" |
| 257 | X fooX() { return X(); } |
| 258 | |
| 259 | namespace PR13182 { |
| 260 | extern char s0[]; |
| 261 | // CHECK-DAG: @"?s0@PR13182@@3PADA" |
| 262 | extern char s1[42]; |
| 263 | // CHECK-DAG: @"?s1@PR13182@@3PADA" |
| 264 | extern const char s2[]; |
| 265 | // CHECK-DAG: @"?s2@PR13182@@3QBDB" |
| 266 | extern const char s3[42]; |
| 267 | // CHECK-DAG: @"?s3@PR13182@@3QBDB" |
| 268 | extern volatile char s4[]; |
| 269 | // CHECK-DAG: @"?s4@PR13182@@3RCDC" |
| 270 | extern const volatile char s5[]; |
| 271 | // CHECK-DAG: @"?s5@PR13182@@3SDDD" |
| 272 | extern const char* const* s6; |
| 273 | // CHECK-DAG: @"?s6@PR13182@@3PBQBDB" |
| 274 | |
| 275 | char foo() { |
| 276 | return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0]; |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | extern "C" inline void extern_c_func() { |
| 281 | static int local; |
| 282 | // CHECK-DAG: @"?local@?1??extern_c_func@@9@4HA" |
| 283 | // X64-DAG: @"?local@?1??extern_c_func@@9@4HA" |
| 284 | } |
| 285 | |
| 286 | void call_extern_c_func() { |
| 287 | extern_c_func(); |
| 288 | } |
| 289 | |
| 290 | int main() { return 0; } |
| 291 | // CHECK-DAG: @main |
| 292 | // X64-DAG: @main |
| 293 | |
| 294 | int wmain() { return 0; } |
| 295 | // CHECK-DAG: @wmain |
| 296 | // X64-DAG: @wmain |
| 297 | |
| 298 | int WinMain() { return 0; } |
| 299 | // CHECK-DAG: @WinMain |
| 300 | // X64-DAG: @WinMain |
| 301 | |
| 302 | int wWinMain() { return 0; } |
| 303 | // CHECK-DAG: @wWinMain |
| 304 | // X64-DAG: @wWinMain |
| 305 | |
| 306 | int DllMain() { return 0; } |
| 307 | // CHECK-DAG: @DllMain |
| 308 | // X64-DAG: @DllMain |
| 309 | |
| 310 | inline int inline_function_with_local_type() { |
| 311 | static struct { |
| 312 | int a_field; |
| 313 | } static_variable_in_inline_function = { 20 }, second_static = { 40 }; |
| 314 | // CHECK: @"?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A" |
| 315 | |
| 316 | return static_variable_in_inline_function.a_field + second_static.a_field; |
| 317 | } |
| 318 | |
| 319 | int call_inline_function_with_local_type() { |
| 320 | return inline_function_with_local_type(); |
| 321 | } |
| 322 | |
| 323 | template <typename T> |
| 324 | inline int templated_inline_function_with_local_type() { |
| 325 | static struct { |
| 326 | int a_field; |
| 327 | } static_variable_in_templated_inline_function = { 20 }, |
| 328 | second_static = { 40 }; |
| 329 | // CHECK: @"?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A" |
| 330 | |
| 331 | return static_variable_in_templated_inline_function.a_field + |
| 332 | second_static.a_field; |
| 333 | } |
| 334 | |
| 335 | int call_templated_inline_function_with_local_type() { |
| 336 | return templated_inline_function_with_local_type<int>(); |
| 337 | } |
| 338 | |
| 339 | // PR17371 |
| 340 | struct OverloadedNewDelete { |
| 341 | // __cdecl |
| 342 | void *operator new(__SIZE_TYPE__); |
| 343 | void *operator new[](__SIZE_TYPE__); |
| 344 | void operator delete(void *); |
| 345 | void operator delete[](void *); |
| 346 | // __thiscall |
| 347 | int operator+(int); |
| 348 | }; |
| 349 | |
| 350 | void *OverloadedNewDelete::operator new(__SIZE_TYPE__ s) { return 0; } |
| 351 | void *OverloadedNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; } |
| 352 | void OverloadedNewDelete::operator delete(void *) { } |
| 353 | void OverloadedNewDelete::operator delete[](void *) { } |
| 354 | int OverloadedNewDelete::operator+(int x) { return x; }; |
| 355 | |
| 356 | // CHECK-DAG: ??2OverloadedNewDelete@@SAPAXI@Z |
| 357 | // CHECK-DAG: ??_UOverloadedNewDelete@@SAPAXI@Z |
| 358 | // CHECK-DAG: ??3OverloadedNewDelete@@SAXPAX@Z |
| 359 | // CHECK-DAG: ??_VOverloadedNewDelete@@SAXPAX@Z |
| 360 | // CHECK-DAG: ??HOverloadedNewDelete@@QAEHH@Z |
| 361 | |
| 362 | // X64-DAG: ??2OverloadedNewDelete@@SAPEAX_K@Z |
| 363 | // X64-DAG: ??_UOverloadedNewDelete@@SAPEAX_K@Z |
| 364 | // X64-DAG: ??3OverloadedNewDelete@@SAXPEAX@Z |
| 365 | // X64-DAG: ??_VOverloadedNewDelete@@SAXPEAX@Z |
| 366 | // X64-DAG: ??HOverloadedNewDelete@@QEAAHH@Z |
| 367 | |
| 368 | // Indirecting the function type through a typedef will require a calling |
| 369 | // convention adjustment before building the method decl. |
| 370 | |
| 371 | typedef void *__thiscall OperatorNewType(__SIZE_TYPE__); |
| 372 | typedef void __thiscall OperatorDeleteType(void *); |
| 373 | |
| 374 | struct TypedefNewDelete { |
| 375 | OperatorNewType operator new; |
| 376 | OperatorNewType operator new[]; |
| 377 | OperatorDeleteType operator delete; |
| 378 | OperatorDeleteType operator delete[]; |
| 379 | }; |
| 380 | |
| 381 | void *TypedefNewDelete::operator new(__SIZE_TYPE__ s) { return 0; } |
| 382 | void *TypedefNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; } |
| 383 | void TypedefNewDelete::operator delete(void *) { } |
| 384 | void TypedefNewDelete::operator delete[](void *) { } |
| 385 | |
| 386 | // CHECK-DAG: ??2TypedefNewDelete@@SAPAXI@Z |
| 387 | // CHECK-DAG: ??_UTypedefNewDelete@@SAPAXI@Z |
| 388 | // CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z |
| 389 | // CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z |
| 390 | |
| 391 | void __vectorcall vector_func() { } |
| 392 | // CHECK-DAG: @"?vector_func@@YQXXZ" |
| 393 | |
| 394 | template <void (*)(void)> |
| 395 | void fn_tmpl() {} |
| 396 | |
| 397 | template void fn_tmpl<extern_c_func>(); |
| 398 | // CHECK-DAG: @"??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ" |
| 399 | |
| 400 | extern "C" void __attribute__((overloadable)) overloaded_fn() {} |
| 401 | // CHECK-DAG: @"?overloaded_fn@@$$J0YAXXZ" |
| 402 | |
| 403 | extern "C" void overloaded_fn2() {} |
| 404 | // CHECK-DAG: @overloaded_fn2 |
| 405 | // |
| 406 | extern "C" void __attribute__((overloadable)) overloaded_fn3(); |
| 407 | extern "C" void overloaded_fn3() {} |
| 408 | // CHECK-DAG: @overloaded_fn3 |
| 409 | |
| 410 | namespace UnnamedType { |
| 411 | struct S { |
| 412 | typedef struct {} *T1[1]; |
| 413 | typedef struct {} T2; |
| 414 | typedef struct {} *T3, T4; |
| 415 | using T5 = struct {}; |
| 416 | using T6 = struct {} *; |
| 417 | }; |
| 418 | void f(S::T1) {} |
| 419 | void f(S::T2) {} |
| 420 | void f(S::T3) {} |
| 421 | void f(S::T4) {} |
| 422 | void f(S::T5) {} |
| 423 | void f(S::T6) {} |
| 424 | // CHECK-DAG: @"?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z" |
| 425 | // CHECK-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z" |
| 426 | // CHECK-DAG: @"?f@UnnamedType@@YAXPAUT4@S@1@@Z" |
| 427 | // CHECK-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z" |
| 428 | // CHECK-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z" |
| 429 | // CHECK-DAG: @"?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z" |
| 430 | |
| 431 | // X64-DAG: @"?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z" |
| 432 | // X64-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z" |
| 433 | // X64-DAG: @"?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4" |
| 434 | // X64-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z" |
| 435 | // X64-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z" |
| 436 | // X64-DAG: @"?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z" |
| 437 | } |
| 438 | |
| 439 | namespace PassObjectSize { |
| 440 | // NOTE: This mangling is subject to change. |
| 441 | // Reiterating from the comment in MicrosoftMangle, the scheme is pretend a |
| 442 | // parameter of type __clang::__pass_object_sizeN exists after each pass object |
| 443 | // size param P, where N is the Type of the pass_object_size attribute on P. |
| 444 | // |
| 445 | // e.g. we want to mangle: |
| 446 | // void foo(void *const __attribute__((pass_object_size(0)))); |
| 447 | // as if it were |
| 448 | // namespace __clang { enum __pass_object_size0 : size_t {}; } |
| 449 | // void foo(void *const, __clang::__pass_object_size0); |
| 450 | // where __clang is a top-level namespace. |
| 451 | |
| 452 | // CHECK-DAG: define dso_local i32 @"?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z" |
| 453 | int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; } |
| 454 | // CHECK-DAG: define dso_local i32 @"?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z" |
| 455 | int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; } |
| 456 | // CHECK-DAG: define dso_local i32 @"?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z" |
| 457 | int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; } |
| 458 | // CHECK-DAG: define dso_local i32 @"?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z" |
| 459 | int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; } |
| 460 | // CHECK-DAG: define dso_local i32 @"?silly_word@PassObjectSize@@YAHQAHW4__pass_dynamic_object_size1@__clang@@@Z" |
| 461 | int silly_word(int *const i __attribute__((pass_dynamic_object_size(1)))) { return 0; } |
| 462 | } |
| 463 | |
| 464 | namespace Atomic { |
| 465 | // CHECK-DAG: define dso_local void @"?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"( |
| 466 | void f(_Atomic(int)) {} |
| 467 | } |
| 468 | namespace Complex { |
| 469 | // CHECK-DAG: define dso_local void @"?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"( |
| 470 | void f(_Complex int) {} |
| 471 | } |
| 472 | #ifdef ARM |
| 473 | namespace Float16 { |
| 474 | // ARM-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"( |
| 475 | void f(_Float16) {} |
| 476 | } |
| 477 | #endif // ARM |
| 478 | |
| 479 | namespace PR26029 { |
| 480 | template <class> |
| 481 | struct L { |
| 482 | L() {} |
| 483 | }; |
| 484 | template <class> |
| 485 | class H; |
| 486 | struct M : L<H<int *> > {}; |
| 487 | |
| 488 | template <class> |
| 489 | struct H {}; |
| 490 | |
| 491 | template <class GT> |
| 492 | void m_fn3() { |
| 493 | (H<GT *>()); |
| 494 | M(); |
| 495 | } |
| 496 | |
| 497 | void runOnFunction() { |
| 498 | L<H<int *> > b; |
| 499 | m_fn3<int>(); |
| 500 | } |
| 501 | // CHECK-DAG: call {{.*}} @"??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ" |
| 502 | } |
| 503 | |