From b42300cfa33d2a47205978db91a539ee174d8907 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 6 Jun 2026 05:07:33 +1000 Subject: [PATCH] Ensure exported entities aren't remapped/duplicated (#7304) This ensures the clang_decls map is used as a cache - without this, visiting the same entity twice could cause it to be re-exported/duplicated. See attached test case. --- toolchain/check/cpp/generate_ast.cpp | 25 ++++++++++++++++--- .../interop/cpp/function/export/alias.carbon | 23 +++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 toolchain/check/testdata/interop/cpp/function/export/alias.carbon diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index 2e21f243dda2..c62c85d75d9e 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -446,15 +446,34 @@ auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup) auto CarbonExternalASTSource::GetOrExportFunctionToCpp( SemIR::InstId target_inst_id, SemIR::FunctionId function_id) -> clang::FunctionDecl* { - const SemIR::Function& function = context_->functions().Get(function_id); + SemIR::Function& function = context_->functions().Get(function_id); auto clang_decl_id = context_->clang_decls().Lookup(function.first_decl_id()); if (clang_decl_id.has_value()) { return cast( context_->clang_decls().Get(clang_decl_id).key.decl); } - return ExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), - function_id); + auto* clang_function_decl = + ExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), function_id); + + if (!clang_function_decl) { + return nullptr; + } + + SemIR::ClangDeclSignature thunk_signature; + thunk_signature.kind = SemIR::ClangDeclSignature::Normal; + thunk_signature.num_params = + static_cast(clang_function_decl->getNumParams()); + thunk_signature.passing_modes.assign( + thunk_signature.num_params, + SemIR::ClangDeclSignature::PassingMode::ByValue); + context_->clang_decls().Add( + {.key = SemIR::ClangDeclKey::ForFunctionDecl( + clang_function_decl, + context_->clang_decl_signatures().Add(std::move(thunk_signature))), + .inst_id = function.first_decl_id()}); + + return clang_function_decl; } auto CarbonExternalASTSource::BuildCarbonNamespace() -> void { diff --git a/toolchain/check/testdata/interop/cpp/function/export/alias.carbon b/toolchain/check/testdata/interop/cpp/function/export/alias.carbon new file mode 100644 index 000000000000..b5c20264835d --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/function/export/alias.carbon @@ -0,0 +1,23 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/export/alias.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/export/alias.carbon + +// --- alias_identical_address.carbon +library "[[@TEST_NAME]]"; + +import Cpp; + +fn F(); +alias G = F; + +inline Cpp ''' +static_assert(&Carbon::F == &Carbon::G); +''';