Rework handling of C++ references. (#6268)

For now, map C++ reference types to const-qualified Carbon pointer types
rather than picking between a (non-const) pointer or a value type. This
fixes misbehavior in lowering for reference members in classes and
reference return types.

Update the special-case handling for references as function parameters
so that it continues to map const reference parameters to Carbon
pass-by-value, and unify the code paths for `self` parameters and other
parameters, which were mostly doing the same thing but had some subtle
differences.

Add references to the list of types that we can pass to and from C++
directly, without needing an additional layer of thunks.
This commit is contained in:
Richard Smith
2025-10-28 00:33:26 +00:00
committed by GitHub
parent 33166ffc7a
commit 6011040481
17 changed files with 845 additions and 437 deletions
@@ -183,6 +183,8 @@ fn Call() {
// CHECK:STDOUT: %X.B.cpp_overload_set.type: type = cpp_overload_set_type @X.B.cpp_overload_set [concrete]
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.1f9: type = ptr_type %X [concrete]
// CHECK:STDOUT: %pattern_type.45c: type = pattern_type %ptr.1f9 [concrete]
// CHECK:STDOUT: %pattern_type.46b: type = pattern_type %X [concrete]
// CHECK:STDOUT: %X.B.type: type = fn_type @X.B [concrete]
// CHECK:STDOUT: %X.B: %X.B.type = struct_value () [concrete]
// CHECK:STDOUT: %X.C.cpp_overload_set.type: type = cpp_overload_set_type @X.C.cpp_overload_set [concrete]
@@ -223,8 +225,13 @@ fn Call() {
// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {}
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete = constants.%X.B.cpp_overload_set.value]
// CHECK:STDOUT: %X.B.decl: %X.B.type = fn_decl @X.B [concrete = constants.%X.B] {
// CHECK:STDOUT: %self.patt: %pattern_type.45c = value_binding_pattern self [concrete]
// CHECK:STDOUT: %self.param_patt: %pattern_type.45c = value_param_pattern %self.patt, call_param0 [concrete]
// CHECK:STDOUT: %.loc10: %pattern_type.46b = addr_pattern %self.param_patt [concrete]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: %self.param: %ptr.1f9 = value_param call_param0
// CHECK:STDOUT: %self: %ptr.1f9 = value_binding self, %self.param
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %X.C.cpp_overload_set.value: %X.C.cpp_overload_set.type = cpp_overload_set_value @X.C.cpp_overload_set [concrete = constants.%X.C.cpp_overload_set.value]
@@ -466,6 +473,7 @@ fn Call() {
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.1f9: type = ptr_type %X [concrete]
// CHECK:STDOUT: %pattern_type.45c: type = pattern_type %ptr.1f9 [concrete]
// CHECK:STDOUT: %pattern_type.46b: type = pattern_type %X [concrete]
// CHECK:STDOUT: %B__carbon_thunk.type: type = fn_type @B__carbon_thunk [concrete]
// CHECK:STDOUT: %B__carbon_thunk: %B__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %X.C.cpp_overload_set.type: type = cpp_overload_set_type @X.C.cpp_overload_set [concrete]
@@ -580,13 +588,14 @@ fn Call() {
// CHECK:STDOUT: %B__carbon_thunk.decl: %B__carbon_thunk.type = fn_decl @B__carbon_thunk [concrete = constants.%B__carbon_thunk] {
// CHECK:STDOUT: %this.patt: %pattern_type.45c = value_binding_pattern this [concrete]
// CHECK:STDOUT: %this.param_patt: %pattern_type.45c = value_param_pattern %this.patt, call_param0 [concrete]
// CHECK:STDOUT: %.1: %pattern_type.46b = addr_pattern %this.param_patt [concrete]
// CHECK:STDOUT: %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]
// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %this.param: %ptr.1f9 = value_param call_param0
// CHECK:STDOUT: %this: %ptr.1f9 = value_binding this, %this.param
// CHECK:STDOUT: %a.param: %i32 = value_param call_param1
// CHECK:STDOUT: %.1: type = splice_block %i32 [concrete = constants.%i32] {
// CHECK:STDOUT: %.2: type = splice_block %i32 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }