xref: /llvm-project/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp (revision db93ef14aef9c572e02bc842762bc4d0278148f9)
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