mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Fix mangling collision for C++ class template specializations (#7269)
Carbon-side thunks (for example the `Copy`/`Destroy` witness thunks generated for imported C++ types) are mangled by Carbon, and their names incorporate a fingerprint of the involved types. The instruction fingerprinter identifies a class only by its name and parent scope, which is sufficient for Carbon classes but not for imported C++ classes: different specializations of one class template (and other cases such as types in anonymous namespaces) share a Carbon name and parent scope. As a result, the thunks for two distinct specializations could mangle to the same name, producing a single LLVM function with two definitions and failing `verifyModule` during lowering. When fingerprinting a class imported from C++, also include the Clang mangled name of its type. Test: toolchain/lower/testdata/interop/cpp/thunks.carbon gains a split with two specializations of one class template, each requiring a thunk; their thunks now get distinct mangled names instead of colliding. Assisted-by: Claude Code --------- Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
This commit is contained in:
co-authored by
Christopher Di Bella
parent
3ef128ac91
commit
8a59f2a76b
@@ -8,6 +8,9 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "common/check.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@@ -221,6 +224,32 @@ auto File::set_cpp_file(std::unique_ptr<SemIR::CppFile> cpp_file) -> void {
|
||||
cpp_file_ = std::move(cpp_file);
|
||||
}
|
||||
|
||||
auto File::AppendCppMangledTypeName(ClassId class_id,
|
||||
llvm::raw_ostream& out) const -> bool {
|
||||
// Only classes imported *from* C++ need this. A C++ scope records the Clang
|
||||
// declaration it came from; note that a Carbon class exported *to* C++ also
|
||||
// has an associated Clang declaration, but its scope is not a C++ scope and
|
||||
// it is already uniquely identified by its name and parent scope.
|
||||
auto scope_id = classes().Get(class_id).scope_id;
|
||||
if (!scope_id.has_value()) {
|
||||
return false;
|
||||
}
|
||||
const auto& scope = name_scopes().Get(scope_id);
|
||||
if (!scope.is_cpp_scope()) {
|
||||
return false;
|
||||
}
|
||||
auto clang_decl_id = scope.clang_decl_context_id();
|
||||
if (!clang_decl_id.has_value()) {
|
||||
return false;
|
||||
}
|
||||
// A C++ class's scope always maps to a Clang tag declaration.
|
||||
auto* tag_decl =
|
||||
clang::cast<clang::TagDecl>(clang_decls().Get(clang_decl_id).key.decl);
|
||||
cpp_file_->mangle_context().mangleCanonicalTypeName(
|
||||
cpp_file_->ast_context().getCanonicalTagType(tag_decl), out);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
Reference in New Issue
Block a user