mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:51:06 +01:00
Add support for using C++ user-defined conversions via interop (#6646)
When performing an implicit conversion to or from a C++ class type, look for a C++ implicit conversion, and if that conversion involves a function call (to a constructor or conversion function), call that function to perform the conversion. Note that this is just a first pass at supporting implicit conversions. There are a lot of other things that can happen in a C++ implicit conversion, such as aggregate initialization or `std::initializer_list` initialization that aren't handled here. In addition, we intentionally leave all standard conversions to Carbon to perform, so that we will reject conversions such as `i32 -> unsigned` that C++ would select but Carbon considers to be invalid. Also support `as` conversions. These are treated analogously, but perform direct-initialization instead of copy-initialization, so they also find `explicit` constructors and conversion functions. In order to give good diagnostics, also track the original C++ source location for imported C++ functions on the imported version of the function. Assisted-by: Gemini 3 Pro via Antigravity
This commit is contained in:
+14
-16
@@ -183,10 +183,9 @@ import Cpp library "definition_single_data_member_value_param_type.h";
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+7]]:11: error: cannot convert expression of type `{}` to `Cpp.S` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: Cpp.foo({} as Cpp.S);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+4]]:11: note: type `{}` does not implement interface `Core.As(Cpp.S)` [MissingImplInMemberAccessNote]
|
||||
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+6]]:11: error: semantics TODO: `Unsupported initialization sequence:
|
||||
// CHECK:STDERR: Normal sequence: list aggregate initialization [struct S]
|
||||
// CHECK:STDERR: ` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo({} as Cpp.S);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
@@ -218,10 +217,9 @@ import Cpp library "definition_multiple_data_members_value_param_type.h";
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+7]]:11: error: cannot convert expression of type `{}` to `Cpp.S` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: Cpp.foo({} as Cpp.S);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+4]]:11: note: type `{}` does not implement interface `Core.As(Cpp.S)` [MissingImplInMemberAccessNote]
|
||||
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+6]]:11: error: semantics TODO: `Unsupported initialization sequence:
|
||||
// CHECK:STDERR: Normal sequence: list aggregate initialization [struct S]
|
||||
// CHECK:STDERR: ` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo({} as Cpp.S);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
@@ -651,12 +649,12 @@ fn F() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Cpp.ref.loc15_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc14_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %.loc15_12: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %.loc14_12: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc14_17: <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: %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %.loc14_14: %S = converted %.loc14_12, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -682,12 +680,12 @@ fn F() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Cpp.ref.loc15_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc14_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %.loc15_12: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %.loc14_12: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc14_17: <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: %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %.loc14_14: %S = converted %.loc14_12, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user