372 lines · cpp
1// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI2// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI3// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI4// RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI5// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-186// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-197 8namespace trivial {9// Trivial structs should be passed directly.10struct A {11 void *p;12};13void foo(A);14void bar() {15 foo({});16}17// CHECK-LABEL: define{{.*}} void @_ZN7trivial3barEv()18// CHECK: alloca %"struct.trivial::A"19// CHECK: load ptr, ptr20// CHECK: call void @_ZN7trivial3fooENS_1AE(ptr %{{.*}})21// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(ptr)22 23// WIN64-LABEL: declare dso_local void @"?foo@trivial@@YAXUA@1@@Z"(i64)24}25 26namespace default_ctor {27struct A {28 A();29 void *p;30};31void foo(A);32void bar() {33 // Core issue 1590. We can pass this type in registers, even though C++34 // normally doesn't permit copies when using braced initialization.35 foo({});36}37// CHECK-LABEL: define{{.*}} void @_ZN12default_ctor3barEv()38// CHECK: alloca %"struct.default_ctor::A"39// CHECK: call void @_Z{{.*}}C1Ev(40// CHECK: load ptr, ptr41// CHECK: call void @_ZN12default_ctor3fooENS_1AE(ptr %{{.*}})42// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(ptr)43 44// WIN64-LABEL: declare dso_local void @"?foo@default_ctor@@YAXUA@1@@Z"(i64)45}46 47namespace move_ctor {48// The presence of a move constructor implicitly deletes the trivial copy ctor49// and means that we have to pass this struct by address.50struct A {51 A();52 A(A &&o);53 void *p;54};55void foo(A);56void bar() {57 foo({});58}59// CHECK-LABEL: define{{.*}} void @_ZN9move_ctor3barEv()60// CHECK: call void @_Z{{.*}}C1Ev(61// CHECK-NOT: call62// NEWABI: call void @_ZN9move_ctor3fooENS_1AE(ptr dead_on_return noundef %{{.*}})63// OLDABI: call void @_ZN9move_ctor3fooENS_1AE(ptr %{{.*}})64// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr dead_on_return noundef)65// OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr)66 67// WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(ptr dead_on_return noundef)68}69 70namespace all_deleted {71struct A {72 A();73 A(const A &o) = delete;74 A(A &&o) = delete;75 void *p;76};77void foo(A);78void bar() {79 foo({});80}81// CHECK-LABEL: define{{.*}} void @_ZN11all_deleted3barEv()82// CHECK: call void @_Z{{.*}}C1Ev(83// CHECK-NOT: call84// NEWABI: call void @_ZN11all_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}})85// OLDABI: call void @_ZN11all_deleted3fooENS_1AE(ptr %{{.*}})86// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr dead_on_return noundef)87// OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr)88 89// WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef)90}91 92namespace implicitly_deleted {93struct A {94 A();95 A &operator=(A &&o);96 void *p;97};98void foo(A);99void bar() {100 foo({});101}102// CHECK-LABEL: define{{.*}} void @_ZN18implicitly_deleted3barEv()103// CHECK: call void @_Z{{.*}}C1Ev(104// CHECK-NOT: call105// NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}})106// OLDABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr %{{.*}})107// NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr dead_on_return noundef)108// OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr)109 110// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.111// WIN64-18-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(i64112// WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef)113}114 115namespace one_deleted {116struct A {117 A();118 A(A &&o) = delete;119 void *p;120};121void foo(A);122void bar() {123 foo({});124}125// CHECK-LABEL: define{{.*}} void @_ZN11one_deleted3barEv()126// CHECK: call void @_Z{{.*}}C1Ev(127// CHECK-NOT: call128// NEWABI: call void @_ZN11one_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}})129// OLDABI: call void @_ZN11one_deleted3fooENS_1AE(ptr %{{.*}})130// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr dead_on_return noundef)131// OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr)132 133// WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef)134}135 136namespace copy_defaulted {137struct A {138 A();139 A(const A &o) = default;140 A(A &&o) = delete;141 void *p;142};143void foo(A);144void bar() {145 foo({});146}147// CHECK-LABEL: define{{.*}} void @_ZN14copy_defaulted3barEv()148// CHECK: call void @_Z{{.*}}C1Ev(149// CHECK: load ptr, ptr150// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(ptr %{{.*}})151// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(ptr)152 153// WIN64-LABEL: declare dso_local void @"?foo@copy_defaulted@@YAXUA@1@@Z"(i64)154}155 156namespace move_defaulted {157struct A {158 A();159 A(const A &o) = delete;160 A(A &&o) = default;161 void *p;162};163void foo(A);164void bar() {165 foo({});166}167// CHECK-LABEL: define{{.*}} void @_ZN14move_defaulted3barEv()168// CHECK: call void @_Z{{.*}}C1Ev(169// CHECK: load ptr, ptr170// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(ptr %{{.*}})171// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(ptr)172 173// WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(ptr dead_on_return noundef)174}175 176namespace trivial_defaulted {177struct A {178 A();179 A(const A &o) = default;180 void *p;181};182void foo(A);183void bar() {184 foo({});185}186// CHECK-LABEL: define{{.*}} void @_ZN17trivial_defaulted3barEv()187// CHECK: call void @_Z{{.*}}C1Ev(188// CHECK: load ptr, ptr189// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(ptr %{{.*}})190// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(ptr)191 192// WIN64-LABEL: declare dso_local void @"?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)193}194 195namespace two_copy_ctors {196struct A {197 A();198 A(const A &) = default;199 A(const A &, int = 0);200 void *p;201};202struct B : A {};203 204void foo(B);205void bar() {206 foo({});207}208// CHECK-LABEL: define{{.*}} void @_ZN14two_copy_ctors3barEv()209// CHECK: call void @_Z{{.*}}C1Ev(210// NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr dead_on_return noundef %{{.*}})211// OLDABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval212// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr dead_on_return noundef)213// OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval214 215// WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(ptr dead_on_return noundef)216}217 218namespace definition_only {219struct A {220 A();221 A(A &&o);222 void *p;223};224void *foo(A a) { return a.p; }225// NEWABI-LABEL: define{{.*}} ptr @_ZN15definition_only3fooENS_1AE(ptr226// OLDABI-LABEL: define{{.*}} ptr @_ZN15definition_only3fooENS_1AE(ptr227// WIN64-LABEL: define dso_local noundef ptr @"?foo@definition_only@@YAPEAXUA@1@@Z"(ptr228}229 230namespace deleted_by_member {231struct B {232 B();233 B(B &&o);234 void *p;235};236struct A {237 A();238 B b;239};240void *foo(A a) { return a.b.p; }241// NEWABI-LABEL: define{{.*}} ptr @_ZN17deleted_by_member3fooENS_1AE(ptr242// OLDABI-LABEL: define{{.*}} ptr @_ZN17deleted_by_member3fooENS_1AE(ptr243// WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_member@@YAPEAXUA@1@@Z"(ptr244}245 246namespace deleted_by_base {247struct B {248 B();249 B(B &&o);250 void *p;251};252struct A : B {253 A();254};255void *foo(A a) { return a.p; }256// NEWABI-LABEL: define{{.*}} ptr @_ZN15deleted_by_base3fooENS_1AE(ptr257// OLDABI-LABEL: define{{.*}} ptr @_ZN15deleted_by_base3fooENS_1AE(ptr258// WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_base@@YAPEAXUA@1@@Z"(ptr259}260 261namespace deleted_by_member_copy {262struct B {263 B();264 B(const B &o) = delete;265 void *p;266};267struct A {268 A();269 B b;270};271void *foo(A a) { return a.b.p; }272// NEWABI-LABEL: define{{.*}} ptr @_ZN22deleted_by_member_copy3fooENS_1AE(ptr273// OLDABI-LABEL: define{{.*}} ptr @_ZN22deleted_by_member_copy3fooENS_1AE(ptr274// WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(ptr275}276 277namespace deleted_by_base_copy {278struct B {279 B();280 B(const B &o) = delete;281 void *p;282};283struct A : B {284 A();285};286void *foo(A a) { return a.p; }287// NEWABI-LABEL: define{{.*}} ptr @_ZN20deleted_by_base_copy3fooENS_1AE(ptr288// OLDABI-LABEL: define{{.*}} ptr @_ZN20deleted_by_base_copy3fooENS_1AE(ptr289// WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(ptr290}291 292namespace explicit_delete {293struct A {294 A();295 A(const A &o) = delete;296 void *p;297};298// NEWABI-LABEL: define{{.*}} ptr @_ZN15explicit_delete3fooENS_1AE(ptr299// OLDABI-LABEL: define{{.*}} ptr @_ZN15explicit_delete3fooENS_1AE(ptr300// WIN64-LABEL: define dso_local noundef ptr @"?foo@explicit_delete@@YAPEAXUA@1@@Z"(ptr301void *foo(A a) { return a.p; }302}303 304namespace implicitly_deleted_copy_ctor {305struct A {306 // No move ctor due to copy assignment.307 A &operator=(const A&);308 // Deleted copy ctor due to rvalue ref member.309 int &&ref;310};311// NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(ptr312// OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(ptr313// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(ptr314int &foo(A a) { return a.ref; }315 316struct B {317 // Passed direct: has non-deleted trivial copy ctor.318 B &operator=(const B&);319 int &ref;320};321int &foo(B b) { return b.ref; }322// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(ptr323// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64324 325struct X { X(const X&); };326struct Y { Y(const Y&) = default; };327 328union C {329 C &operator=(const C&);330 // Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.331 X x;332 int n;333};334int foo(C c) { return c.n; }335// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(ptr336// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(ptr337 338struct D {339 D &operator=(const D&);340 // Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.341 union {342 X x;343 int n;344 };345};346int foo(D d) { return d.n; }347// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(ptr348// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(ptr349 350union E {351 // Passed direct: has non-deleted trivial copy ctor.352 E &operator=(const E&);353 Y y;354 int n;355};356int foo(E e) { return e.n; }357// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32358// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32359 360struct F {361 // Passed direct: has non-deleted trivial copy ctor.362 F &operator=(const F&);363 union {364 Y y;365 int n;366 };367};368int foo(F f) { return f.n; }369// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32370// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32371}372