mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:10:12 +01:00
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>
90 lines
3.1 KiB
C++
90 lines
3.1 KiB
C++
// 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
|
|
|
|
#ifndef CARBON_TOOLCHAIN_SEM_IR_CPP_FILE_H_
|
|
#define CARBON_TOOLCHAIN_SEM_IR_CPP_FILE_H_
|
|
|
|
#include <memory>
|
|
|
|
#include "clang/AST/Mangle.h"
|
|
#include "clang/Basic/CodeGenOptions.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/CodeGen/ModuleBuilder.h"
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Lex/PreprocessorOptions.h"
|
|
#include "common/check.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
namespace Carbon::SemIR {
|
|
|
|
// The result of compiling the C++ portion of a `File`, including both any
|
|
// imported C++ headers and any inline C++ fragments.
|
|
class CppFile {
|
|
public:
|
|
explicit CppFile(std::unique_ptr<clang::CompilerInstance> clang,
|
|
llvm::LLVMContext* llvm_context)
|
|
: clang_(std::move(clang)), llvm_context_(llvm_context) {}
|
|
|
|
// Access to compilation options.
|
|
auto diagnostic_options() const -> const clang::DiagnosticOptions& {
|
|
return clang_->getDiagnostics().getDiagnosticOptions();
|
|
}
|
|
auto lang_options() const -> const clang::LangOptions& {
|
|
return clang_->getLangOpts();
|
|
}
|
|
|
|
// Access to Clang's compilation environment.
|
|
auto source_manager() -> clang::SourceManager& {
|
|
return clang_->getSourceManager();
|
|
}
|
|
auto source_manager() const -> const clang::SourceManager& {
|
|
return clang_->getSourceManager();
|
|
}
|
|
// TODO: This doesn't really belong here, but is currently used by lowering
|
|
// because Clang's code generation may produce diagnostics.
|
|
auto diagnostics() const -> clang::DiagnosticsEngine& {
|
|
return clang_->getDiagnostics();
|
|
}
|
|
|
|
// Access to layers of Clang's C++ representation.
|
|
auto ast_context() -> clang::ASTContext& { return clang_->getASTContext(); }
|
|
auto ast_context() const -> const clang::ASTContext& {
|
|
return clang_->getASTContext();
|
|
}
|
|
|
|
// Creates the mangle context for this file's C++ AST. Must be called once the
|
|
// AST context is available (after the frontend begins the source file) and
|
|
// before `mangle_context()` is used.
|
|
auto CreateMangleContext() -> void {
|
|
CARBON_CHECK(!mangle_context_);
|
|
mangle_context_.reset(ast_context().createMangleContext());
|
|
}
|
|
auto mangle_context() const -> clang::MangleContext& {
|
|
return *mangle_context_;
|
|
}
|
|
|
|
auto llvm_context() const -> llvm::LLVMContext* { return llvm_context_; }
|
|
auto SetCodeGenerator(clang::CodeGenerator* code_generator) -> void {
|
|
code_generator_ = code_generator;
|
|
}
|
|
auto GetCodeGenerator() const -> clang::CodeGenerator* {
|
|
// Clang code generation should not actually modify the AST, but isn't
|
|
// const-correct.
|
|
return code_generator_;
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<clang::CompilerInstance> clang_;
|
|
llvm::LLVMContext* llvm_context_;
|
|
clang::CodeGenerator* code_generator_ = nullptr;
|
|
// Created by `CreateMangleContext()` once the AST context is available.
|
|
std::unique_ptr<clang::MangleContext> mangle_context_;
|
|
};
|
|
|
|
} // namespace Carbon::SemIR
|
|
|
|
#endif // CARBON_TOOLCHAIN_SEM_IR_CPP_FILE_H_
|