Expose C++ reference returns as Carbon reference returns (#6618)

Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
This commit is contained in:
Geoff Romer
2026-01-16 18:08:42 +00:00
committed by GitHub
co-authored by Carbon Infra Bot
parent 94d9bff541
commit 95eb7b16bb
5 changed files with 162 additions and 258 deletions
+3 -1
View File
@@ -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;
+56 -34
View File
@@ -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::CXXConstructorDecl>(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<SemIR::InitForm>(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};
}
@@ -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> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]
// CHECK:STDOUT: %bound_method.e9d: <bound method> = 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: }
@@ -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: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// 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: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_22: <namespace> = 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: <namespace> = 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: <namespace> = 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> = 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: <elided>
// 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: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// 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: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_22: <namespace> = 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: <namespace> = 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: <namespace> = 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> = 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: <elided>
// 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: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// 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: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_28: <namespace> = 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: <namespace> = 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: <namespace> = 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> = 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: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op";
// CHECK:STDOUT:
+54 -116
View File
@@ -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)