Fix mangling collision for C++ class template specializations (#7269)

Carbon-side thunks (for example the `Copy`/`Destroy` witness thunks
generated for imported C++ types) are mangled by Carbon, and their names
incorporate a fingerprint of the involved types. The instruction
fingerprinter identifies a class only by its name and parent scope,
which is sufficient for Carbon classes but not for imported C++ classes:
different specializations of one class template (and other cases such as
types in anonymous namespaces) share a Carbon name and parent scope. As
a result, the thunks for two distinct specializations could mangle to
the same name, producing a single LLVM function with two definitions and
failing `verifyModule` during lowering.

When fingerprinting a class imported from C++, also include the Clang
mangled name of its type.

Test: toolchain/lower/testdata/interop/cpp/thunks.carbon gains a split
with two specializations of one class template, each requiring a thunk;
their thunks now get distinct mangled names instead of colliding.

Assisted-by: Claude Code

---------

Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
This commit is contained in:
Chandler Carruth
2026-05-30 08:13:00 +00:00
committed by GitHub
co-authored by Christopher Di Bella
parent 3ef128ac91
commit 8a59f2a76b
64 changed files with 4762 additions and 4330 deletions
@@ -603,7 +603,7 @@ fn F() {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -629,7 +629,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -678,7 +678,7 @@ fn F() {
// CHECK:STDOUT: %make.cpp_overload_set.type: type = cpp_overload_set_type @make.cpp_overload_set [concrete]
// CHECK:STDOUT: %make.cpp_overload_set.value: %make.cpp_overload_set.type = cpp_overload_set_value @make.cpp_overload_set [concrete]
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %make__carbon_thunk.type: type = fn_type @make__carbon_thunk [concrete]
// CHECK:STDOUT: %make__carbon_thunk: %make__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
@@ -712,11 +712,11 @@ fn F() {
// CHECK:STDOUT: %Cpp.ref.loc8_11: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %make.ref: %make.cpp_overload_set.type = name_ref make, imports.%make.cpp_overload_set.value [concrete = constants.%make.cpp_overload_set.value]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %addr.loc8_20: %ptr.dbb = addr_of %_.var
// CHECK:STDOUT: %addr.loc8_20: %ptr.3a8 = addr_of %_.var
// CHECK:STDOUT: %make__carbon_thunk.call: init %empty_tuple.type = call imports.%make__carbon_thunk.decl(%addr.loc8_20)
// CHECK:STDOUT: %.loc8: init %C to %_.var = mark_in_place_init %make__carbon_thunk.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %addr.loc8_21: %ptr.dbb = addr_of %_.var
// CHECK:STDOUT: %addr.loc8_21: %ptr.3a8 = addr_of %_.var
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -728,7 +728,7 @@ fn F() {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -754,7 +754,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -766,7 +766,7 @@ fn F() {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -792,7 +792,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -801,11 +801,11 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %pattern_type.8ab: type = pattern_type %C [concrete]
// CHECK:STDOUT: %pattern_type.908: type = pattern_type %C [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.d15: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.58d: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
@@ -816,9 +816,9 @@ fn F() {
// CHECK:STDOUT: %C.Op.type: type = fn_type @C.Op [concrete]
// CHECK:STDOUT: %C.Op: %C.Op.type = struct_value () [concrete]
// CHECK:STDOUT: %custom_witness.3d0: <witness> = custom_witness (%C.Op), @Default [concrete]
// CHECK:STDOUT: %Default.facet.8ae: %Default.type = facet_value %C, (%custom_witness.3d0) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.a4e: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table.b72, @T.as_type.as.DefaultOrUnformed.impl(%Default.facet.8ae) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %C, (%DefaultOrUnformed.impl_witness.a4e) [concrete]
// CHECK:STDOUT: %Default.facet.a4a: %Default.type = facet_value %C, (%custom_witness.3d0) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.736: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table.b72, @T.as_type.as.DefaultOrUnformed.impl(%Default.facet.a4a) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %C, (%DefaultOrUnformed.impl_witness.736) [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -850,14 +850,14 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.d15 = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.58d = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.8ab = ref_binding_pattern x [concrete]
// CHECK:STDOUT: %x.var_patt: %pattern_type.8ab = var_pattern %x.patt [concrete]
// CHECK:STDOUT: %x.patt: %pattern_type.908 = ref_binding_pattern x [concrete]
// CHECK:STDOUT: %x.var_patt: %pattern_type.908 = var_pattern %x.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %x.var: ref %C = var %x.var_patt
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%C, (constants.%DefaultOrUnformed.impl_witness.a4e) [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%C, (constants.%DefaultOrUnformed.impl_witness.736) [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %.loc10_24.1: %DefaultOrUnformed.type = converted constants.%C, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %as_type: type = facet_access_type %.loc10_24.1 [concrete = constants.%C]
// CHECK:STDOUT: %.loc10_24.2: type = converted %.loc10_24.1, %as_type [concrete = constants.%C]
@@ -883,7 +883,7 @@ fn F() {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.4c9: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.b51: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -918,7 +918,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.4c9 = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.b51 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -931,10 +931,10 @@ fn F() {
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.714: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.010: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %pattern_type.194: type = pattern_type %O [concrete]
// CHECK:STDOUT: %pattern_type.554: type = pattern_type %O [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
// CHECK:STDOUT: %Default.type: type = facet_type <@Default> [concrete]
// CHECK:STDOUT: %T.4ca: %Default.type = symbolic_binding T, 0 [symbolic]
@@ -943,9 +943,9 @@ fn F() {
// CHECK:STDOUT: %O.Op.type: type = fn_type @O.Op [concrete]
// CHECK:STDOUT: %O.Op: %O.Op.type = struct_value () [concrete]
// CHECK:STDOUT: %custom_witness.213: <witness> = custom_witness (%O.Op), @Default [concrete]
// CHECK:STDOUT: %Default.facet.15f: %Default.type = facet_value %O, (%custom_witness.213) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.424: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table.b72, @T.as_type.as.DefaultOrUnformed.impl(%Default.facet.15f) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %O, (%DefaultOrUnformed.impl_witness.424) [concrete]
// CHECK:STDOUT: %Default.facet.478: %Default.type = facet_value %O, (%custom_witness.213) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.1cc: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table.b72, @T.as_type.as.DefaultOrUnformed.impl(%Default.facet.478) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %O, (%DefaultOrUnformed.impl_witness.1cc) [concrete]
// CHECK:STDOUT: %O.cpp_destructor.type: type = fn_type @O.cpp_destructor [concrete]
// CHECK:STDOUT: %O.cpp_destructor: %O.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -973,14 +973,14 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.714 = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.010 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.194 = ref_binding_pattern x [concrete]
// CHECK:STDOUT: %x.var_patt: %pattern_type.194 = var_pattern %x.patt [concrete]
// CHECK:STDOUT: %x.patt: %pattern_type.554 = ref_binding_pattern x [concrete]
// CHECK:STDOUT: %x.var_patt: %pattern_type.554 = var_pattern %x.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %x.var: ref %O = var %x.var_patt
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%O, (constants.%DefaultOrUnformed.impl_witness.424) [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%O, (constants.%DefaultOrUnformed.impl_witness.1cc) [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %.loc9_22.1: %DefaultOrUnformed.type = converted constants.%O, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %as_type: type = facet_access_type %.loc9_22.1 [concrete = constants.%O]
// CHECK:STDOUT: %.loc9_22.2: type = converted %.loc9_22.1, %as_type [concrete = constants.%O]
@@ -1009,7 +1009,7 @@ fn F() {
// CHECK:STDOUT: %C.bar: %C.bar.type = struct_value () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -1041,7 +1041,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc9: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc9
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc9
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -1053,7 +1053,7 @@ fn F() {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %C.bar.cpp_overload_set.type: type = cpp_overload_set_type @C.bar.cpp_overload_set [concrete]
@@ -1085,7 +1085,7 @@ fn F() {
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %.loc8: ref %C = value_as_ref %c.ref
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc8
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc8
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %Cpp.ref.loc9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, imports.%C.decl [concrete = constants.%C]
@@ -1173,7 +1173,7 @@ fn F() {
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %ptr.dbb: type = ptr_type %C [concrete]
// CHECK:STDOUT: %ptr.3a8: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
@@ -1198,7 +1198,7 @@ fn F() {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %.loc8_11.1: ref %C = temporary_storage
// CHECK:STDOUT: %addr: %ptr.dbb = addr_of %.loc8_11.1
// CHECK:STDOUT: %addr: %ptr.3a8 = addr_of %.loc8_11.1
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %.loc8_11.2: init %C to %.loc8_11.1 = mark_in_place_init %foo__carbon_thunk.call
// CHECK:STDOUT: %.loc8_11.3: ref %C = temporary %.loc8_11.1, %.loc8_11.2