mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +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:
@@ -1391,7 +1391,8 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl)
|
||||
return SemIR::NameId::CppDestructor;
|
||||
}
|
||||
|
||||
case clang::DeclarationName::CXXOperatorName: {
|
||||
case clang::DeclarationName::CXXOperatorName:
|
||||
case clang::DeclarationName::CXXConversionFunctionName: {
|
||||
return SemIR::NameId::CppOperator;
|
||||
}
|
||||
|
||||
@@ -1406,6 +1407,7 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl)
|
||||
// * Have not been imported before.
|
||||
// * Be of supported type (ignoring parameters).
|
||||
static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ImportIRInstId import_ir_inst_id,
|
||||
clang::FunctionDecl* clang_decl, int num_params)
|
||||
-> std::optional<SemIR::FunctionId> {
|
||||
context.scope_stack().PushForDeclName();
|
||||
@@ -1426,7 +1428,8 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
auto function_decl = SemIR::FunctionDecl{
|
||||
SemIR::TypeId::None, SemIR::FunctionId::None, decl_block_id};
|
||||
auto decl_id = AddPlaceholderImportedInstInNoBlock(
|
||||
context, SemIR::LocIdAndInst::NoLoc(function_decl));
|
||||
context,
|
||||
MakeImportedLocIdAndInst(context, import_ir_inst_id, function_decl));
|
||||
|
||||
auto virtual_modifier = SemIR::Function::VirtualModifier::None;
|
||||
int32_t virtual_index = -1;
|
||||
@@ -1506,10 +1509,13 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
|
||||
auto import_ir_inst_id =
|
||||
AddImportIRInst(context.sem_ir(), clang_decl->getLocation());
|
||||
|
||||
CARBON_CHECK(clang_decl->getFunctionType()->isFunctionProtoType(),
|
||||
"Not Prototype function (non-C++ code)");
|
||||
|
||||
auto function_id = ImportFunction(context, loc_id, clang_decl, num_params);
|
||||
auto function_id = ImportFunction(context, loc_id, import_ir_inst_id,
|
||||
clang_decl, num_params);
|
||||
if (!function_id) {
|
||||
MarkFailedDecl(context, key);
|
||||
return SemIR::ErrorInst::InstId;
|
||||
@@ -1526,9 +1532,9 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
if (clang::FunctionDecl* thunk_clang_decl =
|
||||
BuildCppThunk(context, function_info)) {
|
||||
if (auto thunk_function_id =
|
||||
ImportFunction(context, loc_id, thunk_clang_decl,
|
||||
thunk_clang_decl->getNumParams())) {
|
||||
if (auto thunk_function_id = ImportFunction(
|
||||
context, loc_id, import_ir_inst_id, thunk_clang_decl,
|
||||
thunk_clang_decl->getNumParams())) {
|
||||
SemIR::InstId thunk_function_decl_id =
|
||||
context.functions().Get(*thunk_function_id).first_owning_decl_id;
|
||||
function_info.SetHasCppThunk(thunk_function_decl_id);
|
||||
|
||||
Reference in New Issue
Block a user