Files
carbon-lang/toolchain/sem_ir/cpp_domain.h
Richard Smith d08805f1a6 Fix Carbon:: name leakage across files. (#7973)
Split the `Carbon::` namespace into one semantic namespace tree, plus
one separate lookup-only namespace tree per Carbon file. Use the
semantic namespaces as the parents of entities, but use the lookup-only
namespaces when C++ name lookup names a Carbon namespace, in order to
use a different C++ name lookup table in each Carbon file.

Assisted-by: Gemini via Antigravity
2026-10-16 20:59:16 +00:00

106 lines
3.5 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_DOMAIN_H_
#define CARBON_TOOLCHAIN_SEM_IR_CPP_DOMAIN_H_
#include <memory>
#include <utility>
#include "common/check.h"
#include "common/map.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "toolchain/sem_ir/ids.h"
namespace clang {
class CodeGenerator;
class CompilerInstance;
class DeclContext;
class IdentifierInfo;
class Module;
class NamespaceDecl;
class Parser;
} // namespace clang
namespace llvm {
class LLVMContext;
} // namespace llvm
namespace Carbon::SemIR {
// An input Carbon file and its CheckIRId for C++ domain code generation.
struct CppInputFile {
// The ID used to identify this file within SemIR.
CheckIRId check_ir_id;
// The Carbon source filename for this input.
llvm::StringRef filename;
// Whether this input IR will be lowered. If not, we don't need to build a
// Clang CodeGenerator for it.
bool is_lowered;
};
// A C++ compilation domain, including a live Clang instance that can be used to
// parse more code into that domain. May be shared across multiple Carbon files.
class CppDomain {
public:
// A map from parent context and namespace name to semantic namespace, for
// cross-file deduplication of exported packages and namespaces. We use the
// same semantic C++ namespace for the same Carbon package and namespace path
// in every file.
using SemanticNamespacesMap =
Map<std::pair<clang::DeclContext*, clang::IdentifierInfo*>,
clang::NamespaceDecl*>;
explicit CppDomain(std::shared_ptr<clang::CompilerInstance> clang_instance,
std::unique_ptr<clang::Parser> parser,
llvm::ArrayRef<CppInputFile> inputs,
llvm::ArrayRef<clang::CodeGenerator*> code_generators,
llvm::LLVMContext* llvm_context);
~CppDomain();
auto clang_instance() const -> clang::CompilerInstance& {
return *clang_instance_;
}
auto clang_instance_ptr() const -> std::shared_ptr<clang::CompilerInstance> {
return clang_instance_;
}
auto parser() const -> clang::Parser& { return *parser_; }
auto llvm_context() const -> llvm::LLVMContext* { return llvm_context_; }
auto GetCodeGenerator(CheckIRId check_ir_id) const -> clang::CodeGenerator* {
auto res = code_generators_.Lookup(check_ir_id);
CARBON_CHECK(res, "No CodeGenerator found for CheckIRId {0}", check_ir_id);
return res.value();
}
auto file_modules() -> Map<CheckIRId, clang::Module*>& { return modules_; }
auto header_modules() -> llvm::StringMap<clang::Module*>& {
return header_modules_;
}
auto carbon_namespace() const -> clang::NamespaceDecl* {
return carbon_namespace_;
}
auto set_carbon_namespace(clang::NamespaceDecl* carbon_namespace) -> void {
carbon_namespace_ = carbon_namespace;
}
auto semantic_namespaces() -> SemanticNamespacesMap& {
return semantic_namespaces_;
}
private:
std::shared_ptr<clang::CompilerInstance> clang_instance_;
std::unique_ptr<clang::Parser> parser_;
Map<CheckIRId, clang::CodeGenerator*> code_generators_;
Map<CheckIRId, clang::Module*> modules_;
llvm::StringMap<clang::Module*> header_modules_;
clang::NamespaceDecl* carbon_namespace_ = nullptr;
SemanticNamespacesMap semantic_namespaces_;
llvm::LLVMContext* llvm_context_ = nullptr;
};
} // namespace Carbon::SemIR
#endif // CARBON_TOOLCHAIN_SEM_IR_CPP_DOMAIN_H_