319 lines · cpp
1// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-linux -o - | FileCheck %s2 3struct TrivialStruct {4 void explicit_object_function(this TrivialStruct) {}5};6void test() {7 TrivialStruct s;8 s.explicit_object_function();9}10// CHECK: define {{.*}}test{{.*}}11// CHECK-NEXT: entry:12// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 113// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 114// CHECK: call void {{.*}}explicit_object_function{{.*}}15// CHECK-NEXT: ret void16// CHECK-NEXT: }17 18// CHECK: define {{.*}}explicit_object_function{{.*}}19// CHECK-NEXT: entry:20// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 121// CHECK: ret void22// CHECK-NEXT: }23 24 25void test_lambda() {26 [](this auto This) -> int {27 return This();28 }();29}30 31//CHECK: define dso_local void @{{.*}}test_lambda{{.*}}() #0 {32//CHECK: entry:33//CHECK: %agg.tmp = alloca %class.anon, align 134//CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"()35//CHECK: ret void36//CHECK: }37 38//CHECK: define internal noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() #0 align 2 {39//CHECK: entry:40//CHECK: %This = alloca %class.anon, align 141//CHECK: %agg.tmp = alloca %class.anon, align 142//CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"()43//CHECK: ret i32 %call44//CHECK: }45 46void test_lambda_ref() {47 auto l = [i = 42](this auto & This, int j) -> int {48 return This(j);49 };50 l(0);51}52 53// CHECK: define dso_local void @_Z15test_lambda_refv() #0 {54// CHECK: entry:55// CHECK: %[[This_address:.]] = alloca %class.anon{{.*}}, align 456// CHECK: %[[i_addr:.*]] = getelementptr inbounds nuw %class.anon{{.*}}, ptr %[[This_address]], i32 0, i32 057// CHECK: store i32 42, ptr %[[i_addr]], align 458// CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}}59// CHECK: ret void60// CHECK: }61 62// CHECK: define internal noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}}63// CHECK: entry:64// CHECK: %This.addr = alloca ptr, align 865// CHECK: %j.addr = alloca i32, align 466// CHECK: store ptr %This, ptr %This.addr, align 867// CHECK: store i32 %j, ptr %j.addr, align 468// CHECK: %[[this_addr:.*]] = load ptr, ptr %This.addr, align 869// CHECK: %[[j_addr:.*]] = load i32, ptr %j.addr, align 470// CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"(ptr noundef nonnull align 4 dereferenceable(4) %[[this_addr]], i32 noundef %[[j_addr]])71// CHECK: ret i32 %call72// CHECK: }73 74 75struct TestPointer {76 void f(this TestPointer &);77};78 79void test_pointer() {80 TestPointer t;81 using Fn = void(TestPointer&);82 Fn* fn = &TestPointer::f;83 fn(t);84}85//CHECK: define dso_local void @_Z12test_pointerv() #0 {86//CHECK-NEXT: entry:87//CHECK-NEXT: %t = alloca %struct.TestPointer, align 188//CHECK-NEXT: %fn = alloca ptr, align 889//CHECK-NEXT: store ptr @_ZNH11TestPointer1fERS_, ptr %fn, align 890//CHECK: %[[fn_ptr:.*]] = load ptr, ptr %fn, align 891//CHECK-NEXT: call void %[[fn_ptr]](ptr noundef nonnull align 1 dereferenceable(1) %t)92//CHECK-NEXT: ret void93//CHECK-NEXT: }94 95 96struct MaterializedTemporary {97 void foo(this MaterializedTemporary&&);98 MaterializedTemporary();99 ~MaterializedTemporary();100};101 102void test_temporary() {103 MaterializedTemporary{}.foo();104}105 106//CHECK: define dso_local void @_Z14test_temporaryv(){{.*}}107//CHECK-NEXT: entry:108//CHECK: %ref.tmp = alloca %struct.MaterializedTemporary, align 1109//CHECK: call void @_ZN21MaterializedTemporaryC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}}110//CHECK invoke void @_ZNH21MaterializedTemporary3fooEOS_(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}}111 112namespace GH86399 {113volatile int a = 0;114struct function {115 function& operator=(function const&) {116 a = 1;117 return *this;118 }119};120 121void f() {122 function list;123 124 //CHECK-LABEL: define internal void @"_ZZN7GH863991f{{.*}}"(ptr %{{.*}})125 //CHECK: call {{.*}} @_ZN7GH863998functionaSERKS0_126 //CHECK-NEXT: ret void127 [&list](this auto self) {128 list = function{};129 }();130}131}132 133namespace GH84163 {134// Just check that this doesn't crash (we were previously not instantiating135// everything that needs instantiating in here).136template <typename> struct S {};137 138void a() {139 int x;140 const auto l = [&x](this auto&) { S<decltype(x)> q; };141 l();142}143}144 145namespace GH84425 {146// As above.147void do_thing(int x) {148 auto second = [&](this auto const& self, int b) -> int {149 if (x) return x;150 else return self(x);151 };152 153 second(1);154}155 156void do_thing2(int x) {157 auto second = [&](this auto const& self) {158 if (true) return x;159 else return x;160 };161 162 second();163}164}165 166namespace GH79754 {167// As above.168void f() {169 int x;170 [&x](this auto&&) {return x;}();171}172}173 174namespace GH70604 {175auto dothing(int num)176{177 auto fun = [&num](this auto&& self) -> void {178 auto copy = num;179 };180 181 fun();182}183}184 185namespace GH87210 {186template <typename... Ts>187struct Overloaded : Ts... {188 using Ts::operator()...;189};190 191template <typename... Ts>192Overloaded(Ts...) -> Overloaded<Ts...>;193 194// CHECK-LABEL: define dso_local void @_ZN7GH872101fEv()195// CHECK-NEXT: entry:196// CHECK-NEXT: [[X:%.*]] = alloca i32197// CHECK-NEXT: [[Over:%.*]] = alloca %"{{.*}}Overloaded"198// CHECK: call noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Over]])199void f() {200 int x;201 Overloaded o {202 // CHECK: define internal noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Self:%.*]])203 // CHECK-NEXT: entry:204 // CHECK-NEXT: [[SelfAddr:%.*]] = alloca ptr205 // CHECK-NEXT: store ptr [[Self]], ptr [[SelfAddr]]206 // CHECK-NEXT: [[SelfPtr:%.*]] = load ptr, ptr [[SelfAddr]]207 // CHECK-NEXT: [[XRef:%.*]] = getelementptr inbounds nuw %{{.*}}, ptr [[SelfPtr]], i32 0, i32 0208 // CHECK-NEXT: [[X:%.*]] = load ptr, ptr [[XRef]]209 // CHECK-NEXT: ret ptr [[X]]210 [&](this auto& self) {211 return &x;212 }213 };214 o();215}216 217void g() {218 int x;219 Overloaded o {220 [=](this auto& self) {221 return x;222 }223 };224 o();225}226}227 228namespace GH89541 {229// Same as above; just check that this doesn't crash.230int one = 1;231auto factory(int& x = one) {232 return [&](this auto self) {233 x;234 };235};236 237using Base = decltype(factory());238struct Derived : Base {239 Derived() : Base(factory()) {}240};241 242void f() {243 Derived d;244 d();245}246}247 248 249namespace P2797 {250struct C {251 void c(this const C&); // #first252 void c() &; // #second253 static void c(int = 0); // #third254 255 void d() {256 (&C::c)(C{});257 (&C::c)();258 }259};260void test() {261 (void)C{}.d();262}263// CHECK-LABEL: {{.*}} @_ZN5P27971C1dEv264// CHECK: call void @_ZNH5P27971C1cERKS0_265// CHECK: call void @_ZN5P27971C1cEi266}267 268// This used to crash because we weren’t instantiating a dependent 'this'.269namespace GH154054 {270struct S {271 int x;272 auto byval() {273 return [*this](this auto) { return this->x; };274 }275};276 277// CHECK-LABEL: define {{.*}} void @_ZN8GH1540544mainEv278void main() {279 S s{ 42 };280 281 // CHECK: call {{.*}} i32 @_ZZN8GH1540541S5byvalEvENHUlT_E_clIS2_EEDaS1_282 if ( s.byval()() != 42)283 __builtin_abort();284}285 286// CHECK-LABEL: define {{.*}} i32 @_ZZN8GH1540541S5byvalEvENHUlT_E_clIS2_EEDaS1_(i32 %.coerce)287// CHECK: entry:288// CHECK: %0 = alloca %class.anon.11, align 4289// CHECK: %coerce.dive = getelementptr inbounds nuw %class.anon.11, ptr %0, i32 0, i32 0290// CHECK: %coerce.dive1 = getelementptr inbounds nuw %"struct.GH154054::S", ptr %coerce.dive, i32 0, i32 0291// CHECK: store i32 %.coerce, ptr %coerce.dive1, align 4292// CHECK: %1 = getelementptr inbounds nuw %class.anon.11, ptr %0, i32 0, i32 0293// CHECK: %x = getelementptr inbounds nuw %"struct.GH154054::S", ptr %1, i32 0, i32 0294// CHECK: %2 = load i32, ptr %x, align 4295// CHECK: ret i32 %2296 297struct s {298 int q;299 auto f() {300 return [*this](this auto) { return this; };301 }302};303 304// CHECK-LABEL: define {{.*}} void @_ZN8GH1540541fEv305void f() {306 // CHECK: call {{.*}} ptr @_ZZN8GH1540541s1fEvENHUlT_E_clIS2_EEDaS1_307 s{}.f()();308}309 310// CHECK-LABEL: define {{.*}} ptr @_ZZN8GH1540541s1fEvENHUlT_E_clIS2_EEDaS1_(i32 %.coerce)311// CHECK: entry:312// CHECK: %0 = alloca %class.anon.12, align 4313// CHECK: %coerce.dive = getelementptr inbounds nuw %class.anon.12, ptr %0, i32 0, i32 0314// CHECK: %coerce.dive1 = getelementptr inbounds nuw %"struct.GH154054::s", ptr %coerce.dive, i32 0, i32 0315// CHECK: store i32 %.coerce, ptr %coerce.dive1, align 4316// CHECK: %1 = getelementptr inbounds nuw %class.anon.12, ptr %0, i32 0, i32 0317// CHECK: ret ptr %1318}319