Reverse interop support for type aliases. (#7043)

Allow any type that has a mapping from Carbon to C++ to be exposed to
C++ via name lookup. This also exposes the logic to export Carbon
classes to C++ to apply during type mapping, which gives very slight
support for passing Carbon types to C++ functions from Carbon, but not
really enough to sensibly test yet.

Depends on #7042.
This commit is contained in:
Richard Smith
2026-04-14 00:18:33 +00:00
committed by GitHub
parent 5b1de7633c
commit 43867a678b
9 changed files with 135 additions and 46 deletions
+51 -17
View File
@@ -28,8 +28,11 @@
#include "llvm/Support/raw_ostream.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/context.h"
#include "toolchain/check/cpp/access.h"
#include "toolchain/check/cpp/export.h"
#include "toolchain/check/cpp/import.h"
#include "toolchain/check/cpp/location.h"
#include "toolchain/check/cpp/type_mapping.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/check/name_lookup.h"
#include "toolchain/check/type_completion.h"
@@ -38,6 +41,7 @@
#include "toolchain/diagnostics/format_providers.h"
#include "toolchain/parse/node_ids.h"
#include "toolchain/sem_ir/cpp_file.h"
#include "toolchain/sem_ir/typed_insts.h"
namespace Carbon::Check {
@@ -340,7 +344,8 @@ class CarbonExternalASTSource : public clang::ExternalASTSource {
// Map a Carbon entity to a Clang NamedDecl. Returns null if the entity cannot
// currently be represented in C++.
auto MapInstIdToClangDecl(LookupResult lookup) -> clang::NamedDecl*;
auto MapInstIdToClangDeclOrType(LookupResult lookup)
-> std::variant<clang::NamedDecl*, clang::QualType>;
// Get a current best-effort location for the current position within C++
// processing.
@@ -374,12 +379,23 @@ void CarbonExternalASTSource::StartTranslationUnit(
BuildCarbonNamespace();
}
auto CarbonExternalASTSource::MapInstIdToClangDecl(LookupResult lookup)
-> clang::NamedDecl* {
auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup)
-> std::variant<clang::NamedDecl*, clang::QualType> {
auto target_inst_id = lookup.scope_result.target_inst_id();
auto target_constant =
context_->constant_values().GetConstantInstId(target_inst_id);
auto target_inst = context_->insts().Get(target_constant);
auto target_const_id = context_->constant_values().Get(target_inst_id);
auto target_inst = context_->constant_values().GetInst(target_const_id);
if (target_inst.type_id() == SemIR::TypeType::TypeId) {
auto type_id =
context_->types().GetTypeIdForTypeConstantId(target_const_id);
auto type = MapToCppType(*context_, type_id);
if (type.isNull()) {
context_->TODO(GetCurrentCppLocId(), "interop with unsupported type");
return nullptr;
}
return type;
}
CARBON_KIND_SWITCH(target_inst) {
case CARBON_KIND(SemIR::Namespace namespace_info): {
auto* decl_context =
@@ -395,12 +411,8 @@ auto CarbonExternalASTSource::MapInstIdToClangDecl(LookupResult lookup)
}
return cast<clang::NamedDecl>(decl_context);
}
case CARBON_KIND(SemIR::ClassType class_type): {
return ExportClassToCpp(*context_, SemIR::LocId(target_inst_id),
target_inst_id, class_type);
}
case SemIR::StructValue::Kind: {
auto callee = GetCallee(context_->sem_ir(), target_constant);
auto callee = GetCallee(context_->sem_ir(), target_inst_id);
auto* callee_function = std::get_if<SemIR::CalleeFunction>(&callee);
if (!callee_function) {
return nullptr;
@@ -490,13 +502,35 @@ auto CarbonExternalASTSource::FindExternalVisibleDeclsByName(
}
// Map the found Carbon entity to a Clang NamedDecl.
auto* clang_decl = MapInstIdToClangDecl(result);
if (!clang_decl) {
return false;
}
CARBON_KIND_SWITCH(MapInstIdToClangDeclOrType(result)) {
case CARBON_KIND(clang::NamedDecl* clang_decl): {
if (clang_decl) {
SetExternalVisibleDeclsForName(decl_context, decl_name, {clang_decl});
return true;
} else {
SetNoExternalVisibleDeclsForName(decl_context, decl_name);
return false;
}
}
SetExternalVisibleDeclsForName(decl_context, decl_name, {clang_decl});
return true;
case CARBON_KIND(clang::QualType type): {
// Create a typedef declaration to model the type result.
// TODO: If the type is a tag type that was declared with this name in
// this context, use the tag decl directly.
auto& ast_context = context_->ast_context();
auto loc = GetCppLocation(
*context_, SemIR::LocId(result.scope_result.target_inst_id()));
auto* typedef_decl = clang::TypedefDecl::Create(
ast_context, const_cast<clang::DeclContext*>(decl_context), loc, loc,
identifier, ast_context.getTrivialTypeSourceInfo(type, loc));
if (isa<clang::CXXRecordDecl>(decl_context)) {
typedef_decl->setAccess(
MapToCppAccess(result.scope_result.access_kind()));
}
SetExternalVisibleDeclsForName(decl_context, decl_name, {typedef_decl});
return true;
}
}
}
auto CarbonExternalASTSource::CompleteType(clang::TagDecl* tag_decl) -> void {