Destroy temporaries at the end of expression statements. (#7513)

Instead of tracking the cleanup scope depth on entry to each scope,
track an "ambient" cleanup scope depth that's *after* the destructors of
local variables in that scope. This gets increased to include the
destructors of local variables when we create a name-binding
declaration. Then, when we reach a point where temporaries should be
destroyed, run cleanups that are after the ambient cleanup scope depth
on the stack. This happens:

* At the `;` of a statement expression.
* At the `)` of an `if` or `while` statement.
* After performing the implied `HasValue()` call in a `for` statement.

Per informal agreement with leads, this means we lifetime-extend all
temporaries created in the initializer of a name-binding declaration to
the full scope of that declaration, but that temporaries created in an
expression statement are destroyed at the `;`.
This commit is contained in:
Richard Smith
2026-07-16 15:12:39 +00:00
committed by GitHub
parent 81e495ee53
commit 703529fc55
37 changed files with 844 additions and 384 deletions
@@ -1942,14 +1942,14 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %ptr.0a2: type = ptr_type %C [concrete]
// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete]
// CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [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: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %C.Overload.cpp_overload_set.type: type = cpp_overload_set_type @C.Overload.cpp_overload_set [concrete]
// CHECK:STDOUT: %C.Overload.cpp_overload_set.value: %C.Overload.cpp_overload_set.type = cpp_overload_set_value @C.Overload.cpp_overload_set [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type: type = fn_type @Overload__carbon_thunk [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk: %Overload__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [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: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2001,6 +2001,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %C__carbon_thunk.call: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%addr.loc8_38.1, %addr.loc8_38.2)
// CHECK:STDOUT: %.loc8_38.2: init %C to %.loc8_38.1 = mark_in_place_init %C__carbon_thunk.call
// CHECK:STDOUT: %.loc8_38.3: ref %C = temporary %.loc8_38.1, %.loc8_38.2
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_38.3, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_38.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound.loc8: <bound method> = bound_method %.loc8_37.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call.loc8: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound.loc8(%.loc8_37.3)
// CHECK:STDOUT: %Cpp.ref.loc9_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, imports.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %Overload.ref: %C.Overload.cpp_overload_set.type = name_ref Overload, imports.%C.Overload.cpp_overload_set.value [concrete = constants.%C.Overload.cpp_overload_set.value]
@@ -2018,10 +2022,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %Overload__carbon_thunk.call: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl(%addr.loc9_45)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound.loc9: <bound method> = bound_method %.loc9_44.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call.loc9: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound.loc9(%.loc9_44.3)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_38.3, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_38.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound.loc8: <bound method> = bound_method %.loc8_37.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call.loc8: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound.loc8(%.loc8_37.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2304,6 +2304,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %PublicCall__carbon_thunk: %PublicCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type.3dd392.1: type = fn_type @Overload__carbon_thunk.1 [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.1c804c.1: %Overload__carbon_thunk.type.3dd392.1 = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall: type = class_type @ProtectedCall [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.type: type = cpp_overload_set_type @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.value: %ProtectedCall.ProtectedCall.cpp_overload_set.type = cpp_overload_set_value @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
@@ -2314,8 +2316,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %Overload__carbon_thunk.1c804c.2: %Overload__carbon_thunk.type.3dd392.2 = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.type: type = fn_type @ProtectedCall.cpp_destructor [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor: %ProtectedCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2380,6 +2380,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc11_40.5: ref %PublicCall = value_as_ref %.loc11_40.4
// CHECK:STDOUT: %addr.loc11_41: %ptr.d0a = addr_of %.loc11_40.5
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc11: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.c2f84f.1(%addr.loc11_41)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: %Overload.ref.loc12: %Public.Overload.cpp_overload_set.type = name_ref Overload, imports.%Public.Overload.cpp_overload_set.value [concrete = constants.%Public.Overload.cpp_overload_set.value]
// CHECK:STDOUT: %Cpp.ref.loc12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ProtectedCall.ref.loc12_17: type = name_ref ProtectedCall, imports.%ProtectedCall.decl [concrete = constants.%ProtectedCall]
@@ -2395,8 +2397,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc12: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.c2f84f.2(%addr.loc12_47)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc12_46.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc12_46.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2416,6 +2416,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %PublicCall__carbon_thunk: %PublicCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type.3dd392.1: type = fn_type @Overload__carbon_thunk.1 [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.1c804c.1: %Overload__carbon_thunk.type.3dd392.1 = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall: type = class_type @ProtectedCall [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.type: type = cpp_overload_set_type @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.value: %ProtectedCall.ProtectedCall.cpp_overload_set.type = cpp_overload_set_value @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
@@ -2426,8 +2428,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %Overload__carbon_thunk.1c804c.2: %Overload__carbon_thunk.type.3dd392.2 = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.type: type = fn_type @ProtectedCall.cpp_destructor [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor: %ProtectedCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2492,6 +2492,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc11_40.5: ref %PublicCall = value_as_ref %.loc11_40.4
// CHECK:STDOUT: %addr.loc11_41: %ptr.d0a = addr_of %.loc11_40.5
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc11: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.c2f84f.1(%addr.loc11_41)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: %Overload.ref.loc12: %Protected.Overload.cpp_overload_set.type = name_ref Overload, imports.%Protected.Overload.cpp_overload_set.value [concrete = constants.%Protected.Overload.cpp_overload_set.value]
// CHECK:STDOUT: %Cpp.ref.loc12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ProtectedCall.ref.loc12_17: type = name_ref ProtectedCall, imports.%ProtectedCall.decl [concrete = constants.%ProtectedCall]
@@ -2507,8 +2509,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc12: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.c2f84f.2(%addr.loc12_47)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc12_46.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc12_46.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -296,6 +296,10 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %HasQualifiers.ref_this: %HasQualifiers.ref_this.type = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.plain.type.99c640.2: type = fn_type @HasQualifiers.plain.2 [concrete]
// CHECK:STDOUT: %HasQualifiers.plain.cdd9ec.2: %HasQualifiers.plain.type.99c640.2 = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.type: type = fn_type @HasQualifiers.cpp_destructor [concrete]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor: %HasQualifiers.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.type.83af6e.1: type = fn_type @HasQualifiers.Op.1 [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.4dca31.1: %HasQualifiers.Op.type.83af6e.1 = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_ref_this.cpp_overload_set [concrete]
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete]
// CHECK:STDOUT: %ref_ref_this__carbon_thunk.type: type = fn_type @ref_ref_this__carbon_thunk [concrete]
@@ -307,16 +311,12 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %ptr.e71: type = ptr_type %const.ba8 [concrete]
// CHECK:STDOUT: %HasQualifiers__carbon_thunk.type: type = fn_type @HasQualifiers__carbon_thunk [concrete]
// CHECK:STDOUT: %HasQualifiers__carbon_thunk: %HasQualifiers__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.type.83af6e.1: type = fn_type @HasQualifiers.Op.1 [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.4dca31.1: %HasQualifiers.Op.type.83af6e.1 = struct_value () [concrete]
// CHECK:STDOUT: %custom_witness.d0d: <witness> = custom_witness (%HasQualifiers.Op.4dca31.1), @Copy [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.type.83af6e.2: type = fn_type @HasQualifiers.Op.2 [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.4dca31.2: %HasQualifiers.Op.type.83af6e.2 = struct_value () [concrete]
// CHECK:STDOUT: %custom_witness.d0d: <witness> = custom_witness (%HasQualifiers.Op.4dca31.2), @Copy [concrete]
// CHECK:STDOUT: %Copy.facet.11b: %Copy.type = facet_value %HasQualifiers, (%custom_witness.d0d) [concrete]
// CHECK:STDOUT: %Copy.WithSelf.Op.type.033: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.11b) [concrete]
// CHECK:STDOUT: %.703: type = fn_type_with_self_type %Copy.WithSelf.Op.type.033, %Copy.facet.11b [concrete]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.type: type = fn_type @HasQualifiers.cpp_destructor [concrete]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor: %HasQualifiers.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.type.83af6e.2: type = fn_type @HasQualifiers.Op.2 [concrete]
// CHECK:STDOUT: %HasQualifiers.Op.4dca31.2: %HasQualifiers.Op.type.83af6e.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -355,6 +355,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.decl: %HasQualifiers.cpp_destructor.type = fn_decl @HasQualifiers.cpp_destructor [concrete = constants.%HasQualifiers.cpp_destructor] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete = constants.%HasQualifiers.ref_ref_this.cpp_overload_set.value]
// CHECK:STDOUT: %ref_ref_this__carbon_thunk.decl: %ref_ref_this__carbon_thunk.type = fn_decl @ref_ref_this__carbon_thunk [concrete = constants.%ref_ref_this__carbon_thunk] {
// CHECK:STDOUT: <elided>
@@ -371,11 +376,6 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.decl: %HasQualifiers.cpp_destructor.type = fn_decl @HasQualifiers.cpp_destructor [concrete = constants.%HasQualifiers.cpp_destructor] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%v.param: %HasQualifiers, %p.param: %ptr.102) {
@@ -422,6 +422,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %bound_method.loc19: <bound method> = bound_method %.loc19_8.2, %plain.ref.loc19
// CHECK:STDOUT: %.loc19_8.3: %HasQualifiers = acquire_value %.loc19_8.2
// CHECK:STDOUT: %HasQualifiers.plain.call.loc19: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl.3d4ba8.2(%.loc19_8.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc19: <bound method> = bound_method %.loc19_8.2, constants.%HasQualifiers.Op.4dca31.1
// CHECK:STDOUT: %Op.ref.loc19: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc19: <bound method> = bound_method %.loc19_8.2, %Op.ref.loc19
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc19: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc19(%.loc19_8.2)
// CHECK:STDOUT: %Make.ref.loc20: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
// CHECK:STDOUT: %.loc20_8.1: ref %HasQualifiers = temporary_storage
// CHECK:STDOUT: %Make.call.loc20: init %HasQualifiers to %.loc20_8.1 = call %Make.ref.loc20()
@@ -430,6 +435,10 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %bound_method.loc20: <bound method> = bound_method %.loc20_8.2, %const_this.ref.loc20
// CHECK:STDOUT: %.loc20_8.3: %HasQualifiers = acquire_value %.loc20_8.2
// CHECK:STDOUT: %const_this__carbon_thunk.call.loc20: init %empty_tuple.type = call imports.%const_this__carbon_thunk.decl(%.loc20_8.3)
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc20: <bound method> = bound_method %.loc20_8.2, constants.%HasQualifiers.Op.4dca31.1
// CHECK:STDOUT: %Op.ref.loc20: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc20: <bound method> = bound_method %.loc20_8.2, %Op.ref.loc20
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc20: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc20(%.loc20_8.2)
// CHECK:STDOUT: %Make.ref.loc21: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
// CHECK:STDOUT: %.loc21_8.1: ref %HasQualifiers = temporary_storage
// CHECK:STDOUT: %Make.call.loc21: init %HasQualifiers to %.loc21_8.1 = call %Make.ref.loc21()
@@ -438,6 +447,10 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %bound_method.loc21: <bound method> = bound_method %.loc21_8.2, %const_ref_this.ref.loc21
// CHECK:STDOUT: %.loc21_8.3: %HasQualifiers = acquire_value %.loc21_8.2
// CHECK:STDOUT: %const_ref_this__carbon_thunk.call.loc21: init %empty_tuple.type = call imports.%const_ref_this__carbon_thunk.decl(%.loc21_8.3)
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc21: <bound method> = bound_method %.loc21_8.2, constants.%HasQualifiers.Op.4dca31.1
// CHECK:STDOUT: %Op.ref.loc21: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc21: <bound method> = bound_method %.loc21_8.2, %Op.ref.loc21
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc21: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc21(%.loc21_8.2)
// CHECK:STDOUT: %Make.ref.loc22: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
// CHECK:STDOUT: %.loc22_8.1: ref %HasQualifiers = temporary_storage
// CHECK:STDOUT: %Make.call.loc22: init %HasQualifiers to %.loc22_8.1 = call %Make.ref.loc22()
@@ -446,7 +459,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %bound_method.loc22_9: <bound method> = bound_method %.loc22_8.2, %ref_ref_this.ref
// CHECK:STDOUT: %.loc22_8.3: %HasQualifiers = acquire_value %.loc22_8.2
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %impl.elem0.loc22: %.703 = impl_witness_access constants.%custom_witness.d0d, element0 [concrete = constants.%HasQualifiers.Op.4dca31.1]
// CHECK:STDOUT: %impl.elem0.loc22: %.703 = impl_witness_access constants.%custom_witness.d0d, element0 [concrete = constants.%HasQualifiers.Op.4dca31.2]
// CHECK:STDOUT: %bound_method.loc22_8: <bound method> = bound_method %.loc22_8.3, %impl.elem0.loc22
// CHECK:STDOUT: %.loc22_8.4: ref %HasQualifiers = temporary_storage
// CHECK:STDOUT: %Op.ref.loc22_8.1: %HasQualifiers.HasQualifiers.type = name_ref Op, imports.%HasQualifiers.HasQualifiers.decl [concrete = constants.%HasQualifiers.HasQualifiers]
@@ -460,6 +473,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %.loc22_8.8: init %HasQualifiers to %self.var = mark_in_place_init %HasQualifiers__carbon_thunk.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %ref_ref_this__carbon_thunk.call: init %empty_tuple.type = call imports.%ref_ref_this__carbon_thunk.decl(%self.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc22: <bound method> = bound_method %.loc22_8.2, constants.%HasQualifiers.Op.4dca31.1
// CHECK:STDOUT: %Op.ref.loc22_8.2: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc22: <bound method> = bound_method %.loc22_8.2, %Op.ref.loc22_8.2
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc22: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc22(%.loc22_8.2)
// CHECK:STDOUT: %Make.ref.loc23: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
// CHECK:STDOUT: %.loc23_8.1: ref %HasQualifiers = temporary_storage
// CHECK:STDOUT: %Make.call.loc23: init %HasQualifiers to %.loc23_8.1 = call %Make.ref.loc23()
@@ -468,29 +486,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
// CHECK:STDOUT: %bound_method.loc23: <bound method> = bound_method %.loc23_8.2, %const_ref_ref_this.ref.loc23
// CHECK:STDOUT: %.loc23_8.3: %HasQualifiers = acquire_value %.loc23_8.2
// CHECK:STDOUT: %const_ref_ref_this__carbon_thunk.call.loc23: init %empty_tuple.type = call imports.%const_ref_ref_this__carbon_thunk.decl(%.loc23_8.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc23: <bound method> = bound_method %.loc23_8.2, constants.%HasQualifiers.Op.4dca31.2
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc23: <bound method> = bound_method %.loc23_8.2, constants.%HasQualifiers.Op.4dca31.1
// CHECK:STDOUT: %Op.ref.loc23: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc23: <bound method> = bound_method %.loc23_8.2, %Op.ref.loc23
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc23: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc23(%.loc23_8.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc22: <bound method> = bound_method %.loc22_8.2, constants.%HasQualifiers.Op.4dca31.2
// CHECK:STDOUT: %Op.ref.loc22_8.2: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc22: <bound method> = bound_method %.loc22_8.2, %Op.ref.loc22_8.2
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc22: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc22(%.loc22_8.2)
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc21: <bound method> = bound_method %.loc21_8.2, constants.%HasQualifiers.Op.4dca31.2
// CHECK:STDOUT: %Op.ref.loc21: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc21: <bound method> = bound_method %.loc21_8.2, %Op.ref.loc21
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc21: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc21(%.loc21_8.2)
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc20: <bound method> = bound_method %.loc20_8.2, constants.%HasQualifiers.Op.4dca31.2
// CHECK:STDOUT: %Op.ref.loc20: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc20: <bound method> = bound_method %.loc20_8.2, %Op.ref.loc20
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc20: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc20(%.loc20_8.2)
// CHECK:STDOUT: %HasQualifiers.Op.bound.loc19: <bound method> = bound_method %.loc19_8.2, constants.%HasQualifiers.Op.4dca31.2
// CHECK:STDOUT: %Op.ref.loc19: %HasQualifiers.cpp_destructor.type = name_ref Op, imports.%HasQualifiers.cpp_destructor.decl [concrete = constants.%HasQualifiers.cpp_destructor]
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.bound.loc19: <bound method> = bound_method %.loc19_8.2, %Op.ref.loc19
// CHECK:STDOUT: %HasQualifiers.cpp_destructor.call.loc19: init %empty_tuple.type = call %HasQualifiers.cpp_destructor.bound.loc19(%.loc19_8.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_object_param_qualifiers_overloaded.carbon