From 95eb7b16bb0cef0f3857fe17aba8d2b8fe11a6eb Mon Sep 17 00:00:00 2001 From: Geoff Romer Date: Fri, 16 Jan 2026 10:08:42 -0800 Subject: [PATCH] Expose C++ reference returns as Carbon reference returns (#6618) Co-authored-by: Carbon Infra Bot --- toolchain/check/context.h | 4 +- toolchain/check/cpp/import.cpp | 90 ++++++---- .../interop/cpp/function/operators.carbon | 26 ++- .../interop/cpp/function/reference.carbon | 130 ++++---------- .../testdata/interop/cpp/reference.carbon | 170 ++++++------------ 5 files changed, 162 insertions(+), 258 deletions(-) diff --git a/toolchain/check/context.h b/toolchain/check/context.h index bd9857a0a71c..b4f42ac3af92 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -255,7 +255,9 @@ class Context { // Data about a form expression. struct FormExpr { - // The inst ID of the form expression itself. + // The inst ID of the form expression itself. This is always a form inst, + // such as InitForm or RefForm. + // TODO: Consider creating an AnyForm inst category to refer to those insts. SemIR::InstId form_inst_id; // The inst ID of the form expression's type component. SemIR::TypeInstId type_component_id; diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index f4a73a81ebf2..0f2fa1343c85 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -1195,9 +1195,26 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, // are treated as returning a class instance. // TODO: Support more return types. static auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id, - clang::FunctionDecl* clang_decl) -> TypeExpr { + clang::FunctionDecl* clang_decl) + -> Context::FormExpr { + auto make_init_form = [&](SemIR::TypeInstId type_component_inst_id) { + SemIR::InitForm inst = { + .type_id = SemIR::FormType::TypeId, + .type_component_inst_id = type_component_inst_id, + .index = context.full_pattern_stack().NextCallParamIndex()}; + return context.constant_values().GetInstId(TryEvalInst(context, inst)); + }; + auto make_ref_form = [&](SemIR::TypeInstId type_component_inst_id) { + SemIR::RefForm inst = {.type_id = SemIR::FormType::TypeId, + .type_component_inst_id = type_component_inst_id}; + return context.constant_values().GetInstId(TryEvalInst(context, inst)); + }; clang::QualType orig_ret_type = clang_decl->getReturnType(); if (!orig_ret_type->isVoidType()) { + bool is_reference = orig_ret_type->isReferenceType(); + if (is_reference) { + orig_ret_type = orig_ret_type->getPointeeType(); + } // TODO: We should eventually map reference returns to non-pointer types // here. We should return by `ref` for `T&` return types once `ref` return // is implemented. @@ -1205,24 +1222,33 @@ static auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id, if (!orig_type_inst_id.has_value()) { context.TODO(loc_id, llvm::formatv("Unsupported: return type: {0}", orig_ret_type.getAsString())); - return {.inst_id = SemIR::ErrorInst::TypeInstId, + return {.form_inst_id = SemIR::ErrorInst::InstId, + .type_component_id = SemIR::ErrorInst::TypeInstId, .type_id = SemIR::ErrorInst::TypeId}; } + Context::FormExpr result = { + .form_inst_id = is_reference ? make_ref_form(orig_type_inst_id) + : make_init_form(orig_type_inst_id), + .type_component_id = orig_type_inst_id, + .type_id = type_id}; - return {orig_type_inst_id, type_id}; + return result; } auto* ctor = dyn_cast(clang_decl); if (!ctor) { // void. - return TypeExpr::None; + return {.form_inst_id = SemIR::InstId::None, + .type_component_id = SemIR::TypeInstId::None, + .type_id = SemIR::TypeId::None}; } // TODO: Make this a `PartialType`. SemIR::TypeInstId record_type_inst_id = context.types().GetAsTypeInstId( LookupClangDeclInstId(context, SemIR::ClangDeclKey(ctor->getParent()))); return { - .inst_id = record_type_inst_id, + .form_inst_id = make_init_form(record_type_inst_id), + .type_component_id = record_type_inst_id, .type_id = context.types().GetTypeIdForTypeInstId(record_type_inst_id)}; } @@ -1240,16 +1266,17 @@ struct ReturnInfo { // Constructors are treated as returning a class instance. static auto GetReturnInfo(Context& context, SemIR::LocId loc_id, clang::FunctionDecl* clang_decl) -> ReturnInfo { - auto [type_inst_id, type_id] = GetReturnTypeExpr(context, loc_id, clang_decl); - if (!type_inst_id.has_value()) { + auto [form_inst_id, type_inst_id, type_id] = + GetReturnTypeExpr(context, loc_id, clang_decl); + if (!form_inst_id.has_value()) { // void. - return {.return_type_inst_id = type_inst_id, + return {.return_type_inst_id = SemIR::TypeInstId::None, .return_form_inst_id = SemIR::InstId::None, .return_patterns_id = SemIR::InstBlockId::None}; } - if (type_inst_id == SemIR::ErrorInst::TypeInstId) { - return {.return_type_inst_id = type_inst_id, - .return_form_inst_id = SemIR::InstId::None, + if (form_inst_id == SemIR::ErrorInst::InstId) { + return {.return_type_inst_id = SemIR::ErrorInst::TypeInstId, + .return_form_inst_id = SemIR::ErrorInst::InstId, .return_patterns_id = SemIR::InstBlockId::None}; } auto pattern_type_id = GetPatternType(context, type_id); @@ -1264,30 +1291,25 @@ static auto GetReturnInfo(Context& context, SemIR::LocId loc_id, } SemIR::ImportIRInstId return_type_import_ir_inst_id = AddImportIRInst(context.sem_ir(), return_type_loc); - SemIR::InstId return_slot_pattern_id = AddPatternInst( - context, MakeImportedLocIdAndInst( - context, return_type_import_ir_inst_id, - SemIR::ReturnSlotPattern({.type_id = pattern_type_id, - .type_inst_id = type_inst_id}))); - auto return_index = context.full_pattern_stack().NextCallParamIndex(); - SemIR::InstId param_pattern_id = AddPatternInst( - context, - MakeImportedLocIdAndInst( - context, return_type_import_ir_inst_id, - SemIR::OutParamPattern({.type_id = pattern_type_id, - .subpattern_id = return_slot_pattern_id, - .index = return_index}))); - auto return_patterns_id = context.inst_blocks().Add({param_pattern_id}); - - // For consistency with how C++ import handles types, we use TryEvalInst to - // directly create a constant rather than adding it to insts() first. - auto return_form_const_id = TryEvalInst( - context, SemIR::InitForm{.type_id = SemIR::FormType::TypeId, - .type_component_inst_id = type_inst_id, - .index = return_index}); + auto return_patterns_id = SemIR::InstBlockId::Empty; + if (auto init_form = + context.insts().TryGetAs(form_inst_id)) { + SemIR::InstId return_slot_pattern_id = AddPatternInst( + context, MakeImportedLocIdAndInst( + context, return_type_import_ir_inst_id, + SemIR::ReturnSlotPattern({.type_id = pattern_type_id, + .type_inst_id = type_inst_id}))); + auto param_pattern_id = AddPatternInst( + context, + MakeImportedLocIdAndInst( + context, return_type_import_ir_inst_id, + SemIR::OutParamPattern({.type_id = pattern_type_id, + .subpattern_id = return_slot_pattern_id, + .index = init_form->index}))); + return_patterns_id = context.inst_blocks().Add({param_pattern_id}); + } return {.return_type_inst_id = type_inst_id, - .return_form_inst_id = - context.constant_values().GetInstId(return_form_const_id), + .return_form_inst_id = form_inst_id, .return_patterns_id = return_patterns_id}; } diff --git a/toolchain/check/testdata/interop/cpp/function/operators.carbon b/toolchain/check/testdata/interop/cpp/function/operators.carbon index 0af8ab32348a..7f422f445bef 100644 --- a/toolchain/check/testdata/interop/cpp/function/operators.carbon +++ b/toolchain/check/testdata/interop/cpp/function/operators.carbon @@ -1081,7 +1081,6 @@ fn F() { // CHECK:STDOUT: %ptr.d9e: 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: %const: type = const_type %ptr.d9e [concrete] // CHECK:STDOUT: %cpp_operator.type.1ea478.1: type = fn_type @cpp_operator.1 [concrete] // CHECK:STDOUT: %cpp_operator.0a3797.1: %cpp_operator.type.1ea478.1 = struct_value () [concrete] // CHECK:STDOUT: %cpp_operator.type.1ea478.2: type = fn_type @cpp_operator.2 [concrete] @@ -1149,9 +1148,9 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %c: ref %C = ref_binding c, %c.var // CHECK:STDOUT: %c.ref.loc11: ref %C = name_ref c, %c -// CHECK:STDOUT: %cpp_operator.call.loc11: init %const = call imports.%cpp_operator.decl.4206c9.1(%c.ref.loc11) +// CHECK:STDOUT: %cpp_operator.call.loc11: ref %C = call imports.%cpp_operator.decl.4206c9.1(%c.ref.loc11) // CHECK:STDOUT: %c.ref.loc12: ref %C = name_ref c, %c -// CHECK:STDOUT: %cpp_operator.call.loc12: init %const = call imports.%cpp_operator.decl.4206c9.2(%c.ref.loc12) +// CHECK:STDOUT: %cpp_operator.call.loc12: ref %C = call imports.%cpp_operator.decl.4206c9.2(%c.ref.loc12) // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %minus.patt: %pattern_type.217 = value_binding_pattern minus [concrete] // CHECK:STDOUT: } @@ -1252,7 +1251,6 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005: = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete] // CHECK:STDOUT: %bound_method.e9d: = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %int_5.0f6: %i32 = int_value 5 [concrete] -// CHECK:STDOUT: %const.7c5: type = const_type %ptr.d9e [concrete] // CHECK:STDOUT: %operator_PlusEqual__carbon_thunk.type: type = fn_type @operator_PlusEqual__carbon_thunk [concrete] // CHECK:STDOUT: %operator_PlusEqual__carbon_thunk: %operator_PlusEqual__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: %operator_MinusEqual__carbon_thunk.type: type = fn_type @operator_MinusEqual__carbon_thunk [concrete] @@ -1726,49 +1724,49 @@ fn F() { // CHECK:STDOUT: %.loc26_9.1: %C = acquire_value %c2.ref.loc26 // CHECK:STDOUT: %.loc26_9.2: ref %C = value_as_ref %.loc26_9.1 // CHECK:STDOUT: %addr.loc26: %ptr.d9e = addr_of %.loc26_9.2 -// CHECK:STDOUT: %operator_PlusEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_PlusEqual__carbon_thunk.decl(%c1.ref.loc26, %addr.loc26) +// CHECK:STDOUT: %operator_PlusEqual__carbon_thunk.call: ref %C = call imports.%operator_PlusEqual__carbon_thunk.decl(%c1.ref.loc26, %addr.loc26) // CHECK:STDOUT: %c1.ref.loc27: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc27: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc27_9.1: %C = acquire_value %c2.ref.loc27 // CHECK:STDOUT: %.loc27_9.2: ref %C = value_as_ref %.loc27_9.1 // CHECK:STDOUT: %addr.loc27: %ptr.d9e = addr_of %.loc27_9.2 -// CHECK:STDOUT: %operator_MinusEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_MinusEqual__carbon_thunk.decl(%c1.ref.loc27, %addr.loc27) +// CHECK:STDOUT: %operator_MinusEqual__carbon_thunk.call: ref %C = call imports.%operator_MinusEqual__carbon_thunk.decl(%c1.ref.loc27, %addr.loc27) // CHECK:STDOUT: %c1.ref.loc28: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc28: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc28_9.1: %C = acquire_value %c2.ref.loc28 // CHECK:STDOUT: %.loc28_9.2: ref %C = value_as_ref %.loc28_9.1 // CHECK:STDOUT: %addr.loc28: %ptr.d9e = addr_of %.loc28_9.2 -// CHECK:STDOUT: %operator_StarEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_StarEqual__carbon_thunk.decl(%c1.ref.loc28, %addr.loc28) +// CHECK:STDOUT: %operator_StarEqual__carbon_thunk.call: ref %C = call imports.%operator_StarEqual__carbon_thunk.decl(%c1.ref.loc28, %addr.loc28) // CHECK:STDOUT: %c1.ref.loc29: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc29: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc29_9.1: %C = acquire_value %c2.ref.loc29 // CHECK:STDOUT: %.loc29_9.2: ref %C = value_as_ref %.loc29_9.1 // CHECK:STDOUT: %addr.loc29: %ptr.d9e = addr_of %.loc29_9.2 -// CHECK:STDOUT: %operator_SlashEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_SlashEqual__carbon_thunk.decl(%c1.ref.loc29, %addr.loc29) +// CHECK:STDOUT: %operator_SlashEqual__carbon_thunk.call: ref %C = call imports.%operator_SlashEqual__carbon_thunk.decl(%c1.ref.loc29, %addr.loc29) // CHECK:STDOUT: %c1.ref.loc30: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc30: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc30_9.1: %C = acquire_value %c2.ref.loc30 // CHECK:STDOUT: %.loc30_9.2: ref %C = value_as_ref %.loc30_9.1 // CHECK:STDOUT: %addr.loc30: %ptr.d9e = addr_of %.loc30_9.2 -// CHECK:STDOUT: %operator_PercentEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_PercentEqual__carbon_thunk.decl(%c1.ref.loc30, %addr.loc30) +// CHECK:STDOUT: %operator_PercentEqual__carbon_thunk.call: ref %C = call imports.%operator_PercentEqual__carbon_thunk.decl(%c1.ref.loc30, %addr.loc30) // CHECK:STDOUT: %c1.ref.loc33: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc33: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc33_9.1: %C = acquire_value %c2.ref.loc33 // CHECK:STDOUT: %.loc33_9.2: ref %C = value_as_ref %.loc33_9.1 // CHECK:STDOUT: %addr.loc33: %ptr.d9e = addr_of %.loc33_9.2 -// CHECK:STDOUT: %operator_AmpEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_AmpEqual__carbon_thunk.decl(%c1.ref.loc33, %addr.loc33) +// CHECK:STDOUT: %operator_AmpEqual__carbon_thunk.call: ref %C = call imports.%operator_AmpEqual__carbon_thunk.decl(%c1.ref.loc33, %addr.loc33) // CHECK:STDOUT: %c1.ref.loc34: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc34: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc34_9.1: %C = acquire_value %c2.ref.loc34 // CHECK:STDOUT: %.loc34_9.2: ref %C = value_as_ref %.loc34_9.1 // CHECK:STDOUT: %addr.loc34: %ptr.d9e = addr_of %.loc34_9.2 -// CHECK:STDOUT: %operator_PipeEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_PipeEqual__carbon_thunk.decl(%c1.ref.loc34, %addr.loc34) +// CHECK:STDOUT: %operator_PipeEqual__carbon_thunk.call: ref %C = call imports.%operator_PipeEqual__carbon_thunk.decl(%c1.ref.loc34, %addr.loc34) // CHECK:STDOUT: %c1.ref.loc35: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %c2.ref.loc35: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %.loc35_9.1: %C = acquire_value %c2.ref.loc35 // CHECK:STDOUT: %.loc35_9.2: ref %C = value_as_ref %.loc35_9.1 // CHECK:STDOUT: %addr.loc35: %ptr.d9e = addr_of %.loc35_9.2 -// CHECK:STDOUT: %operator_CaretEqual__carbon_thunk.call: init %const.7c5 = call imports.%operator_CaretEqual__carbon_thunk.decl(%c1.ref.loc35, %addr.loc35) +// CHECK:STDOUT: %operator_CaretEqual__carbon_thunk.call: ref %C = call imports.%operator_CaretEqual__carbon_thunk.decl(%c1.ref.loc35, %addr.loc35) // CHECK:STDOUT: %c1.ref.loc36: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %int_3.loc36: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] // CHECK:STDOUT: %impl.elem0.loc36: %.863 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5] @@ -1778,7 +1776,7 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc36: init %i32 = call %bound_method.loc36_10.2(%int_3.loc36) [concrete = constants.%int_3.822] // CHECK:STDOUT: %.loc36_10.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc36 [concrete = constants.%int_3.822] // CHECK:STDOUT: %.loc36_10.2: %i32 = converted %int_3.loc36, %.loc36_10.1 [concrete = constants.%int_3.822] -// CHECK:STDOUT: %cpp_operator.call.loc36: init %const.7c5 = call imports.%cpp_operator.decl.4206c9.19(%c1.ref.loc36, %.loc36_10.2) +// CHECK:STDOUT: %cpp_operator.call.loc36: ref %C = call imports.%cpp_operator.decl.4206c9.19(%c1.ref.loc36, %.loc36_10.2) // CHECK:STDOUT: %c1.ref.loc37: ref %C = name_ref c1, %c1 // CHECK:STDOUT: %int_5.loc37: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b] // CHECK:STDOUT: %impl.elem0.loc37: %.863 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5] @@ -1788,7 +1786,7 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc37: init %i32 = call %bound_method.loc37_10.2(%int_5.loc37) [concrete = constants.%int_5.0f6] // CHECK:STDOUT: %.loc37_10.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc37 [concrete = constants.%int_5.0f6] // CHECK:STDOUT: %.loc37_10.2: %i32 = converted %int_5.loc37, %.loc37_10.1 [concrete = constants.%int_5.0f6] -// CHECK:STDOUT: %cpp_operator.call.loc37: init %const.7c5 = call imports.%cpp_operator.decl.4206c9.20(%c1.ref.loc37, %.loc37_10.2) +// CHECK:STDOUT: %cpp_operator.call.loc37: ref %C = call imports.%cpp_operator.decl.4206c9.20(%c1.ref.loc37, %.loc37_10.2) // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %equal.patt: %pattern_type.831 = value_binding_pattern equal [concrete] // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/interop/cpp/function/reference.carbon b/toolchain/check/testdata/interop/cpp/function/reference.carbon index f71e5bf896ed..aababf9a0df0 100644 --- a/toolchain/check/testdata/interop/cpp/function/reference.carbon +++ b/toolchain/check/testdata/interop/cpp/function/reference.carbon @@ -248,7 +248,7 @@ import Cpp library "return_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin - let s: Cpp.S* = Cpp.ReturnsLValue(); + let ref s: Cpp.S = Cpp.ReturnsLValue(); //@dump-sem-ir-end } @@ -270,7 +270,7 @@ import Cpp library "return_rvalue_ref.h"; fn F() { //@dump-sem-ir-begin - var s: Cpp.S* = Cpp.ReturnsRValue(); + let ref s: Cpp.S = Cpp.ReturnsRValue(); //@dump-sem-ir-end } @@ -292,7 +292,7 @@ import Cpp library "return_const_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin - var s: const Cpp.S* = Cpp.ReturnConstLValue(); + let ref s: const Cpp.S = Cpp.ReturnConstLValue(); //@dump-sem-ir-end } @@ -303,16 +303,17 @@ library "[[@TEST_NAME]]"; import Cpp library "return_const_lvalue_ref.h"; fn F() { - // CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `const (const Cpp.S*)` to `Cpp.S*` [ConversionFailure] - // CHECK:STDERR: var s: Cpp.S* = Cpp.ReturnConstLValue(); - // CHECK:STDERR: ^~~~~~~~~~~~~ - // CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+4]]:3: note: type `const (const Cpp.S*)` does not implement interface `Core.ImplicitAs(Cpp.S*)` [MissingImplInMemberAccessNote] - // CHECK:STDERR: var s: Cpp.S* = Cpp.ReturnConstLValue(); - // CHECK:STDERR: ^~~~~~~~~~~~~ + // CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+7]]:22: error: cannot implicitly convert expression of type `const Cpp.S` to `Cpp.S` [ConversionFailure] + // CHECK:STDERR: let ref s: Cpp.S = Cpp.ReturnConstLValue(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+4]]:22: note: type `const Cpp.S` does not implement interface `Core.ImplicitAs(Cpp.S)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: let ref s: Cpp.S = Cpp.ReturnConstLValue(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - var s: Cpp.S* = Cpp.ReturnConstLValue(); + let ref s: Cpp.S = Cpp.ReturnConstLValue(); } + // CHECK:STDOUT: --- call_param_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -849,17 +850,12 @@ fn F() { // CHECK:STDOUT: --- call_return_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %S: type = class_type @S [concrete] -// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete] -// CHECK:STDOUT: %pattern_type.259: type = pattern_type %ptr [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %S [concrete] // CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnsLValue.cpp_overload_set [concrete] // CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.value: %ReturnsLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsLValue.cpp_overload_set [concrete] -// CHECK:STDOUT: %const: type = const_type %ptr [concrete] // CHECK:STDOUT: %ReturnsLValue.type: type = fn_type @ReturnsLValue [concrete] // CHECK:STDOUT: %ReturnsLValue: %ReturnsLValue.type = struct_value () [concrete] -// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete] -// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -870,53 +866,34 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.value: %ReturnsLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsLValue.cpp_overload_set [concrete = constants.%ReturnsLValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } +// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %s.patt: %pattern_type.259 = value_binding_pattern s [concrete] +// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc8_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Cpp.ref.loc8_22: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %ReturnsLValue.ref: %ReturnsLValue.cpp_overload_set.type = name_ref ReturnsLValue, imports.%ReturnsLValue.cpp_overload_set.value [concrete = constants.%ReturnsLValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnsLValue.call: init %const = call imports.%ReturnsLValue.decl() -// CHECK:STDOUT: %.loc8_15: type = splice_block %ptr [concrete = constants.%ptr] { -// CHECK:STDOUT: %Cpp.ref.loc8_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnsLValue.call: ref %S = call imports.%ReturnsLValue.decl() +// CHECK:STDOUT: %.loc8: type = splice_block %S.ref [concrete = constants.%S] { +// CHECK:STDOUT: %Cpp.ref.loc8_14: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S] -// CHECK:STDOUT: %ptr: type = ptr_type %S.ref [concrete = constants.%ptr] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc8_37.1: init %ptr = as_compatible %ReturnsLValue.call -// CHECK:STDOUT: %.loc8_37.2: init %ptr = converted %ReturnsLValue.call, %.loc8_37.1 -// CHECK:STDOUT: %.loc8_37.3: ref %ptr = temporary_storage -// CHECK:STDOUT: %.loc8_37.4: ref %ptr = temporary %.loc8_37.3, %.loc8_37.2 -// CHECK:STDOUT: %.loc8_37.5: %ptr = acquire_value %.loc8_37.4 -// CHECK:STDOUT: %s: %ptr = value_binding s, %.loc8_37.5 -// CHECK:STDOUT: %DestroyOp.bound: = bound_method %.loc8_37.4, constants.%DestroyOp -// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc8_37.4) +// CHECK:STDOUT: %s: ref %S = ref_binding s, %ReturnsLValue.call // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op"; -// CHECK:STDOUT: // CHECK:STDOUT: --- call_return_rvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %S: type = class_type @S [concrete] -// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete] -// CHECK:STDOUT: %pattern_type.259: type = pattern_type %ptr [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %S [concrete] // CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnsRValue.cpp_overload_set [concrete] // CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.value: %ReturnsRValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsRValue.cpp_overload_set [concrete] -// CHECK:STDOUT: %const: type = const_type %ptr [concrete] // CHECK:STDOUT: %ReturnsRValue.type: type = fn_type @ReturnsRValue [concrete] // CHECK:STDOUT: %ReturnsRValue: %ReturnsRValue.type = struct_value () [concrete] -// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete] -// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -927,54 +904,35 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.value: %ReturnsRValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsRValue.cpp_overload_set [concrete = constants.%ReturnsRValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } +// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %s.patt: %pattern_type.259 = ref_binding_pattern s [concrete] -// CHECK:STDOUT: %s.var_patt: %pattern_type.259 = var_pattern %s.patt [concrete] +// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %s.var: ref %ptr = var %s.var_patt -// CHECK:STDOUT: %Cpp.ref.loc8_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Cpp.ref.loc8_22: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %ReturnsRValue.ref: %ReturnsRValue.cpp_overload_set.type = name_ref ReturnsRValue, imports.%ReturnsRValue.cpp_overload_set.value [concrete = constants.%ReturnsRValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnsRValue.call: init %const = call imports.%ReturnsRValue.decl() -// CHECK:STDOUT: %.loc8_3.1: init %ptr = as_compatible %ReturnsRValue.call -// CHECK:STDOUT: %.loc8_3.2: init %ptr = converted %ReturnsRValue.call, %.loc8_3.1 -// CHECK:STDOUT: assign %s.var, %.loc8_3.2 -// CHECK:STDOUT: %.loc8_15: type = splice_block %ptr [concrete = constants.%ptr] { -// CHECK:STDOUT: %Cpp.ref.loc8_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnsRValue.call: ref %S = call imports.%ReturnsRValue.decl() +// CHECK:STDOUT: %.loc8: type = splice_block %S.ref [concrete = constants.%S] { +// CHECK:STDOUT: %Cpp.ref.loc8_14: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S] -// CHECK:STDOUT: %ptr: type = ptr_type %S.ref [concrete = constants.%ptr] // CHECK:STDOUT: } -// CHECK:STDOUT: %s: ref %ptr = ref_binding s, %s.var -// CHECK:STDOUT: %DestroyOp.bound: = bound_method %s.var, constants.%DestroyOp -// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%s.var) +// CHECK:STDOUT: %s: ref %S = ref_binding s, %ReturnsRValue.call // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op"; -// CHECK:STDOUT: // CHECK:STDOUT: --- call_return_const_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %S: type = class_type @S [concrete] -// CHECK:STDOUT: %const.e39: type = const_type %S [concrete] -// CHECK:STDOUT: %ptr: type = ptr_type %const.e39 [concrete] -// CHECK:STDOUT: %pattern_type.32f: type = pattern_type %ptr [concrete] +// CHECK:STDOUT: %const: type = const_type %S [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %const [concrete] // CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnConstLValue.cpp_overload_set [concrete] // CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.value: %ReturnConstLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnConstLValue.cpp_overload_set [concrete] -// CHECK:STDOUT: %const.179: type = const_type %ptr [concrete] // CHECK:STDOUT: %ReturnConstLValue.type: type = fn_type @ReturnConstLValue [concrete] // CHECK:STDOUT: %ReturnConstLValue: %ReturnConstLValue.type = struct_value () [concrete] -// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete] -// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -985,37 +943,23 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.value: %ReturnConstLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnConstLValue.cpp_overload_set [concrete = constants.%ReturnConstLValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } +// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %s.patt: %pattern_type.32f = ref_binding_pattern s [concrete] -// CHECK:STDOUT: %s.var_patt: %pattern_type.32f = var_pattern %s.patt [concrete] +// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %s.var: ref %ptr = var %s.var_patt -// CHECK:STDOUT: %Cpp.ref.loc8_25: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Cpp.ref.loc8_28: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %ReturnConstLValue.ref: %ReturnConstLValue.cpp_overload_set.type = name_ref ReturnConstLValue, imports.%ReturnConstLValue.cpp_overload_set.value [concrete = constants.%ReturnConstLValue.cpp_overload_set.value] -// CHECK:STDOUT: %ReturnConstLValue.call: init %const.179 = call imports.%ReturnConstLValue.decl() -// CHECK:STDOUT: %.loc8_3.1: init %ptr = as_compatible %ReturnConstLValue.call -// CHECK:STDOUT: %.loc8_3.2: init %ptr = converted %ReturnConstLValue.call, %.loc8_3.1 -// CHECK:STDOUT: assign %s.var, %.loc8_3.2 -// CHECK:STDOUT: %.loc8_21: type = splice_block %ptr [concrete = constants.%ptr] { -// CHECK:STDOUT: %Cpp.ref.loc8_16: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnConstLValue.call: ref %const = call imports.%ReturnConstLValue.decl() +// CHECK:STDOUT: %.loc8: type = splice_block %const [concrete = constants.%const] { +// CHECK:STDOUT: %Cpp.ref.loc8_20: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S] -// CHECK:STDOUT: %const: type = const_type %S.ref [concrete = constants.%const.e39] -// CHECK:STDOUT: %ptr: type = ptr_type %const [concrete = constants.%ptr] +// CHECK:STDOUT: %const: type = const_type %S.ref [concrete = constants.%const] // CHECK:STDOUT: } -// CHECK:STDOUT: %s: ref %ptr = ref_binding s, %s.var -// CHECK:STDOUT: %DestroyOp.bound: = bound_method %s.var, constants.%DestroyOp -// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%s.var) +// CHECK:STDOUT: %s: ref %const = ref_binding s, %ReturnConstLValue.call // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op"; -// CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/reference.carbon b/toolchain/lower/testdata/interop/cpp/reference.carbon index b75d6acbe2c1..431fbaaa7516 100644 --- a/toolchain/lower/testdata/interop/cpp/reference.carbon +++ b/toolchain/lower/testdata/interop/cpp/reference.carbon @@ -92,13 +92,13 @@ auto ReturnConstIntRef() -> const int&; '''; fn GetRefs() { - var _: Cpp.C* = Cpp.ReturnCRef(); - var _: Cpp.C* = Cpp.ReturnCRRef(); - var _: const Cpp.C* = Cpp.ReturnConstCRef(); + let ref _: Cpp.C = Cpp.ReturnCRef(); + let ref _: Cpp.C = Cpp.ReturnCRRef(); + let ref _: const Cpp.C = Cpp.ReturnConstCRef(); - var _: i32* = Cpp.ReturnIntRef(); - var _: i32* = Cpp.ReturnIntRRef(); - var _: const i32* = Cpp.ReturnConstIntRef(); + let ref _: i32 = Cpp.ReturnIntRef(); + let ref _: i32 = Cpp.ReturnIntRRef(); + let ref _: const i32 = Cpp.ReturnConstIntRef(); } // --- return_references_via_thunk.carbon @@ -119,13 +119,13 @@ auto ReturnConstIntRef(ForceThunk = {}) -> const int&; '''; fn GetRefs() { - var _: Cpp.C* = Cpp.ReturnCRef(); - var _: Cpp.C* = Cpp.ReturnCRRef(); - var _: const Cpp.C* = Cpp.ReturnConstCRef(); + let ref _: Cpp.C = Cpp.ReturnCRef(); + let ref _: Cpp.C = Cpp.ReturnCRRef(); + let ref _: const Cpp.C = Cpp.ReturnConstCRef(); - var _: i32* = Cpp.ReturnIntRef(); - var _: i32* = Cpp.ReturnIntRRef(); - var _: const i32* = Cpp.ReturnConstIntRef(); + let ref _: i32 = Cpp.ReturnIntRef(); + let ref _: i32 = Cpp.ReturnIntRRef(); + let ref _: const i32 = Cpp.ReturnConstIntRef(); } // CHECK:STDOUT: ; ModuleID = 'pass_references.carbon' @@ -438,31 +438,13 @@ fn GetRefs() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CGetRefs.Main() #0 !dbg !12 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %_.var.loc17 = alloca ptr, align 8, !dbg !15 -// CHECK:STDOUT: %_.var.loc18 = alloca ptr, align 8, !dbg !16 -// CHECK:STDOUT: %_.var.loc19 = alloca ptr, align 8, !dbg !17 -// CHECK:STDOUT: %_.var.loc21 = alloca ptr, align 8, !dbg !18 -// CHECK:STDOUT: %_.var.loc22 = alloca ptr, align 8, !dbg !19 -// CHECK:STDOUT: %_.var.loc23 = alloca ptr, align 8, !dbg !20 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc17), !dbg !15 -// CHECK:STDOUT: %ReturnCRef.call = call ptr @_Z10ReturnCRefv(), !dbg !21 -// CHECK:STDOUT: store ptr %ReturnCRef.call, ptr %_.var.loc17, align 8, !dbg !15 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc18), !dbg !16 -// CHECK:STDOUT: %ReturnCRRef.call = call ptr @_Z11ReturnCRRefv(), !dbg !22 -// CHECK:STDOUT: store ptr %ReturnCRRef.call, ptr %_.var.loc18, align 8, !dbg !16 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc19), !dbg !17 -// CHECK:STDOUT: %ReturnConstCRef.call = call ptr @_Z15ReturnConstCRefv(), !dbg !23 -// CHECK:STDOUT: store ptr %ReturnConstCRef.call, ptr %_.var.loc19, align 8, !dbg !17 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc21), !dbg !18 -// CHECK:STDOUT: %ReturnIntRef.call = call ptr @_Z12ReturnIntRefv(), !dbg !24 -// CHECK:STDOUT: store ptr %ReturnIntRef.call, ptr %_.var.loc21, align 8, !dbg !18 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc22), !dbg !19 -// CHECK:STDOUT: %ReturnIntRRef.call = call ptr @_Z13ReturnIntRRefv(), !dbg !25 -// CHECK:STDOUT: store ptr %ReturnIntRRef.call, ptr %_.var.loc22, align 8, !dbg !19 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc23), !dbg !20 -// CHECK:STDOUT: %ReturnConstIntRef.call = call ptr @_Z17ReturnConstIntRefv(), !dbg !26 -// CHECK:STDOUT: store ptr %ReturnConstIntRef.call, ptr %_.var.loc23, align 8, !dbg !20 -// CHECK:STDOUT: ret void, !dbg !27 +// CHECK:STDOUT: %ReturnCRef.call = call ptr @_Z10ReturnCRefv(), !dbg !15 +// CHECK:STDOUT: %ReturnCRRef.call = call ptr @_Z11ReturnCRRefv(), !dbg !16 +// CHECK:STDOUT: %ReturnConstCRef.call = call ptr @_Z15ReturnConstCRefv(), !dbg !17 +// CHECK:STDOUT: %ReturnIntRef.call = call ptr @_Z12ReturnIntRefv(), !dbg !18 +// CHECK:STDOUT: %ReturnIntRRef.call = call ptr @_Z13ReturnIntRRefv(), !dbg !19 +// CHECK:STDOUT: %ReturnConstIntRef.call = call ptr @_Z17ReturnConstIntRefv(), !dbg !20 +// CHECK:STDOUT: ret void, !dbg !21 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: declare ptr @_Z10ReturnCRefv() @@ -477,14 +459,7 @@ fn GetRefs() { // CHECK:STDOUT: // CHECK:STDOUT: declare ptr @_Z17ReturnConstIntRefv() // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) -// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #1 -// CHECK:STDOUT: -// CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 5, 4, 3, 2, 1, 0 } -// CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } -// CHECK:STDOUT: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} // CHECK:STDOUT: !llvm.dbg.cu = !{!6} @@ -505,19 +480,13 @@ fn GetRefs() { // CHECK:STDOUT: !12 = distinct !DISubprogram(name: "GetRefs", linkageName: "_CGetRefs.Main", scope: null, file: !7, line: 16, type: !13, spFlags: DISPFlagDefinition, unit: !6) // CHECK:STDOUT: !13 = !DISubroutineType(types: !14) // CHECK:STDOUT: !14 = !{null} -// CHECK:STDOUT: !15 = !DILocation(line: 17, column: 3, scope: !12) -// CHECK:STDOUT: !16 = !DILocation(line: 18, column: 3, scope: !12) -// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 3, scope: !12) -// CHECK:STDOUT: !18 = !DILocation(line: 21, column: 3, scope: !12) -// CHECK:STDOUT: !19 = !DILocation(line: 22, column: 3, scope: !12) -// CHECK:STDOUT: !20 = !DILocation(line: 23, column: 3, scope: !12) -// CHECK:STDOUT: !21 = !DILocation(line: 17, column: 19, scope: !12) -// CHECK:STDOUT: !22 = !DILocation(line: 18, column: 19, scope: !12) -// CHECK:STDOUT: !23 = !DILocation(line: 19, column: 25, scope: !12) -// CHECK:STDOUT: !24 = !DILocation(line: 21, column: 17, scope: !12) -// CHECK:STDOUT: !25 = !DILocation(line: 22, column: 17, scope: !12) -// CHECK:STDOUT: !26 = !DILocation(line: 23, column: 23, scope: !12) -// CHECK:STDOUT: !27 = !DILocation(line: 16, column: 1, scope: !12) +// CHECK:STDOUT: !15 = !DILocation(line: 17, column: 22, scope: !12) +// CHECK:STDOUT: !16 = !DILocation(line: 18, column: 22, scope: !12) +// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 28, scope: !12) +// CHECK:STDOUT: !18 = !DILocation(line: 21, column: 20, scope: !12) +// CHECK:STDOUT: !19 = !DILocation(line: 22, column: 20, scope: !12) +// CHECK:STDOUT: !20 = !DILocation(line: 23, column: 26, scope: !12) +// CHECK:STDOUT: !21 = !DILocation(line: 16, column: 1, scope: !12) // CHECK:STDOUT: ; ModuleID = 'return_references_via_thunk.carbon' // CHECK:STDOUT: source_filename = "return_references_via_thunk.carbon" // CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" @@ -528,103 +497,78 @@ fn GetRefs() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CGetRefs.Main() #0 !dbg !12 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %_.var.loc18 = alloca ptr, align 8, !dbg !15 -// CHECK:STDOUT: %_.var.loc19 = alloca ptr, align 8, !dbg !16 -// CHECK:STDOUT: %_.var.loc20 = alloca ptr, align 8, !dbg !17 -// CHECK:STDOUT: %_.var.loc22 = alloca ptr, align 8, !dbg !18 -// CHECK:STDOUT: %_.var.loc23 = alloca ptr, align 8, !dbg !19 -// CHECK:STDOUT: %_.var.loc24 = alloca ptr, align 8, !dbg !20 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc18), !dbg !15 -// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0(), !dbg !21 -// CHECK:STDOUT: store ptr %ReturnCRef__carbon_thunk.call, ptr %_.var.loc18, align 8, !dbg !15 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc19), !dbg !16 -// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0(), !dbg !22 -// CHECK:STDOUT: store ptr %ReturnCRRef__carbon_thunk.call, ptr %_.var.loc19, align 8, !dbg !16 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc20), !dbg !17 -// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0(), !dbg !23 -// CHECK:STDOUT: store ptr %ReturnConstCRef__carbon_thunk.call, ptr %_.var.loc20, align 8, !dbg !17 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc22), !dbg !18 -// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0(), !dbg !24 -// CHECK:STDOUT: store ptr %ReturnIntRef__carbon_thunk.call, ptr %_.var.loc22, align 8, !dbg !18 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc23), !dbg !19 -// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0(), !dbg !25 -// CHECK:STDOUT: store ptr %ReturnIntRRef__carbon_thunk.call, ptr %_.var.loc23, align 8, !dbg !19 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc24), !dbg !20 -// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0(), !dbg !26 -// CHECK:STDOUT: store ptr %ReturnConstIntRef__carbon_thunk.call, ptr %_.var.loc24, align 8, !dbg !20 -// CHECK:STDOUT: ret void, !dbg !27 +// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0(), !dbg !15 +// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0(), !dbg !16 +// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0(), !dbg !17 +// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0(), !dbg !18 +// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0(), !dbg !19 +// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0(), !dbg !20 +// CHECK:STDOUT: ret void, !dbg !21 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) -// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #1 -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk() #3 +// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk() #3 +// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk() #3 +// CHECK:STDOUT: declare noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk() #3 +// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk() #3 +// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0() #2 { +// CHECK:STDOUT: define dso_local noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk() // CHECK:STDOUT: ret ptr %call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk() #3 -// CHECK:STDOUT: -// CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 5, 4, 3, 2, 1, 0 } +// CHECK:STDOUT: declare noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk() #2 // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } -// CHECK:STDOUT: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } -// CHECK:STDOUT: attributes #2 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #3 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} // CHECK:STDOUT: !llvm.dbg.cu = !{!6} @@ -645,16 +589,10 @@ fn GetRefs() { // CHECK:STDOUT: !12 = distinct !DISubprogram(name: "GetRefs", linkageName: "_CGetRefs.Main", scope: null, file: !7, line: 17, type: !13, spFlags: DISPFlagDefinition, unit: !6) // CHECK:STDOUT: !13 = !DISubroutineType(types: !14) // CHECK:STDOUT: !14 = !{null} -// CHECK:STDOUT: !15 = !DILocation(line: 18, column: 3, scope: !12) -// CHECK:STDOUT: !16 = !DILocation(line: 19, column: 3, scope: !12) -// CHECK:STDOUT: !17 = !DILocation(line: 20, column: 3, scope: !12) -// CHECK:STDOUT: !18 = !DILocation(line: 22, column: 3, scope: !12) -// CHECK:STDOUT: !19 = !DILocation(line: 23, column: 3, scope: !12) -// CHECK:STDOUT: !20 = !DILocation(line: 24, column: 3, scope: !12) -// CHECK:STDOUT: !21 = !DILocation(line: 18, column: 19, scope: !12) -// CHECK:STDOUT: !22 = !DILocation(line: 19, column: 19, scope: !12) -// CHECK:STDOUT: !23 = !DILocation(line: 20, column: 25, scope: !12) -// CHECK:STDOUT: !24 = !DILocation(line: 22, column: 17, scope: !12) -// CHECK:STDOUT: !25 = !DILocation(line: 23, column: 17, scope: !12) -// CHECK:STDOUT: !26 = !DILocation(line: 24, column: 23, scope: !12) -// CHECK:STDOUT: !27 = !DILocation(line: 17, column: 1, scope: !12) +// CHECK:STDOUT: !15 = !DILocation(line: 18, column: 22, scope: !12) +// CHECK:STDOUT: !16 = !DILocation(line: 19, column: 22, scope: !12) +// CHECK:STDOUT: !17 = !DILocation(line: 20, column: 28, scope: !12) +// CHECK:STDOUT: !18 = !DILocation(line: 22, column: 20, scope: !12) +// CHECK:STDOUT: !19 = !DILocation(line: 23, column: 20, scope: !12) +// CHECK:STDOUT: !20 = !DILocation(line: 24, column: 26, scope: !12) +// CHECK:STDOUT: !21 = !DILocation(line: 17, column: 1, scope: !12)