1 // RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.20 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck %s 2 3 struct StructA {}; 4 5 template<class T> 6 auto AutoT() { return T(); } 7 8 template<class T> 9 const auto AutoConstT() { return T(); } 10 11 template<class T> 12 volatile auto AutoVolatileT() { return T(); } 13 14 template<class T> 15 const volatile auto AutoConstVolatileT() { return T(); } 16 17 // The qualifiers of the return type should always be emitted even for void types. 18 // Void types usually have their qualifers stripped in the mangled name for MSVC ABI. 19 void test_template_auto_void() { 20 AutoT<void>(); 21 // CHECK: call {{.*}} @"??$AutoT@X@@YA?A_PXZ" 22 23 AutoT<const void>(); 24 // CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ" 25 26 AutoT<volatile void>(); 27 // CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ" 28 29 AutoT<const volatile void>(); 30 // CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ" 31 32 AutoConstT<void>(); 33 // CHECK: call {{.*}} @"??$AutoConstT@X@@YA?B_PXZ" 34 35 AutoVolatileT<void>(); 36 // CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ" 37 38 AutoConstVolatileT<void>(); 39 // CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ" 40 } 41 42 void test_template_auto_int() { 43 AutoT<int>(); 44 // CHECK: call {{.*}} @"??$AutoT@H@@YA?A_PXZ" 45 46 AutoT<const int>(); 47 // CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ" 48 49 AutoT<volatile int>(); 50 // CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ" 51 52 AutoT<const volatile int>(); 53 // CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ" 54 55 AutoConstT<int>(); 56 // CHECK: call {{.*}} @"??$AutoConstT@H@@YA?B_PXZ" 57 58 AutoVolatileT<int>(); 59 // CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ" 60 61 AutoConstVolatileT<int>(); 62 // CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ" 63 } 64 65 void test_template_auto_struct() { 66 AutoT<StructA>(); 67 // CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ" 68 69 AutoT<const StructA>(); 70 // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ" 71 72 AutoConstT<StructA>(); 73 // CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ" 74 75 AutoVolatileT<StructA>(); 76 // CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ" 77 78 AutoConstVolatileT<StructA>(); 79 // CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ" 80 } 81 82 void test_template_auto_ptr() { 83 AutoT<int*>(); 84 // CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ" 85 86 AutoT<const int*>(); 87 // CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ" 88 89 AutoT<const int* const>(); 90 // CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ" 91 92 AutoConstT<int*>(); 93 // CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ" 94 95 AutoVolatileT<int*>(); 96 // CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ" 97 98 AutoConstVolatileT<int*>(); 99 // CHECK: call {{.*}} @"??$AutoConstVolatileT@PEAH@@YA?D_PXZ" 100 } 101 102 template<class T> 103 auto* PtrAutoT() { return T(); } 104 105 template<class T> 106 const auto* PtrAutoConstT() { return T(); } 107 108 template<class T> 109 volatile auto* PtrAutoVolatileT() { return T(); } 110 111 template<class T> 112 const volatile auto* PtrAutoConstVolatileT() { return T(); } 113 114 void test_template_ptr_auto() { 115 PtrAutoT<int*>(); 116 // CHECK: call {{.*}} @"??$PtrAutoT@PEAH@@YAPEA_PXZ" 117 118 PtrAutoT<const int*>(); 119 // CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ" 120 121 PtrAutoT<const int* const>(); 122 // CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ" 123 124 PtrAutoConstT<int*>(); 125 // CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ" 126 127 PtrAutoVolatileT<int*>(); 128 // CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ" 129 130 PtrAutoConstVolatileT<int*>(); 131 // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@PEAH@@YAPED_PXZ" 132 } 133 134 int func_int(); 135 const int func_constint(); 136 void func_void(); 137 int* func_intptr(); 138 139 template<class T, T v> 140 auto (*FuncPtrAutoT())() { return v; } 141 142 void test_template_func_ptr_auto() { 143 FuncPtrAutoT<int (*)(), &func_int>(); 144 // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ" 145 146 FuncPtrAutoT<const int (*)(), &func_constint>(); 147 // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ" 148 149 FuncPtrAutoT<void (*)(), &func_void>(); 150 // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ" 151 152 FuncPtrAutoT<int * (*)(), &func_intptr>(); 153 // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ" 154 } 155 156 template<class T> 157 auto& RefAutoT(T& x) { return x; } 158 159 template<class T> 160 const auto& ConstRefAutoT(T& x) { return x; } 161 162 template<class T> 163 auto&& RRefAutoT(T& x) { return static_cast<int&&>(x); } 164 165 void test_template_ref_auto() { 166 int x; 167 168 RefAutoT(x); 169 // CHECK: call {{.*}} @"??$RefAutoT@H@@YAAEA_PAEAH@Z" 170 171 ConstRefAutoT(x); 172 // CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z" 173 174 RRefAutoT(x); 175 // CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@Z" 176 } 177 178 template<class T> 179 decltype(auto) DecltypeAutoT() { return T(); } 180 181 template<class T> 182 decltype(auto) DecltypeAutoT2(T& x) { return static_cast<T&&>(x); } 183 184 void test_template_decltypeauto() { 185 DecltypeAutoT<void>(); 186 // CHECK: call {{.*}} @"??$DecltypeAutoT@X@@YA?A_TXZ" 187 188 DecltypeAutoT<const void>(); 189 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ" 190 191 DecltypeAutoT<volatile void>(); 192 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ" 193 194 DecltypeAutoT<const volatile void>(); 195 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ" 196 197 DecltypeAutoT<int>(); 198 // CHECK: call {{.*}} @"??$DecltypeAutoT@H@@YA?A_TXZ" 199 200 DecltypeAutoT<const int>(); 201 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ" 202 203 DecltypeAutoT<volatile int>(); 204 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ" 205 206 DecltypeAutoT<const volatile int>(); 207 // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ" 208 209 int x; 210 211 DecltypeAutoT2(x); 212 // CHECK: call {{.*}} @"??$DecltypeAutoT2@H@@YA?A_TAEAH@Z" 213 } 214 215 // Still want to use clang's custom mangling for lambdas to keep backwards compatibility until 216 // MSVC lambda name mangling has been deciphered. 217 void test_lambda() { 218 int i = 0; 219 220 auto lambdaIntRetAuto = []() { return 0; }; 221 lambdaIntRetAuto(); 222 // CHECK: call {{.*}} @"??R<lambda_1>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ" 223 224 auto lambdaIntRet = []() -> int { return 0; }; 225 lambdaIntRet(); 226 // CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ@QEBA@XZ" 227 228 auto lambdaGenericIntIntRetAuto = [](auto a) { return a; }; 229 lambdaGenericIntIntRetAuto(0); 230 // CHECK: call {{.*}} @"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z" 231 232 auto lambdaRetTrailingAuto = []() -> auto { return 0; }; 233 lambdaRetTrailingAuto(); 234 // CHECK: call {{.*}} @"??R<lambda_3>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ" 235 236 auto lambdaRetTrailingDecltypeAuto = []() -> decltype(auto) { return 0; }; 237 lambdaRetTrailingDecltypeAuto(); 238 // CHECK: call {{.*}} @"??R<lambda_4>@?0??test_lambda@@YAXXZ@QEBA?A?<decltype-auto>@@XZ" 239 240 auto lambdaRetTrailingRefCollapse = [](int x) -> auto&& { return x; }; 241 lambdaRetTrailingRefCollapse(i); 242 // CHECK: call {{.*}} @"??R<lambda_5>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z" 243 } 244 245 auto TestTrailingInt() -> int { 246 return 0; 247 } 248 249 auto TestTrailingConstVolatileVoid() -> const volatile void { 250 } 251 252 auto TestTrailingStructA() -> StructA { 253 return StructA{}; 254 } 255 256 void test_trailing_return() { 257 TestTrailingInt(); 258 // CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ" 259 260 TestTrailingConstVolatileVoid(); 261 // CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ" 262 263 TestTrailingStructA(); 264 // CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ" 265 } 266 267 auto TestNonTemplateAutoInt() { 268 return 0; 269 } 270 271 auto TestNonTemplateAutoVoid() { 272 return; 273 } 274 275 auto TestNonTemplateAutoStructA() { 276 return StructA{}; 277 } 278 279 const auto TestNonTemplateConstAutoInt() { 280 return 0; 281 } 282 283 const auto TestNonTemplateConstAutoVoid() { 284 return; 285 } 286 287 const auto TestNonTemplateConstAutoStructA() { 288 return StructA{}; 289 } 290 291 void test_nontemplate_auto() { 292 TestNonTemplateAutoInt(); 293 // CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA@XZ" 294 295 TestNonTemplateAutoVoid(); 296 // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ" 297 298 TestNonTemplateAutoStructA(); 299 // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ" 300 301 TestNonTemplateConstAutoInt(); 302 // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ" 303 304 TestNonTemplateConstAutoVoid(); 305 // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ" 306 307 TestNonTemplateConstAutoStructA(); 308 // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ" 309 } 310 311 decltype(auto) TestNonTemplateDecltypeAutoInt() { 312 return 0; 313 } 314 315 decltype(auto) TestNonTemplateDecltypeAutoVoid() { 316 return; 317 } 318 319 decltype(auto) TestNonTemplateDecltypeAutoStructA() { 320 return StructA{}; 321 } 322 323 void test_nontemplate_decltypeauto() { 324 TestNonTemplateDecltypeAutoInt(); 325 // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ" 326 327 TestNonTemplateDecltypeAutoVoid(); 328 // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ" 329 330 TestNonTemplateDecltypeAutoStructA(); 331 // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@XZ" 332 } 333 334 struct StructB { 335 int x; 336 }; 337 338 template<class T> 339 auto StructB::* AutoMemberDataPtrT(T x) { return x; } 340 341 template<class T> 342 const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; } 343 344 void test_template_auto_member_data_ptr() { 345 AutoMemberDataPtrT(&StructB::x); 346 // CHECK: call {{.*}} @"??$AutoMemberDataPtrT@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z" 347 348 AutoConstMemberDataPtrT(&StructB::x); 349 // CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@H@Z" 350 } 351 352 struct StructC { 353 void test() {} 354 }; 355 356 struct StructD { 357 const int test() { return 0; } 358 }; 359 360 template<class T> 361 auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; } 362 363 template<class T> 364 const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; } 365 366 void test_template_auto_member_func_ptr() { 367 AutoMemberFuncPtrT(&StructC::test); 368 // CHECK: call {{.*}} @"??$AutoMemberFuncPtrT@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z" 369 370 AutoConstMemberFuncPtrT(&StructD::test); 371 // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@Z" 372 } 373 374 template<class T> 375 auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() { 376 T * __attribute__((address_space(1))) * p = nullptr; 377 return p; 378 } 379 380 void test_template_auto_address_space_ptr() { 381 AutoPtrAddressSpaceT<int>(); 382 // CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT@H@@YA?A?<auto>@@XZ" 383 } 384 385 template<class T> 386 auto&& AutoReferenceCollapseT(T& x) { return static_cast<T&>(x); } 387 388 auto&& AutoReferenceCollapse(int& x) { return static_cast<int&>(x); } 389 390 void test2() { 391 int x = 1; 392 auto&& rref0 = AutoReferenceCollapseT(x); 393 // CHECK: call {{.*}} @"??$AutoReferenceCollapseT@H@@YA$$QEA_PAEAH@Z" 394 395 auto&& rref1 = AutoReferenceCollapse(x); 396 // CHECK: call {{.*}} @"?AutoReferenceCollapse@@YA@AEAH@Z" 397 } 398