From a16102b249b4271617b881656234243d7db74f05 Mon Sep 17 00:00:00 2001 From: Boaz Brickner Date: Thu, 2 Oct 2025 10:49:10 +0200 Subject: [PATCH] Add tests for returning a C++ reference type, rvalue and const reference (#6149) Part of #6148. --- .../interop/cpp/function/reference.carbon | 328 +++++++++++++++--- 1 file changed, 281 insertions(+), 47 deletions(-) diff --git a/toolchain/check/testdata/interop/cpp/function/reference.carbon b/toolchain/check/testdata/interop/cpp/function/reference.carbon index e79b6dbbfa73..5bdf26f71324 100644 --- a/toolchain/check/testdata/interop/cpp/function/reference.carbon +++ b/toolchain/check/testdata/interop/cpp/function/reference.carbon @@ -14,18 +14,18 @@ // Lvalue reference as a parameter type // ============================================================================ -// --- lvalue_ref.h +// --- param_lvalue_ref.h struct S {}; struct T {}; auto TakesLValue(S&) -> void; -// --- call_lvalue_ref.carbon +// --- call_param_lvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "lvalue_ref.h"; +import Cpp library "param_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin @@ -34,43 +34,43 @@ fn F() { //@dump-sem-ir-end } -// --- fail_lvalue_ref.carbon +// --- fail_param_lvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "lvalue_ref.h"; +import Cpp library "param_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin var v: Cpp.S; let s: Cpp.S = v; - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError] // CHECK:STDERR: 18 | Cpp.TakesLValue(s); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-9]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: expects an lvalue for 1st argument [CppInteropParseNote] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-9]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: expects an lvalue for 1st argument [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesLValue(S&) -> void; // CHECK:STDERR: | ^ ~~ // CHECK:STDERR: Cpp.TakesLValue(s); var t: Cpp.T; - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError] // CHECK:STDERR: 29 | Cpp.TakesLValue(t); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesLValue(S&) -> void; // CHECK:STDERR: | ^ ~~ // CHECK:STDERR: Cpp.TakesLValue(t); var u: Cpp.S; - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:35: error: no matching function for call to 'TakesLValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:35: error: no matching function for call to 'TakesLValue' [CppInteropParseError] // CHECK:STDERR: 40 | Cpp.TakesLValue(u as const Cpp.S); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote] + // CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesLValue(S&) -> void; // CHECK:STDERR: | ^ ~~ // CHECK:STDERR: @@ -82,18 +82,18 @@ fn F() { // Rvalue reference as a parameter type // ============================================================================ -// --- rvalue_ref.h +// --- param_rvalue_ref.h struct S {}; struct T {}; auto TakesRValue(S&&) -> void; -// --- call_rvalue_ref.carbon +// --- call_param_rvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "rvalue_ref.h"; +import Cpp library "param_rvalue_ref.h"; fn F() { //@dump-sem-ir-begin @@ -101,11 +101,11 @@ fn F() { //@dump-sem-ir-end } -// --- todo_fail_value_arg_for_rvalue_ref.carbon +// --- todo_fail_param_value_arg_for_rvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "rvalue_ref.h"; +import Cpp library "param_rvalue_ref.h"; fn F() { //@dump-sem-ir-begin @@ -118,41 +118,41 @@ fn F() { //@dump-sem-ir-end } -// --- fail_rvalue_ref.carbon +// --- fail_param_rvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "rvalue_ref.h"; +import Cpp library "param_rvalue_ref.h"; fn F() { //@dump-sem-ir-begin var s: Cpp.S; - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError] // CHECK:STDERR: 17 | Cpp.TakesRValue(s); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-8]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: expects an rvalue for 1st argument [CppInteropParseNote] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-8]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: expects an rvalue for 1st argument [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void; // CHECK:STDERR: | ^ ~~~ // CHECK:STDERR: Cpp.TakesRValue(s); var t: Cpp.T; - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError] // CHECK:STDERR: 28 | Cpp.TakesRValue(t); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void; // CHECK:STDERR: | ^ ~~~ // CHECK:STDERR: Cpp.TakesRValue(t); - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:47: error: no matching function for call to 'TakesRValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:47: error: no matching function for call to 'TakesRValue' [CppInteropParseError] // CHECK:STDERR: 38 | Cpp.TakesRValue(({} as Cpp.S) as const Cpp.S); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote] + // CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void; // CHECK:STDERR: | ^ ~~~ // CHECK:STDERR: @@ -164,18 +164,18 @@ fn F() { // Const reference as a parameter type // ============================================================================ -// --- const_lvalue_ref.h +// --- param_const_lvalue_ref.h struct S {}; struct T {}; auto TakesConstLValue(const S&) -> void; -// --- call_const_lvalue_ref.carbon +// --- call_param_const_lvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "const_lvalue_ref.h"; +import Cpp library "param_const_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin @@ -186,11 +186,11 @@ fn F() { //@dump-sem-ir-end } -// --- fail_const_lvalue_ref.carbon +// --- fail_param_const_lvalue_ref.carbon library "[[@TEST_NAME]]"; -import Cpp library "const_lvalue_ref.h"; +import Cpp library "param_const_lvalue_ref.h"; fn F() { //@dump-sem-ir-begin @@ -199,19 +199,19 @@ fn F() { // TODO: The diagnostic here is wrong; we're internally using `addr` but this // is not `addr self`. let s: Cpp.S = {}; - // CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE+5]]:24: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef] + // CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE+5]]:24: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef] // CHECK:STDERR: Cpp.TakesConstLValue(s); // CHECK:STDERR: ^ - // CHECK:STDERR: fail_const_lvalue_ref.carbon: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fail_param_const_lvalue_ref.carbon: note: initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: Cpp.TakesConstLValue(s); var t: Cpp.T; - // CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE+8]]:25: error: no matching function for call to 'TakesConstLValue' [CppInteropParseError] + // CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE+8]]:25: error: no matching function for call to 'TakesConstLValue' [CppInteropParseError] // CHECK:STDERR: 29 | Cpp.TakesConstLValue(t); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude] - // CHECK:STDERR: ./const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'const S' for 1st argument [CppInteropParseNote] + // CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./param_const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'const S' for 1st argument [CppInteropParseNote] // CHECK:STDERR: 5 | auto TakesConstLValue(const S&) -> void; // CHECK:STDERR: | ^ ~~~~~~~~ // CHECK:STDERR: @@ -219,7 +219,79 @@ fn F() { //@dump-sem-ir-end } -// CHECK:STDOUT: --- call_lvalue_ref.carbon +// ============================================================================ +// Lvalue reference as return type +// ============================================================================ + +// --- fail_todo_call_return_lvalue_ref.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +struct S {}; + +auto ReturnsLValue() -> S&; +'''; + +fn F() { + //@dump-sem-ir-begin + // CHECK:STDERR: fail_todo_call_return_lvalue_ref.carbon:[[@LINE+4]]:19: error: semantics TODO: `Unsupported: return type: S &` [SemanticsTodo] + // CHECK:STDERR: let s: Cpp.S* = Cpp.ReturnsLValue(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + let s: Cpp.S* = Cpp.ReturnsLValue(); + //@dump-sem-ir-end +} + +// ============================================================================ +// Rvalue reference as return type +// ============================================================================ + +// --- fail_todo_call_return_rvalue_ref.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +struct S {}; + +auto ReturnsRValue() -> S&&; +'''; + +fn F() { + //@dump-sem-ir-begin + // CHECK:STDERR: fail_todo_call_return_rvalue_ref.carbon:[[@LINE+4]]:18: error: semantics TODO: `Unsupported: return type: S &&` [SemanticsTodo] + // CHECK:STDERR: var s: Cpp.S = Cpp.ReturnsRValue(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + var s: Cpp.S = Cpp.ReturnsRValue(); + //@dump-sem-ir-end +} + +// ============================================================================ +// Const reference as return type +// ============================================================================ + +// --- fail_todo_call_return_const_lvalue_ref.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +struct S {}; + +auto ReturnConstLValue() -> const S&; +'''; + +fn F() { + //@dump-sem-ir-begin + // CHECK:STDERR: fail_todo_call_return_const_lvalue_ref.carbon:[[@LINE+4]]:24: error: semantics TODO: `Unsupported: return type: const S &` [SemanticsTodo] + // CHECK:STDERR: var s: const Cpp.S = Cpp.ReturnConstLValue(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + var s: const Cpp.S = Cpp.ReturnConstLValue(); + //@dump-sem-ir-end +} + +// CHECK:STDOUT: --- call_param_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -284,7 +356,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_lvalue_ref.carbon +// CHECK:STDOUT: --- fail_param_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -398,7 +470,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- call_rvalue_ref.carbon +// CHECK:STDOUT: --- call_param_rvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -456,7 +528,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_value_arg_for_rvalue_ref.carbon +// CHECK:STDOUT: --- todo_fail_param_value_arg_for_rvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -522,7 +594,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_rvalue_ref.carbon +// CHECK:STDOUT: --- fail_param_rvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -624,7 +696,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- call_const_lvalue_ref.carbon +// CHECK:STDOUT: --- call_param_const_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -703,7 +775,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_const_lvalue_ref.carbon +// CHECK:STDOUT: --- fail_param_const_lvalue_ref.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] @@ -801,3 +873,165 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_call_return_lvalue_ref.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %S: type = class_type @S [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete] +// CHECK:STDOUT: %.041: type = cpp_overload_set_type @ReturnsLValue [concrete] +// CHECK:STDOUT: %.03d: %.041 = cpp_overload_set_value @ReturnsLValue [concrete] +// CHECK:STDOUT: %ReturnsLValue.type: type = fn_type @ReturnsLValue [concrete] +// CHECK:STDOUT: %ReturnsLValue: %ReturnsLValue.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .S = %S.decl +// CHECK:STDOUT: .ReturnsLValue = %.03d +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} +// CHECK:STDOUT: %.03d: %.041 = cpp_overload_set_value @ReturnsLValue [concrete = constants.%.03d] +// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %s.patt: %pattern_type = binding_pattern s [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc16_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnsLValue.ref: %.041 = name_ref ReturnsLValue, imports.%.03d [concrete = constants.%.03d] +// CHECK:STDOUT: %ReturnsLValue.call: init = call imports.%ReturnsLValue.decl() +// CHECK:STDOUT: %.loc16: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref.loc16_10: = 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: %ptr = bind_name s, [concrete = ] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_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: %pattern_type.7da: type = pattern_type %S [concrete] +// CHECK:STDOUT: %.c60: type = cpp_overload_set_type @ReturnsRValue [concrete] +// CHECK:STDOUT: %.99d: %.c60 = cpp_overload_set_value @ReturnsRValue [concrete] +// CHECK:STDOUT: %ReturnsRValue.type: type = fn_type @ReturnsRValue [concrete] +// CHECK:STDOUT: %ReturnsRValue: %ReturnsRValue.type = struct_value () [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %S, () [concrete] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.type.df1: type = fn_type @DestroyT.as_type.as.Destroy.impl.Op, @DestroyT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.cc2: %DestroyT.as_type.as.Destroy.impl.Op.type.df1 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .S = %S.decl +// CHECK:STDOUT: .ReturnsRValue = %.99d +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} +// CHECK:STDOUT: %.99d: %.c60 = cpp_overload_set_value @ReturnsRValue [concrete = constants.%.99d] +// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %s.patt: %pattern_type.7da = binding_pattern s [concrete] +// CHECK:STDOUT: %s.var_patt: %pattern_type.7da = var_pattern %s.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt +// CHECK:STDOUT: %Cpp.ref.loc16_18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnsRValue.ref: %.c60 = name_ref ReturnsRValue, imports.%.99d [concrete = constants.%.99d] +// CHECK:STDOUT: %ReturnsRValue.call: init = call imports.%ReturnsRValue.decl() +// CHECK:STDOUT: assign %s.var, +// CHECK:STDOUT: %.loc16_13: type = splice_block %S.ref [concrete = constants.%S] { +// CHECK:STDOUT: %Cpp.ref.loc16_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var +// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%S, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc16_3: %type_where = converted constants.%S, %facet_value [concrete = constants.%facet_value] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.bound: = bound_method %s.var, constants.%DestroyT.as_type.as.Destroy.impl.Op.cc2 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method: = bound_method %s.var, %DestroyT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr: %ptr.5c7 = addr_of %s.var +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_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: type = const_type %S [concrete] +// CHECK:STDOUT: %pattern_type.9be: type = pattern_type %const [concrete] +// CHECK:STDOUT: %.c99: type = cpp_overload_set_type @ReturnConstLValue [concrete] +// CHECK:STDOUT: %.bf8: %.c99 = cpp_overload_set_value @ReturnConstLValue [concrete] +// CHECK:STDOUT: %ReturnConstLValue.type: type = fn_type @ReturnConstLValue [concrete] +// CHECK:STDOUT: %ReturnConstLValue: %ReturnConstLValue.type = struct_value () [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %const, () [concrete] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.type.31d: type = fn_type @DestroyT.as_type.as.Destroy.impl.Op, @DestroyT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.818: %DestroyT.as_type.as.Destroy.impl.Op.type.31d = struct_value () [concrete] +// CHECK:STDOUT: %ptr.ff5: type = ptr_type %const [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .S = %S.decl +// CHECK:STDOUT: .ReturnConstLValue = %.bf8 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} +// CHECK:STDOUT: %.bf8: %.c99 = cpp_overload_set_value @ReturnConstLValue [concrete = constants.%.bf8] +// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %s.patt: %pattern_type.9be = binding_pattern s [concrete] +// CHECK:STDOUT: %s.var_patt: %pattern_type.9be = var_pattern %s.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s.var: ref %const = var %s.var_patt +// CHECK:STDOUT: %Cpp.ref.loc16_24: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %ReturnConstLValue.ref: %.c99 = name_ref ReturnConstLValue, imports.%.bf8 [concrete = constants.%.bf8] +// CHECK:STDOUT: %ReturnConstLValue.call: init = call imports.%ReturnConstLValue.decl() +// CHECK:STDOUT: assign %s.var, +// CHECK:STDOUT: %.loc16_10: type = splice_block %const [concrete = constants.%const] { +// CHECK:STDOUT: %Cpp.ref.loc16_16: = 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] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s: ref %const = bind_name s, %s.var +// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%const, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc16_3: %type_where = converted constants.%const, %facet_value [concrete = constants.%facet_value] +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.bound: = bound_method %s.var, constants.%DestroyT.as_type.as.Destroy.impl.Op.818 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method: = bound_method %s.var, %DestroyT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr: %ptr.ff5 = addr_of %s.var +// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: