1 // RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-linux -o - | FileCheck %s 2 3 struct TrivialStruct { 4 void explicit_object_function(this TrivialStruct) {} 5 }; 6 void test() { 7 TrivialStruct s; 8 s.explicit_object_function(); 9 } 10 // CHECK: define {{.*}}test{{.*}} 11 // CHECK-NEXT: entry: 12 // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 13 // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 14 // CHECK: call void {{.*}}explicit_object_function{{.*}} 15 // CHECK-NEXT: ret void 16 // CHECK-NEXT: } 17 18 // CHECK: define {{.*}}explicit_object_function{{.*}} 19 // CHECK-NEXT: entry: 20 // CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 21 // CHECK: ret void 22 // CHECK-NEXT: } 23 24 25 void 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 1 34 //CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() 35 //CHECK: ret void 36 //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 1 41 //CHECK: %agg.tmp = alloca %class.anon, align 1 42 //CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() 43 //CHECK: ret i32 %call 44 //CHECK: } 45 46 void 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 4 56 // CHECK: %[[i_addr:.*]] = getelementptr inbounds nuw %class.anon{{.*}}, ptr %[[This_address]], i32 0, i32 0 57 // CHECK: store i32 42, ptr %[[i_addr]], align 4 58 // CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} 59 // CHECK: ret void 60 // CHECK: } 61 62 // CHECK: define internal noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} 63 // CHECK: entry: 64 // CHECK: %This.addr = alloca ptr, align 8 65 // CHECK: %j.addr = alloca i32, align 4 66 // CHECK: store ptr %This, ptr %This.addr, align 8 67 // CHECK: store i32 %j, ptr %j.addr, align 4 68 // CHECK: %[[this_addr:.*]] = load ptr, ptr %This.addr, align 8 69 // CHECK: %[[j_addr:.*]] = load i32, ptr %j.addr, align 4 70 // 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 %call 72 // CHECK: } 73 74 75 struct TestPointer { 76 void f(this TestPointer &); 77 }; 78 79 void 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 1 88 //CHECK-NEXT: %fn = alloca ptr, align 8 89 //CHECK-NEXT: store ptr @_ZNH11TestPointer1fERS_, ptr %fn, align 8 90 //CHECK: %[[fn_ptr:.*]] = load ptr, ptr %fn, align 8 91 //CHECK-NEXT: call void %[[fn_ptr]](ptr noundef nonnull align 1 dereferenceable(1) %t) 92 //CHECK-NEXT: ret void 93 //CHECK-NEXT: } 94 95 96 struct MaterializedTemporary { 97 void foo(this MaterializedTemporary&&); 98 MaterializedTemporary(); 99 ~MaterializedTemporary(); 100 }; 101 102 void 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 1 109 //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 112 namespace GH86399 { 113 volatile int a = 0; 114 struct function { 115 function& operator=(function const&) { 116 a = 1; 117 return *this; 118 } 119 }; 120 121 void f() { 122 function list; 123 124 //CHECK-LABEL: define internal void @"_ZZN7GH863991f{{.*}}"(ptr %{{.*}}) 125 //CHECK: call {{.*}} @_ZN7GH863998functionaSERKS0_ 126 //CHECK-NEXT: ret void 127 [&list](this auto self) { 128 list = function{}; 129 }(); 130 } 131 } 132 133 namespace GH84163 { 134 // Just check that this doesn't crash (we were previously not instantiating 135 // everything that needs instantiating in here). 136 template <typename> struct S {}; 137 138 void a() { 139 int x; 140 const auto l = [&x](this auto&) { S<decltype(x)> q; }; 141 l(); 142 } 143 } 144 145 namespace GH84425 { 146 // As above. 147 void 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 156 void 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 166 namespace GH79754 { 167 // As above. 168 void f() { 169 int x; 170 [&x](this auto&&) {return x;}(); 171 } 172 } 173 174 namespace GH70604 { 175 auto dothing(int num) 176 { 177 auto fun = [&num](this auto&& self) -> void { 178 auto copy = num; 179 }; 180 181 fun(); 182 } 183 } 184 185 namespace GH87210 { 186 template <typename... Ts> 187 struct Overloaded : Ts... { 188 using Ts::operator()...; 189 }; 190 191 template <typename... Ts> 192 Overloaded(Ts...) -> Overloaded<Ts...>; 193 194 // CHECK-LABEL: define dso_local void @_ZN7GH872101fEv() 195 // CHECK-NEXT: entry: 196 // CHECK-NEXT: [[X:%.*]] = alloca i32 197 // CHECK-NEXT: [[Over:%.*]] = alloca %"{{.*}}Overloaded" 198 // CHECK: call noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Over]]) 199 void 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 ptr 205 // 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 0 208 // 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 217 void g() { 218 int x; 219 Overloaded o { 220 [=](this auto& self) { 221 return x; 222 } 223 }; 224 o(); 225 } 226 } 227 228 namespace GH89541 { 229 // Same as above; just check that this doesn't crash. 230 int one = 1; 231 auto factory(int& x = one) { 232 return [&](this auto self) { 233 x; 234 }; 235 }; 236 237 using Base = decltype(factory()); 238 struct Derived : Base { 239 Derived() : Base(factory()) {} 240 }; 241 242 void f() { 243 Derived d; 244 d(); 245 } 246 } 247 248 249 namespace P2797 { 250 struct C { 251 void c(this const C&); // #first 252 void c() &; // #second 253 static void c(int = 0); // #third 254 255 void d() { 256 (&C::c)(C{}); 257 (&C::c)(); 258 } 259 }; 260 void test() { 261 (void)C{}.d(); 262 } 263 // CHECK-LABEL: {{.*}} @_ZN5P27971C1dEv 264 // CHECK: call void @_ZNH5P27971C1cERKS0_ 265 // CHECK: call void @_ZN5P27971C1cEi 266 } 267