mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 08:54:47 +01:00
C++ interop: Add return reference types support (#6178)
This is a follow up of #6082, which added support for reference types, but not for return types. C++ Interop Demo: ```carbon // main.carbon library "Main"; import Core library "io"; import Cpp inline ''' struct C { auto Inc() -> void { ++x; } int x = 0; }; auto GetC() -> C& { static C c; return c; } '''; fn Run() -> i32 { Core.Print(Cpp.GetC()->x); Cpp.GetC()->Inc(); Core.Print(Cpp.GetC()->x); Cpp.GetC()->Inc(); Core.Print(Cpp.GetC()->x); return 0; } ``` ```shell $ bazel build toolchain:carbon && bazel-bin/toolchain/carbon compile main.carbon && bazel-bin/toolchain/carbon link main.o --output=demo && ./demo 0 1 2 ``` **Without this change**: ```shell main.carbon:19:14: error: semantics TODO: `Unsupported: return type: C &` Core.Print(Cpp.GetC()->x); ^~~~~~~~~~ ``` Part of #6148.
This commit is contained in:
@@ -1446,16 +1446,26 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
|
||||
// TODO: Support more return types.
|
||||
static auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id,
|
||||
clang::FunctionDecl* clang_decl) -> TypeExpr {
|
||||
clang::QualType ret_type = clang_decl->getReturnType();
|
||||
if (!ret_type->isVoidType()) {
|
||||
TypeExpr mapped_type = MapType(context, loc_id, ret_type);
|
||||
if (!mapped_type.inst_id.has_value()) {
|
||||
clang::QualType orig_ret_type = clang_decl->getReturnType();
|
||||
if (!orig_ret_type->isVoidType()) {
|
||||
// We map `T&` return type to `addr param: T*`, and `T&&` parameters to
|
||||
// `param: T`.
|
||||
// TODO: Revisit this and decide what we really want to do here.
|
||||
clang::QualType ret_type = orig_ret_type.getNonReferenceType();
|
||||
|
||||
auto [orig_type_inst_id, type_id] = MapType(context, loc_id, ret_type);
|
||||
if (!orig_type_inst_id.has_value()) {
|
||||
context.TODO(loc_id, llvm::formatv("Unsupported: return type: {0}",
|
||||
ret_type.getAsString()));
|
||||
orig_ret_type.getAsString()));
|
||||
return {.inst_id = SemIR::ErrorInst::TypeInstId,
|
||||
.type_id = SemIR::ErrorInst::TypeId};
|
||||
}
|
||||
return mapped_type;
|
||||
|
||||
if (orig_ret_type->isLValueReferenceType()) {
|
||||
type_id = GetPointerType(context, orig_type_inst_id);
|
||||
}
|
||||
|
||||
return {orig_type_inst_id, type_id};
|
||||
}
|
||||
|
||||
auto* ctor = dyn_cast<clang::CXXConstructorDecl>(clang_decl);
|
||||
|
||||
@@ -241,6 +241,14 @@ static auto GetNonnullType(clang::ASTContext& ast_context,
|
||||
pointer_type, pointer_type);
|
||||
}
|
||||
|
||||
// Given a type, returns the corresponding _Nonnull-qualified pointer type,
|
||||
// ignoring references.
|
||||
static auto GetNonNullablePointerType(clang::ASTContext& ast_context,
|
||||
clang::QualType type) {
|
||||
return GetNonnullType(ast_context,
|
||||
ast_context.getPointerType(type.getNonReferenceType()));
|
||||
}
|
||||
|
||||
// Given the type of a callee parameter, returns the type to use for the
|
||||
// corresponding thunk parameter.
|
||||
static auto GetThunkParameterType(clang::ASTContext& ast_context,
|
||||
@@ -249,8 +257,7 @@ static auto GetThunkParameterType(clang::ASTContext& ast_context,
|
||||
if (IsSimpleAbiType(ast_context, callee_type)) {
|
||||
return callee_type;
|
||||
}
|
||||
return GetNonnullType(ast_context, ast_context.getPointerType(
|
||||
callee_type.getNonReferenceType()));
|
||||
return GetNonNullablePointerType(ast_context, callee_type);
|
||||
}
|
||||
|
||||
// Creates the thunk parameter types given the callee function.
|
||||
@@ -272,9 +279,8 @@ static auto BuildThunkParameterTypes(clang::ASTContext& ast_context,
|
||||
}
|
||||
|
||||
if (!callee_info.has_simple_return_type) {
|
||||
thunk_param_types.push_back(GetNonnullType(
|
||||
ast_context,
|
||||
ast_context.getPointerType(callee_info.effective_return_type)));
|
||||
thunk_param_types.push_back(GetNonNullablePointerType(
|
||||
ast_context, callee_info.effective_return_type));
|
||||
}
|
||||
|
||||
CARBON_CHECK(thunk_param_types.size() == callee_info.num_thunk_params());
|
||||
@@ -524,7 +530,7 @@ static auto BuildThunkBody(clang::Sema& sema,
|
||||
|
||||
auto* return_object_addr = BuildThunkParamRef(
|
||||
sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex());
|
||||
auto return_type = callee_info.effective_return_type;
|
||||
auto return_type = callee_info.effective_return_type.getNonReferenceType();
|
||||
auto* return_type_info =
|
||||
sema.Context.getTrivialTypeSourceInfo(return_type, clang_loc);
|
||||
auto placement_new = sema.BuildCXXNew(
|
||||
|
||||
Reference in New Issue
Block a user