mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 19:01:05 +01:00
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:
@@ -156,6 +156,8 @@ fn F() {
|
||||
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.b02: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.cd0, %ImplicitAs.facet.4ba) [concrete]
|
||||
// CHECK:STDOUT: %.0a4: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b02, %ImplicitAs.facet.4ba [concrete]
|
||||
// CHECK:STDOUT: %U.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.as_type.as.ImplicitAs.impl.Convert.968, @U.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.e9e, %OptionalAs.facet) [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.4: type = fn_type @Destroy.Op.loc11_18.3 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.4: %Destroy.Op.type.1d8f74.4 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t: type = class_type @NullptrT [concrete]
|
||||
// CHECK:STDOUT: %uninit: %Cpp.nullptr_t = uninitialized_value [concrete]
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.type.e28: type = fn_type @Cpp.nullptr_t.as.ImplicitAs.impl.Convert, @Cpp.nullptr_t.as.ImplicitAs.impl(%T.67d) [symbolic]
|
||||
@@ -169,8 +171,6 @@ fn F() {
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.0b4 [concrete]
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.0b4, @Cpp.nullptr_t.as.ImplicitAs.impl.Convert(%i32) [concrete]
|
||||
// CHECK:STDOUT: %bound_method.480: <bound method> = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.5: type = fn_type @Destroy.Op.loc13_21.3 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.5: %Destroy.Op.type.1d8f74.5 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.8: type = fn_type @Destroy.Op.loc10_3.3 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.8: %Destroy.Op.type.1d8f74.8 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
@@ -259,6 +259,8 @@ fn F() {
|
||||
// CHECK:STDOUT: %.loc11_18.3: ref %Optional.cd0 = temporary %.loc11_18.2, %.loc11_18.1
|
||||
// CHECK:STDOUT: %.loc11_18.4: %Optional.cd0 = acquire_value %.loc11_18.3
|
||||
// CHECK:STDOUT: %TakesArray.call.loc11: init %empty_tuple.type = call imports.%TakesArray.decl(%.loc11_18.4)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_18.3, constants.%Destroy.Op.1a2547.4
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_18.3)
|
||||
// CHECK:STDOUT: %Cpp.ref.loc13_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %TakesArray.ref.loc13: %TakesArray.cpp_overload_set.type = name_ref TakesArray, imports.%TakesArray.cpp_overload_set.value [concrete = constants.%TakesArray.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc13_18: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
@@ -274,26 +276,24 @@ fn F() {
|
||||
// CHECK:STDOUT: %.loc13_21.3: ref %Optional.cd0 = temporary %.loc13_21.2, %.loc13_21.1
|
||||
// CHECK:STDOUT: %.loc13_21.4: %Optional.cd0 = acquire_value %.loc13_21.3
|
||||
// CHECK:STDOUT: %TakesArray.call.loc13: init %empty_tuple.type = call imports.%TakesArray.decl(%.loc13_21.4)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_21.3, constants.%Destroy.Op.1a2547.5
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_21.3, constants.%Destroy.Op.1a2547.4
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_21.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_18.3, constants.%Destroy.Op.1a2547.5
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_18.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc10: <bound method> = bound_method %n.var, constants.%Destroy.Op.1a2547.8
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%n.var)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_21.1(%self.param: ref %.0f8) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_18.1(%self.param: ref %.0f8) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_21.2(%self.param: ref %MaybeUnformed.b84) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_18.2(%self.param: ref %MaybeUnformed.b84) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_21.3(%self.param: ref %Optional.cd0) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_18.3(%self.param: ref %Optional.cd0) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -188,6 +188,8 @@ fn Call() {
|
||||
// CHECK:STDOUT: %bound_method.f8c: <bound method> = bound_method %.414, %X.B.cpp_overload_set.value [concrete]
|
||||
// CHECK:STDOUT: %X.B.type: type = fn_type @X.B [concrete]
|
||||
// CHECK:STDOUT: %X.B: %X.B.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.type: type = cpp_overload_set_type @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.C.type: type = fn_type @X.C [concrete]
|
||||
@@ -198,8 +200,6 @@ fn Call() {
|
||||
// CHECK:STDOUT: %ptr.ca1: type = ptr_type %X [concrete]
|
||||
// CHECK:STDOUT: %D__carbon_thunk.type: type = fn_type @D__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %D__carbon_thunk: %D__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -230,6 +230,11 @@ fn Call() {
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.C.decl: %X.C.type = fn_decl @X.C [concrete = constants.%X.C] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -242,11 +247,6 @@ fn Call() {
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Call() {
|
||||
@@ -355,6 +355,8 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc10_22.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_22 [concrete = constants.%int_2.295]
|
||||
// CHECK:STDOUT: %.loc10_22.2: %i32 = converted %int_2.loc10, %.loc10_22.1 [concrete = constants.%int_2.295]
|
||||
// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%.loc10_7.3, %.loc10_19.2, %.loc10_22.2)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %Op.ref.loc10: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc11: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %X.ref.loc11: type = name_ref X, imports.%X.decl [concrete = constants.%X]
|
||||
// CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
@@ -404,9 +406,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc12_7.4: ref %X = value_as_ref %.loc12_7.3
|
||||
// CHECK:STDOUT: %addr: %ptr.ca1 = addr_of %.loc12_7.4
|
||||
// CHECK:STDOUT: %D__carbon_thunk.call: init %empty_tuple.type = call imports.%D__carbon_thunk.decl(%addr, %.loc12_19.2, %.loc12_22.2)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %Op.ref.loc12: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Op.ref.loc10: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -479,6 +479,18 @@ fn Call() {
|
||||
// CHECK:STDOUT: %this.patt: %pattern_type.fa7 = at_binding_pattern this, %this.param_patt [concrete]
|
||||
// CHECK:STDOUT: %B__carbon_thunk.type: type = fn_type @B__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %B__carbon_thunk: %B__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete]
|
||||
// CHECK:STDOUT: %Self.0e7: %Destroy.type = symbolic_binding Self, 0 [symbolic]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.d3e: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Self.0e7) [symbolic]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.42b: %Destroy.WithSelf.Op.type.d3e = struct_value () [symbolic]
|
||||
// CHECK:STDOUT: %self.param_patt.a14: %pattern_type.fa7 = ref_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %self.patt.37b: %pattern_type.fa7 = at_binding_pattern self, %self.param_patt.a14 [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.c5a: <witness> = custom_witness (), @Destroy [concrete]
|
||||
// CHECK:STDOUT: %Destroy.facet.761: %Destroy.type = facet_value %X, (%custom_witness.c5a) [concrete]
|
||||
// CHECK:STDOUT: %X.Op.type: type = fn_type @X.Op [concrete]
|
||||
// CHECK:STDOUT: %X.Op: %X.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.type: type = cpp_overload_set_type @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete]
|
||||
@@ -492,18 +504,6 @@ fn Call() {
|
||||
// CHECK:STDOUT: %_.patt: %pattern_type.cf1 = at_binding_pattern _, %_.param_patt [concrete]
|
||||
// CHECK:STDOUT: %D__carbon_thunk.type: type = fn_type @D__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %D__carbon_thunk: %D__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete]
|
||||
// CHECK:STDOUT: %Self.0e7: %Destroy.type = symbolic_binding Self, 0 [symbolic]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.d3e: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Self.0e7) [symbolic]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.42b: %Destroy.WithSelf.Op.type.d3e = struct_value () [symbolic]
|
||||
// CHECK:STDOUT: %self.param_patt.a14: %pattern_type.fa7 = ref_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %self.patt.37b: %pattern_type.fa7 = at_binding_pattern self, %self.param_patt.a14 [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.c5a: <witness> = custom_witness (), @Destroy [concrete]
|
||||
// CHECK:STDOUT: %Destroy.facet.761: %Destroy.type = facet_value %X, (%custom_witness.c5a) [concrete]
|
||||
// CHECK:STDOUT: %X.Op.type: type = fn_type @X.Op [concrete]
|
||||
// CHECK:STDOUT: %X.Op: %X.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -623,6 +623,15 @@ fn Call() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %a.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.d3e = fn_decl @Destroy.WithSelf.Op [symbolic = @Destroy.WithSelf.%Destroy.WithSelf.Op (constants.%Destroy.WithSelf.Op.42b)] {} {}
|
||||
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
|
||||
// CHECK:STDOUT: %self.param_patt: %pattern_type.fa7 = ref_param_pattern [concrete = constants.%self.param_patt.a14]
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.fa7 = at_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.37b]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
|
||||
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] {
|
||||
// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%a.param_patt]
|
||||
@@ -653,15 +662,6 @@ fn Call() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %a.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.d3e = fn_decl @Destroy.WithSelf.Op [symbolic = @Destroy.WithSelf.%Destroy.WithSelf.Op (constants.%Destroy.WithSelf.Op.42b)] {} {}
|
||||
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
|
||||
// CHECK:STDOUT: %self.param_patt: %pattern_type.fa7 = ref_param_pattern [concrete = constants.%self.param_patt.a14]
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.fa7 = at_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.37b]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
|
||||
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -782,6 +782,14 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc11_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11 [concrete = constants.%int_1.0c6]
|
||||
// CHECK:STDOUT: %.loc11_19.2: %i32 = converted %int_1.loc11, %.loc11_19.1 [concrete = constants.%int_1.0c6]
|
||||
// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%.loc11_7.3, %.loc11_19.2)
|
||||
// CHECK:STDOUT: %X.Op.decl: %X.Op.type = fn_decl @X.Op [concrete = constants.%X.Op] {
|
||||
// CHECK:STDOUT: %.1: %pattern_type.fa7 = specific_constant constants.%self.param_patt.a14, @Destroy.WithSelf.Op(constants.%Destroy.facet.761) [concrete = constants.%self.param_patt.a14]
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.fa7 = at_binding_pattern self, %.1 [concrete = constants.%self.patt.37b]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
|
||||
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Op.ref.loc11: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %X.ref.loc12: type = name_ref X, imports.%X.decl [concrete = constants.%X]
|
||||
// CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
@@ -815,15 +823,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc13_7.4: ref %X = value_as_ref %.loc13_7.3
|
||||
// CHECK:STDOUT: %addr: %ptr.ca1 = addr_of %.loc13_7.4
|
||||
// CHECK:STDOUT: %D__carbon_thunk.call: init %empty_tuple.type = call imports.%D__carbon_thunk.decl(%addr, %.loc13_19.2)
|
||||
// CHECK:STDOUT: %X.Op.decl: %X.Op.type = fn_decl @X.Op [concrete = constants.%X.Op] {
|
||||
// CHECK:STDOUT: %.1: %pattern_type.fa7 = specific_constant constants.%self.param_patt.a14, @Destroy.WithSelf.Op(constants.%Destroy.facet.761) [concrete = constants.%self.param_patt.a14]
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.fa7 = at_binding_pattern self, %.1 [concrete = constants.%self.patt.37b]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
|
||||
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Op.ref.loc13: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Op.ref.loc11: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -843,14 +843,6 @@ fn Call() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: %X, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.C(%a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @C__carbon_thunk(%a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.D(%self.param: %X, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @D__carbon_thunk(%_.param: %ptr.ca1, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.cpp_destructor(%self.param: ref %X) = "no_op";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.Op(%self.param: ref %X) [thunk imports.%X.cpp_destructor.decl for imports.%Destroy.WithSelf.Op.decl, @Destroy.WithSelf.Op(constants.%Destroy.facet.761)] {
|
||||
@@ -861,6 +853,14 @@ fn Call() {
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.C(%a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @C__carbon_thunk(%a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.D(%self.param: %X, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @D__carbon_thunk(%_.param: %ptr.ca1, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_call_too_few_args.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
@@ -877,13 +877,13 @@ fn Call() {
|
||||
// CHECK:STDOUT: %X.B.cpp_overload_set.type: type = cpp_overload_set_type @X.B.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %bound_method.f8c: <bound method> = bound_method %.414, %X.B.cpp_overload_set.value [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.type: type = cpp_overload_set_type @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.D.cpp_overload_set.type: type = cpp_overload_set_type @X.D.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %X.D.cpp_overload_set.value: %X.D.cpp_overload_set.type = cpp_overload_set_value @X.D.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %bound_method.9a8: <bound method> = bound_method %.414, %X.D.cpp_overload_set.value [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -897,13 +897,13 @@ fn Call() {
|
||||
// CHECK:STDOUT: %GlobalReturnInt.cpp_overload_set.value: %GlobalReturnInt.cpp_overload_set.type = cpp_overload_set_value @GlobalReturnInt.cpp_overload_set [concrete = constants.%GlobalReturnInt.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {}
|
||||
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete = constants.%X.B.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.D.cpp_overload_set.value: %X.D.cpp_overload_set.type = cpp_overload_set_value @X.D.cpp_overload_set [concrete = constants.%X.D.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %X.D.cpp_overload_set.value: %X.D.cpp_overload_set.type = cpp_overload_set_value @X.D.cpp_overload_set [concrete = constants.%X.D.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Call() {
|
||||
@@ -927,6 +927,8 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc56_7.2: ref %X = temporary %.loc56_5.2, %.loc56_7.1 [concrete = constants.%.414]
|
||||
// CHECK:STDOUT: %B.ref: %X.B.cpp_overload_set.type = name_ref B, imports.%X.B.cpp_overload_set.value [concrete = constants.%X.B.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc56: <bound method> = bound_method %.loc56_7.2, %B.ref [concrete = constants.%bound_method.f8c]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %Op.ref.loc56: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc66: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %X.ref.loc66: type = name_ref X, imports.%X.decl [concrete = constants.%X]
|
||||
// CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
@@ -939,9 +941,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %.loc76_7.2: ref %X = temporary %.loc76_5.2, %.loc76_7.1 [concrete = constants.%.414]
|
||||
// CHECK:STDOUT: %D.ref: %X.D.cpp_overload_set.type = name_ref D, imports.%X.D.cpp_overload_set.value [concrete = constants.%X.D.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc76: <bound method> = bound_method %.loc76_7.2, %D.ref [concrete = constants.%bound_method.9a8]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %Op.ref.loc76: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: %Op.ref.loc56: %X.cpp_destructor.type = name_ref Op, imports.%X.cpp_destructor.decl [concrete = constants.%X.cpp_destructor]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -1993,14 +1993,14 @@ fn F() {
|
||||
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.243: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.0c8, %ImplicitAs.facet.424) [concrete]
|
||||
// CHECK:STDOUT: %.954: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.243, %ImplicitAs.facet.424 [concrete]
|
||||
// CHECK:STDOUT: %U.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.as_type.as.ImplicitAs.impl.Convert.593, @U.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.0d5, %OptionalAs.facet) [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.4: type = fn_type @Destroy.Op.loc11_14.3 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.4: %Destroy.Op.type.1d8f74.4 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.9f1 = value_binding_pattern a [concrete]
|
||||
// CHECK:STDOUT: %Indirect.cpp_overload_set.type: type = cpp_overload_set_type @Indirect.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %Indirect.cpp_overload_set.value: %Indirect.cpp_overload_set.type = cpp_overload_set_value @Indirect.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %Indirect__carbon_thunk.type: type = fn_type @Indirect__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %Indirect__carbon_thunk: %Indirect__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.a94: ref %S = temporary invalid, %S.val [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.4: type = fn_type @Destroy.Op.loc13_65.3 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.4: %Destroy.Op.type.1d8f74.4 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %S.cpp_destructor.type: type = fn_type @S.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %S.cpp_destructor: %S.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
@@ -2048,6 +2048,7 @@ fn F() {
|
||||
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.cf7 = impl_witness_table (%Core.import_ref.eb9), @U.as_type.as.ImplicitAs.impl.167 [concrete]
|
||||
// CHECK:STDOUT: %Core.import_ref.017d8: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
|
||||
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete]
|
||||
// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
|
||||
// CHECK:STDOUT: %Indirect.cpp_overload_set.value: %Indirect.cpp_overload_set.type = cpp_overload_set_value @Indirect.cpp_overload_set [concrete = constants.%Indirect.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %Indirect__carbon_thunk.decl: %Indirect__carbon_thunk.type = fn_decl @Indirect__carbon_thunk [concrete = constants.%Indirect__carbon_thunk] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -2057,7 +2058,6 @@ fn F() {
|
||||
// CHECK:STDOUT: %Optional: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet.0d5) [concrete = constants.%Optional.0c8]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
@@ -2090,6 +2090,8 @@ fn F() {
|
||||
// CHECK:STDOUT: %.loc11_14.3: ref %Optional.0c8 = temporary %.loc11_14.2, %.loc11_14.1
|
||||
// CHECK:STDOUT: %.loc11_14.4: %Optional.0c8 = acquire_value %.loc11_14.3
|
||||
// CHECK:STDOUT: %Direct.call: init %Optional.0c8 = call imports.%Direct.decl(%.loc11_14.4)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_14.3, constants.%Destroy.Op.1a2547.4
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_14.3)
|
||||
// CHECK:STDOUT: %Cpp.ref.loc13_41: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %Indirect.ref: %Indirect.cpp_overload_set.type = name_ref Indirect, imports.%Indirect.cpp_overload_set.value [concrete = constants.%Indirect.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %.loc13_55.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
@@ -2122,24 +2124,22 @@ fn F() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_65.2, constants.%Destroy.Op.1a2547.4
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_65.2)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_14.3, constants.%Destroy.Op.1a2547.4
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_14.3)
|
||||
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
|
||||
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_65.1(%self.param: ref %.08a0) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_14.1(%self.param: ref %.08a0) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_65.2(%self.param: ref %MaybeUnformed.9f2) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_14.2(%self.param: ref %MaybeUnformed.9f2) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc13_65.3(%self.param: ref %Optional.0c8) {
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc11_14.3(%self.param: ref %Optional.0c8) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -122,12 +122,12 @@ fn Var() {
|
||||
// CHECK:STDOUT: %foo1__carbon_thunk.type: type = fn_type @foo1__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %foo1__carbon_thunk: %foo1__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %i16.builtin: type = int_type signed, %int_16 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.2: type = fn_type @Destroy.Op.loc11_22.2 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.2: %Destroy.Op.type.1d8f74.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %foo2.cpp_overload_set.type: type = cpp_overload_set_type @foo2.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %foo2.cpp_overload_set.value: %foo2.cpp_overload_set.type = cpp_overload_set_value @foo2.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %foo2.type: type = fn_type @foo2 [concrete]
|
||||
// CHECK:STDOUT: %foo2: %foo2.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.1d8f74.2: type = fn_type @Destroy.Op.loc11_22.2 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.1a2547.2: %Destroy.Op.type.1d8f74.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -162,6 +162,8 @@ fn Var() {
|
||||
// CHECK:STDOUT: %.loc11_22.3: ref %i16 = temporary %.loc11_22.1, %.loc11_22.2
|
||||
// CHECK:STDOUT: %.loc11_22.4: %i16 = acquire_value %.loc11_22.3
|
||||
// CHECK:STDOUT: %IngestI16.call: init %empty_tuple.type = call %IngestI16.ref(%.loc11_22.4)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc11_22.3, constants.%Destroy.Op.1a2547.2
|
||||
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc11_22.3)
|
||||
// CHECK:STDOUT: %IngestI32.ref: %IngestI32.type = name_ref IngestI32, file.%IngestI32.decl [concrete = constants.%IngestI32]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo2.ref: %foo2.cpp_overload_set.type = name_ref foo2, imports.%foo2.cpp_overload_set.value [concrete = constants.%foo2.cpp_overload_set.value]
|
||||
@@ -169,8 +171,6 @@ fn Var() {
|
||||
// CHECK:STDOUT: %.loc12_22.1: %i32 = value_of_initializer %foo2.call
|
||||
// CHECK:STDOUT: %.loc12_22.2: %i32 = converted %foo2.call, %.loc12_22.1
|
||||
// CHECK:STDOUT: %IngestI32.call: init %empty_tuple.type = call %IngestI32.ref(%.loc12_22.2)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc11_22.3, constants.%Destroy.Op.1a2547.2
|
||||
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc11_22.3)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user