Skip to content

Commit 8c90808

Browse files
authored
Support for building thunks for C++ methods. (#5972)
Also tweak how we import C++ methods to properly handle C++23's explicit object parameters.
1 parent ddafbc9 commit 8c90808

File tree

7 files changed

+491
-105
lines changed

7 files changed

+491
-105
lines changed

toolchain/check/cpp_thunk.cpp

Lines changed: 198 additions & 91 deletions
Large diffs are not rendered by default.

toolchain/check/import_cpp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,8 +1277,9 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
12771277
return SemIR::InstBlockId::Empty;
12781278
}
12791279
llvm::SmallVector<SemIR::InstId> params;
1280-
params.reserve(clang_decl.parameters().size());
1281-
for (const clang::ParmVarDecl* param : clang_decl.parameters()) {
1280+
params.reserve(clang_decl.getNumNonObjectParams());
1281+
for (unsigned i : llvm::seq(clang_decl.getNumNonObjectParams())) {
1282+
const auto* param = clang_decl.getNonObjectParameter(i);
12821283
// TODO: Get the parameter type from the function, not from the
12831284
// `ParmVarDecl`. The type of the `ParmVarDecl` is the type within the
12841285
// function, and isn't in general the same as the type that's exposed to

toolchain/check/testdata/interop/cpp/class/base.carbon

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,15 @@ class V {
407407
// CHECK:STDOUT: %Base: type = class_type @Base [concrete]
408408
// CHECK:STDOUT: %Base.f.type: type = fn_type @Base.f [concrete]
409409
// CHECK:STDOUT: %Base.f: %Base.f.type = struct_value () [concrete]
410+
// CHECK:STDOUT: %const: type = const_type %Base [concrete]
411+
// CHECK:STDOUT: %ptr.a97: type = ptr_type %const [concrete]
412+
// CHECK:STDOUT: %f__carbon_thunk.type: type = fn_type @f__carbon_thunk [concrete]
413+
// CHECK:STDOUT: %f__carbon_thunk: %f__carbon_thunk.type = struct_value () [concrete]
414+
// CHECK:STDOUT: %ptr.fb2: type = ptr_type %Base [concrete]
410415
// CHECK:STDOUT: %Base.g.type: type = fn_type @Base.g [concrete]
411416
// CHECK:STDOUT: %Base.g: %Base.g.type = struct_value () [concrete]
417+
// CHECK:STDOUT: %g__carbon_thunk.type: type = fn_type @g__carbon_thunk [concrete]
418+
// CHECK:STDOUT: %g__carbon_thunk: %g__carbon_thunk.type = struct_value () [concrete]
412419
// CHECK:STDOUT: }
413420
// CHECK:STDOUT:
414421
// CHECK:STDOUT: imports {
@@ -424,11 +431,21 @@ class V {
424431
// CHECK:STDOUT: } {
425432
// CHECK:STDOUT: <elided>
426433
// CHECK:STDOUT: }
434+
// CHECK:STDOUT: %f__carbon_thunk.decl: %f__carbon_thunk.type = fn_decl @f__carbon_thunk [concrete = constants.%f__carbon_thunk] {
435+
// CHECK:STDOUT: <elided>
436+
// CHECK:STDOUT: } {
437+
// CHECK:STDOUT: <elided>
438+
// CHECK:STDOUT: }
427439
// CHECK:STDOUT: %Base.g.decl: %Base.g.type = fn_decl @Base.g [concrete = constants.%Base.g] {
428440
// CHECK:STDOUT: <elided>
429441
// CHECK:STDOUT: } {
430442
// CHECK:STDOUT: <elided>
431443
// CHECK:STDOUT: }
444+
// CHECK:STDOUT: %g__carbon_thunk.decl: %g__carbon_thunk.type = fn_decl @g__carbon_thunk [concrete = constants.%g__carbon_thunk] {
445+
// CHECK:STDOUT: <elided>
446+
// CHECK:STDOUT: } {
447+
// CHECK:STDOUT: <elided>
448+
// CHECK:STDOUT: }
432449
// CHECK:STDOUT: }
433450
// CHECK:STDOUT:
434451
// CHECK:STDOUT: fn @CallDirect(%d.param: %Derived) {
@@ -439,7 +456,11 @@ class V {
439456
// CHECK:STDOUT: %.loc8_3.1: ref %Base = class_element_access %d.ref, element0
440457
// CHECK:STDOUT: %.loc8_3.2: ref %Base = converted %d.ref, %.loc8_3.1
441458
// CHECK:STDOUT: %.loc8_3.3: %Base = bind_value %.loc8_3.2
442-
// CHECK:STDOUT: %Base.f.call: init %empty_tuple.type = call %Base.f.bound(%.loc8_3.3)
459+
// CHECK:STDOUT: %.loc8_3.4: ref %Base = value_as_ref %.loc8_3.3
460+
// CHECK:STDOUT: %addr: %ptr.fb2 = addr_of %.loc8_3.4
461+
// CHECK:STDOUT: %.loc8_7.1: %ptr.a97 = as_compatible %addr
462+
// CHECK:STDOUT: %.loc8_7.2: %ptr.a97 = converted %addr, %.loc8_7.1
463+
// CHECK:STDOUT: %f__carbon_thunk.call: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc8_7.2)
443464
// CHECK:STDOUT: <elided>
444465
// CHECK:STDOUT: }
445466
// CHECK:STDOUT:
@@ -453,7 +474,11 @@ class V {
453474
// CHECK:STDOUT: %.loc14_3.1: ref %Base = class_element_access %d.ref, element0
454475
// CHECK:STDOUT: %.loc14_3.2: ref %Base = converted %d.ref, %.loc14_3.1
455476
// CHECK:STDOUT: %.loc14_3.3: %Base = bind_value %.loc14_3.2
456-
// CHECK:STDOUT: %Base.g.call: init %empty_tuple.type = call %Base.g.bound(%.loc14_3.3)
477+
// CHECK:STDOUT: %.loc14_3.4: ref %Base = value_as_ref %.loc14_3.3
478+
// CHECK:STDOUT: %addr: %ptr.fb2 = addr_of %.loc14_3.4
479+
// CHECK:STDOUT: %.loc14_18.1: %ptr.a97 = as_compatible %addr
480+
// CHECK:STDOUT: %.loc14_18.2: %ptr.a97 = converted %addr, %.loc14_18.1
481+
// CHECK:STDOUT: %g__carbon_thunk.call: init %empty_tuple.type = call imports.%g__carbon_thunk.decl(%.loc14_18.2)
457482
// CHECK:STDOUT: <elided>
458483
// CHECK:STDOUT: }
459484
// CHECK:STDOUT:

toolchain/check/testdata/interop/cpp/class/method.carbon

Lines changed: 145 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Exceptions. See /LICENSE for license information.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
//
5-
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
5+
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon
6+
// EXTRA-ARGS: --clang-arg=-std=c++23
67
//
78
// AUTOUPDATE
89
// TIP: To test this file alone, run:
@@ -136,6 +137,31 @@ fn Ref(p: Cpp.HasQualifiers*) {
136137
p->const_ref_ref_this();
137138
}
138139

140+
// --- explicit_object_param.h
141+
142+
struct Another {
143+
};
144+
145+
struct ExplicitObjectParam {
146+
void F(this ExplicitObjectParam);
147+
void G(this int);
148+
void H(this Another);
149+
};
150+
151+
// --- call_explicit_object_param.carbon
152+
153+
library "[[@TEST_NAME]]";
154+
155+
import Cpp library "explicit_object_param.h";
156+
157+
fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
158+
//@dump-sem-ir-begin
159+
e.F();
160+
n.(Cpp.ExplicitObjectParam.G)();
161+
a.(Cpp.ExplicitObjectParam.H)();
162+
//@dump-sem-ir-end
163+
}
164+
139165
// CHECK:STDOUT: --- use_object_param_qualifiers.carbon
140166
// CHECK:STDOUT:
141167
// CHECK:STDOUT: constants {
@@ -144,8 +170,14 @@ fn Ref(p: Cpp.HasQualifiers*) {
144170
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
145171
// CHECK:STDOUT: %HasQualifiers.const_this.type: type = fn_type @HasQualifiers.const_this [concrete]
146172
// CHECK:STDOUT: %HasQualifiers.const_this: %HasQualifiers.const_this.type = struct_value () [concrete]
173+
// CHECK:STDOUT: %const: type = const_type %HasQualifiers [concrete]
174+
// CHECK:STDOUT: %ptr.2cb: type = ptr_type %const [concrete]
175+
// CHECK:STDOUT: %const_this__carbon_thunk.type: type = fn_type @const_this__carbon_thunk [concrete]
176+
// CHECK:STDOUT: %const_this__carbon_thunk: %const_this__carbon_thunk.type = struct_value () [concrete]
147177
// CHECK:STDOUT: %HasQualifiers.const_ref_this.type: type = fn_type @HasQualifiers.const_ref_this [concrete]
148178
// CHECK:STDOUT: %HasQualifiers.const_ref_this: %HasQualifiers.const_ref_this.type = struct_value () [concrete]
179+
// CHECK:STDOUT: %const_ref_this__carbon_thunk.type: type = fn_type @const_ref_this__carbon_thunk [concrete]
180+
// CHECK:STDOUT: %const_ref_this__carbon_thunk: %const_ref_this__carbon_thunk.type = struct_value () [concrete]
149181
// CHECK:STDOUT: %HasQualifiers.plain.type: type = fn_type @HasQualifiers.plain [concrete]
150182
// CHECK:STDOUT: %HasQualifiers.plain: %HasQualifiers.plain.type = struct_value () [concrete]
151183
// CHECK:STDOUT: %HasQualifiers.ref_this.type: type = fn_type @HasQualifiers.ref_this [concrete]
@@ -158,11 +190,21 @@ fn Ref(p: Cpp.HasQualifiers*) {
158190
// CHECK:STDOUT: } {
159191
// CHECK:STDOUT: <elided>
160192
// CHECK:STDOUT: }
193+
// CHECK:STDOUT: %const_this__carbon_thunk.decl: %const_this__carbon_thunk.type = fn_decl @const_this__carbon_thunk [concrete = constants.%const_this__carbon_thunk] {
194+
// CHECK:STDOUT: <elided>
195+
// CHECK:STDOUT: } {
196+
// CHECK:STDOUT: <elided>
197+
// CHECK:STDOUT: }
161198
// CHECK:STDOUT: %HasQualifiers.const_ref_this.decl: %HasQualifiers.const_ref_this.type = fn_decl @HasQualifiers.const_ref_this [concrete = constants.%HasQualifiers.const_ref_this] {
162199
// CHECK:STDOUT: <elided>
163200
// CHECK:STDOUT: } {
164201
// CHECK:STDOUT: <elided>
165202
// CHECK:STDOUT: }
203+
// CHECK:STDOUT: %const_ref_this__carbon_thunk.decl: %const_ref_this__carbon_thunk.type = fn_decl @const_ref_this__carbon_thunk [concrete = constants.%const_ref_this__carbon_thunk] {
204+
// CHECK:STDOUT: <elided>
205+
// CHECK:STDOUT: } {
206+
// CHECK:STDOUT: <elided>
207+
// CHECK:STDOUT: }
166208
// CHECK:STDOUT: %HasQualifiers.plain.decl: %HasQualifiers.plain.type = fn_decl @HasQualifiers.plain [concrete = constants.%HasQualifiers.plain] {
167209
// CHECK:STDOUT: <elided>
168210
// CHECK:STDOUT: } {
@@ -180,11 +222,19 @@ fn Ref(p: Cpp.HasQualifiers*) {
180222
// CHECK:STDOUT: %v.ref.loc8: %HasQualifiers = name_ref v, %v
181223
// CHECK:STDOUT: %const_this.ref.loc8: %HasQualifiers.const_this.type = name_ref const_this, imports.%HasQualifiers.const_this.decl [concrete = constants.%HasQualifiers.const_this]
182224
// CHECK:STDOUT: %HasQualifiers.const_this.bound.loc8: <bound method> = bound_method %v.ref.loc8, %const_this.ref.loc8
183-
// CHECK:STDOUT: %HasQualifiers.const_this.call.loc8: init %empty_tuple.type = call %HasQualifiers.const_this.bound.loc8(%v.ref.loc8)
225+
// CHECK:STDOUT: %.loc8_3: ref %HasQualifiers = value_as_ref %v.ref.loc8
226+
// CHECK:STDOUT: %addr.loc8: %ptr.ec3 = addr_of %.loc8_3
227+
// CHECK:STDOUT: %.loc8_16.1: %ptr.2cb = as_compatible %addr.loc8
228+
// CHECK:STDOUT: %.loc8_16.2: %ptr.2cb = converted %addr.loc8, %.loc8_16.1
229+
// CHECK:STDOUT: %const_this__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%const_this__carbon_thunk.decl(%.loc8_16.2)
184230
// CHECK:STDOUT: %v.ref.loc9: %HasQualifiers = name_ref v, %v
185231
// CHECK:STDOUT: %const_ref_this.ref.loc9: %HasQualifiers.const_ref_this.type = name_ref const_ref_this, imports.%HasQualifiers.const_ref_this.decl [concrete = constants.%HasQualifiers.const_ref_this]
186232
// CHECK:STDOUT: %HasQualifiers.const_ref_this.bound.loc9: <bound method> = bound_method %v.ref.loc9, %const_ref_this.ref.loc9
187-
// CHECK:STDOUT: %HasQualifiers.const_ref_this.call.loc9: init %empty_tuple.type = call %HasQualifiers.const_ref_this.bound.loc9(%v.ref.loc9)
233+
// CHECK:STDOUT: %.loc9_3: ref %HasQualifiers = value_as_ref %v.ref.loc9
234+
// CHECK:STDOUT: %addr.loc9: %ptr.ec3 = addr_of %.loc9_3
235+
// CHECK:STDOUT: %.loc9_20.1: %ptr.2cb = as_compatible %addr.loc9
236+
// CHECK:STDOUT: %.loc9_20.2: %ptr.2cb = converted %addr.loc9, %.loc9_20.1
237+
// CHECK:STDOUT: %const_ref_this__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%const_ref_this__carbon_thunk.decl(%.loc9_20.2)
188238
// CHECK:STDOUT: %p.ref.loc11: %ptr.ec3 = name_ref p, %p
189239
// CHECK:STDOUT: %.loc11: ref %HasQualifiers = deref %p.ref.loc11
190240
// CHECK:STDOUT: %plain.ref: %HasQualifiers.plain.type = name_ref plain, imports.%HasQualifiers.plain.decl [concrete = constants.%HasQualifiers.plain]
@@ -202,13 +252,103 @@ fn Ref(p: Cpp.HasQualifiers*) {
202252
// CHECK:STDOUT: %const_this.ref.loc13: %HasQualifiers.const_this.type = name_ref const_this, imports.%HasQualifiers.const_this.decl [concrete = constants.%HasQualifiers.const_this]
203253
// CHECK:STDOUT: %HasQualifiers.const_this.bound.loc13: <bound method> = bound_method %.loc13_4.1, %const_this.ref.loc13
204254
// CHECK:STDOUT: %.loc13_4.2: %HasQualifiers = bind_value %.loc13_4.1
205-
// CHECK:STDOUT: %HasQualifiers.const_this.call.loc13: init %empty_tuple.type = call %HasQualifiers.const_this.bound.loc13(%.loc13_4.2)
255+
// CHECK:STDOUT: %.loc13_4.3: ref %HasQualifiers = value_as_ref %.loc13_4.2
256+
// CHECK:STDOUT: %addr.loc13: %ptr.ec3 = addr_of %.loc13_4.3
257+
// CHECK:STDOUT: %.loc13_17.1: %ptr.2cb = as_compatible %addr.loc13
258+
// CHECK:STDOUT: %.loc13_17.2: %ptr.2cb = converted %addr.loc13, %.loc13_17.1
259+
// CHECK:STDOUT: %const_this__carbon_thunk.call.loc13: init %empty_tuple.type = call imports.%const_this__carbon_thunk.decl(%.loc13_17.2)
206260
// CHECK:STDOUT: %p.ref.loc14: %ptr.ec3 = name_ref p, %p
207261
// CHECK:STDOUT: %.loc14_4.1: ref %HasQualifiers = deref %p.ref.loc14
208262
// CHECK:STDOUT: %const_ref_this.ref.loc14: %HasQualifiers.const_ref_this.type = name_ref const_ref_this, imports.%HasQualifiers.const_ref_this.decl [concrete = constants.%HasQualifiers.const_ref_this]
209263
// CHECK:STDOUT: %HasQualifiers.const_ref_this.bound.loc14: <bound method> = bound_method %.loc14_4.1, %const_ref_this.ref.loc14
210264
// CHECK:STDOUT: %.loc14_4.2: %HasQualifiers = bind_value %.loc14_4.1
211-
// CHECK:STDOUT: %HasQualifiers.const_ref_this.call.loc14: init %empty_tuple.type = call %HasQualifiers.const_ref_this.bound.loc14(%.loc14_4.2)
265+
// CHECK:STDOUT: %.loc14_4.3: ref %HasQualifiers = value_as_ref %.loc14_4.2
266+
// CHECK:STDOUT: %addr.loc14: %ptr.ec3 = addr_of %.loc14_4.3
267+
// CHECK:STDOUT: %.loc14_21.1: %ptr.2cb = as_compatible %addr.loc14
268+
// CHECK:STDOUT: %.loc14_21.2: %ptr.2cb = converted %addr.loc14, %.loc14_21.1
269+
// CHECK:STDOUT: %const_ref_this__carbon_thunk.call.loc14: init %empty_tuple.type = call imports.%const_ref_this__carbon_thunk.decl(%.loc14_21.2)
270+
// CHECK:STDOUT: <elided>
271+
// CHECK:STDOUT: }
272+
// CHECK:STDOUT:
273+
// CHECK:STDOUT: --- call_explicit_object_param.carbon
274+
// CHECK:STDOUT:
275+
// CHECK:STDOUT: constants {
276+
// CHECK:STDOUT: %ExplicitObjectParam: type = class_type @ExplicitObjectParam [concrete]
277+
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
278+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
279+
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
280+
// CHECK:STDOUT: %Another: type = class_type @Another [concrete]
281+
// CHECK:STDOUT: %ExplicitObjectParam.F.type: type = fn_type @ExplicitObjectParam.F [concrete]
282+
// CHECK:STDOUT: %ExplicitObjectParam.F: %ExplicitObjectParam.F.type = struct_value () [concrete]
283+
// CHECK:STDOUT: %ptr.7f5: type = ptr_type %ExplicitObjectParam [concrete]
284+
// CHECK:STDOUT: %F__carbon_thunk.type: type = fn_type @F__carbon_thunk [concrete]
285+
// CHECK:STDOUT: %F__carbon_thunk: %F__carbon_thunk.type = struct_value () [concrete]
286+
// CHECK:STDOUT: %ExplicitObjectParam.G.type: type = fn_type @ExplicitObjectParam.G [concrete]
287+
// CHECK:STDOUT: %ExplicitObjectParam.G: %ExplicitObjectParam.G.type = struct_value () [concrete]
288+
// CHECK:STDOUT: %ExplicitObjectParam.H.type: type = fn_type @ExplicitObjectParam.H [concrete]
289+
// CHECK:STDOUT: %ExplicitObjectParam.H: %ExplicitObjectParam.H.type = struct_value () [concrete]
290+
// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete]
291+
// CHECK:STDOUT: %H__carbon_thunk.type: type = fn_type @H__carbon_thunk [concrete]
292+
// CHECK:STDOUT: %H__carbon_thunk: %H__carbon_thunk.type = struct_value () [concrete]
293+
// CHECK:STDOUT: }
294+
// CHECK:STDOUT:
295+
// CHECK:STDOUT: imports {
296+
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
297+
// CHECK:STDOUT: .ExplicitObjectParam = %ExplicitObjectParam.decl
298+
// CHECK:STDOUT: .Another = %Another.decl
299+
// CHECK:STDOUT: import Cpp//...
300+
// CHECK:STDOUT: }
301+
// CHECK:STDOUT: %ExplicitObjectParam.decl: type = class_decl @ExplicitObjectParam [concrete = constants.%ExplicitObjectParam] {} {}
302+
// CHECK:STDOUT: %Another.decl: type = class_decl @Another [concrete = constants.%Another] {} {}
303+
// CHECK:STDOUT: %ExplicitObjectParam.F.decl: %ExplicitObjectParam.F.type = fn_decl @ExplicitObjectParam.F [concrete = constants.%ExplicitObjectParam.F] {
304+
// CHECK:STDOUT: <elided>
305+
// CHECK:STDOUT: } {
306+
// CHECK:STDOUT: <elided>
307+
// CHECK:STDOUT: }
308+
// CHECK:STDOUT: %F__carbon_thunk.decl: %F__carbon_thunk.type = fn_decl @F__carbon_thunk [concrete = constants.%F__carbon_thunk] {
309+
// CHECK:STDOUT: <elided>
310+
// CHECK:STDOUT: } {
311+
// CHECK:STDOUT: <elided>
312+
// CHECK:STDOUT: }
313+
// CHECK:STDOUT: %ExplicitObjectParam.G.decl: %ExplicitObjectParam.G.type = fn_decl @ExplicitObjectParam.G [concrete = constants.%ExplicitObjectParam.G] {
314+
// CHECK:STDOUT: <elided>
315+
// CHECK:STDOUT: } {
316+
// CHECK:STDOUT: <elided>
317+
// CHECK:STDOUT: }
318+
// CHECK:STDOUT: %ExplicitObjectParam.H.decl: %ExplicitObjectParam.H.type = fn_decl @ExplicitObjectParam.H [concrete = constants.%ExplicitObjectParam.H] {
319+
// CHECK:STDOUT: <elided>
320+
// CHECK:STDOUT: } {
321+
// CHECK:STDOUT: <elided>
322+
// CHECK:STDOUT: }
323+
// CHECK:STDOUT: %H__carbon_thunk.decl: %H__carbon_thunk.type = fn_decl @H__carbon_thunk [concrete = constants.%H__carbon_thunk] {
324+
// CHECK:STDOUT: <elided>
325+
// CHECK:STDOUT: } {
326+
// CHECK:STDOUT: <elided>
327+
// CHECK:STDOUT: }
328+
// CHECK:STDOUT: }
329+
// CHECK:STDOUT:
330+
// CHECK:STDOUT: fn @Call(%e.param: %ExplicitObjectParam, %n.param: %i32, %a.param: %Another) {
331+
// CHECK:STDOUT: !entry:
332+
// CHECK:STDOUT: %e.ref: %ExplicitObjectParam = name_ref e, %e
333+
// CHECK:STDOUT: %F.ref: %ExplicitObjectParam.F.type = name_ref F, imports.%ExplicitObjectParam.F.decl [concrete = constants.%ExplicitObjectParam.F]
334+
// CHECK:STDOUT: %ExplicitObjectParam.F.bound: <bound method> = bound_method %e.ref, %F.ref
335+
// CHECK:STDOUT: %.loc8: ref %ExplicitObjectParam = value_as_ref %e.ref
336+
// CHECK:STDOUT: %addr.loc8: %ptr.7f5 = addr_of %.loc8
337+
// CHECK:STDOUT: %F__carbon_thunk.call: init %empty_tuple.type = call imports.%F__carbon_thunk.decl(%addr.loc8)
338+
// CHECK:STDOUT: %n.ref: %i32 = name_ref n, %n
339+
// CHECK:STDOUT: %Cpp.ref.loc9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
340+
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
341+
// CHECK:STDOUT: %G.ref: %ExplicitObjectParam.G.type = name_ref G, imports.%ExplicitObjectParam.G.decl [concrete = constants.%ExplicitObjectParam.G]
342+
// CHECK:STDOUT: %ExplicitObjectParam.G.bound: <bound method> = bound_method %n.ref, %G.ref
343+
// CHECK:STDOUT: %ExplicitObjectParam.G.call: init %empty_tuple.type = call %ExplicitObjectParam.G.bound(%n.ref)
344+
// CHECK:STDOUT: %a.ref: %Another = name_ref a, %a
345+
// CHECK:STDOUT: %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
346+
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
347+
// CHECK:STDOUT: %H.ref: %ExplicitObjectParam.H.type = name_ref H, imports.%ExplicitObjectParam.H.decl [concrete = constants.%ExplicitObjectParam.H]
348+
// CHECK:STDOUT: %ExplicitObjectParam.H.bound: <bound method> = bound_method %a.ref, %H.ref
349+
// CHECK:STDOUT: %.loc10: ref %Another = value_as_ref %a.ref
350+
// CHECK:STDOUT: %addr.loc10: %ptr.289 = addr_of %.loc10
351+
// CHECK:STDOUT: %H__carbon_thunk.call: init %empty_tuple.type = call imports.%H__carbon_thunk.decl(%addr.loc10)
212352
// CHECK:STDOUT: <elided>
213353
// CHECK:STDOUT: }
214354
// CHECK:STDOUT:

0 commit comments

Comments
 (0)