// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-linux -o - | FileCheck %s struct TrivialStruct { void explicit_object_function(this TrivialStruct) {} }; void test() { TrivialStruct s; s.explicit_object_function(); } // CHECK: define {{.*}}test{{.*}} // CHECK-NEXT: entry: // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 // CHECK: call void {{.*}}explicit_object_function{{.*}} // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK: define {{.*}}explicit_object_function{{.*}} // CHECK-NEXT: entry: // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 // CHECK: ret void // CHECK-NEXT: } void test_lambda() { [](this auto This) -> int { return This(); }(); } //CHECK: define dso_local void @{{.*}}test_lambda{{.*}}() #0 { //CHECK: entry: //CHECK: %agg.tmp = alloca %class.anon, align 1 //CHECK: %ref.tmp = alloca %class.anon, align 1 //CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() //CHECK: ret void //CHECK: } //CHECK: define internal noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() #0 align 2 { //CHECK: entry: //CHECK: %This = alloca %class.anon, align 1 //CHECK: %agg.tmp = alloca %class.anon, align 1 //CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() //CHECK: ret i32 %call //CHECK: } void test_lambda_ref() { auto l = [i = 42](this auto & This, int j) -> int { return This(j); }; l(0); } // CHECK: define dso_local void @_Z15test_lambda_refv() #0 { // CHECK: entry: // CHECK: %[[This_address:.]] = alloca %class.anon{{.*}}, align 4 // CHECK: %[[i_addr:.*]] = getelementptr inbounds %class.anon{{.*}}, ptr %[[This_address]], i32 0, i32 0 // CHECK: store i32 42, ptr %[[i_addr]], align 4 // CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} // CHECK: ret void // CHECK: } // CHECK: define internal noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} // CHECK: entry: // CHECK: %This.addr = alloca ptr, align 8 // CHECK: %j.addr = alloca i32, align 4 // CHECK: store ptr %This, ptr %This.addr, align 8 // CHECK: store i32 %j, ptr %j.addr, align 4 // CHECK: %[[this_addr:.*]] = load ptr, ptr %This.addr, align 8 // CHECK: %[[j_addr:.*]] = load i32, ptr %j.addr, align 4 // CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"(ptr noundef nonnull align 4 dereferenceable(4) %[[this_addr]], i32 noundef %[[j_addr]]) // CHECK: ret i32 %call // CHECK: } struct TestPointer { void f(this TestPointer &); }; void test_pointer() { TestPointer t; using Fn = void(TestPointer&); Fn* fn = &TestPointer::f; fn(t); } //CHECK: define dso_local void @_Z12test_pointerv() #0 { //CHECK-NEXT: entry: //CHECK-NEXT: %t = alloca %struct.TestPointer, align 1 //CHECK-NEXT: %fn = alloca ptr, align 8 //CHECK-NEXT: store ptr @_ZNH11TestPointer1fERS_, ptr %fn, align 8 //CHECK: %[[fn_ptr:.*]] = load ptr, ptr %fn, align 8 //CHECK-NEXT: call void %[[fn_ptr]](ptr noundef nonnull align 1 dereferenceable(1) %t) //CHECK-NEXT: ret void //CHECK-NEXT: } struct MaterializedTemporary { void foo(this MaterializedTemporary&&); MaterializedTemporary(); ~MaterializedTemporary(); }; void test_temporary() { MaterializedTemporary{}.foo(); } //CHECK: define dso_local void @_Z14test_temporaryv(){{.*}} //CHECK-NEXT: entry: //CHECK: %ref.tmp = alloca %struct.MaterializedTemporary, align 1 //CHECK: call void @_ZN21MaterializedTemporaryC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}} //CHECK invoke void @_ZNH21MaterializedTemporary3fooEOS_(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}}