From 66f03aecb1cb083f89072fba6bb3e98ae1e38ea9 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 3 Nov 2026 18:28:21 +0000 Subject: [PATCH] Export class friends to C++ (#8068) --- toolchain/check/cpp/generate_ast.cpp | 21 +++++++++++++++ .../interop/cpp/class/export/access.carbon | 27 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index 38538125c63c..e6218f2bc952 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -573,6 +573,27 @@ auto CarbonExternalASTSource::CompleteType(clang::TagDecl* tag_decl) -> void { virtual_fn.method_decl); } } + + // Export friends. + for (auto friend_scope : class_info.friend_scopes.entries()) { + auto friend_inst_id = context_->constant_values().GetInstId(friend_scope); + if (auto friend_class_type = + context_->insts().TryGetAs(friend_inst_id)) { + const auto& friend_class_info = + context_->classes().Get(friend_class_type->class_id); + if (const auto* friend_clang_decl = context_->clang_decls().Lookup( + friend_class_info.first_decl_id())) { + auto* friend_tag_decl = + llvm::cast(friend_clang_decl->decl()); + auto* friend_tsi = context_->ast_context().getTrivialTypeSourceInfo( + context_->ast_context().getCanonicalTagType(friend_tag_decl)); + clang::FriendDecl::Create(context_->ast_context(), class_decl, + /*L=*/clang::SourceLocation(), friend_tsi, + /*FL=*/clang::SourceLocation()); + } + } + // TODO: support other kinds of friends. + } } auto CarbonExternalASTSource::layoutRecordType( diff --git a/toolchain/check/testdata/interop/cpp/class/export/access.carbon b/toolchain/check/testdata/interop/cpp/class/export/access.carbon index 8188086504fc..027faa587480 100644 --- a/toolchain/check/testdata/interop/cpp/class/export/access.carbon +++ b/toolchain/check/testdata/interop/cpp/class/export/access.carbon @@ -106,3 +106,30 @@ void F() { b.F(); } '''; + +// --- access_exported_private_member_of_friend.carbon +library "[[@TEST_NAME]]"; +import Cpp; + +inline Cpp ''' +class C; +'''; + +alias C = Cpp.C; + +class A {} + +class B { + friend C; + fn Make() -> Self { return {}; } + private fn F() {} +} + +inline Cpp ''' +class C { + void G() { + auto b = Carbon::B::Make(); + b.F(); + } +}; +''';