mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Add support for importing C++ namespaces (#5103)
This adds support for having different C++ `NameScope`s (and not just
the main `Cpp` scope), and we keep a pointer to `clang::DeclContext`
these scopes so we can look up C++ names in the right part of the AST.
C++ Interop Demo with a namespace:
```c++
// hello_world.h
namespace some_namespace {
void hello_world();
} // namespace some_namespace
```
```c++
// hello_world.cpp
#include <cstdio>
namespace some_namespace {
void hello_world() { printf("Hello World!\n"); }
} // namespace some_namespace
```
```carbon
// main.carbon
library "Main";
import Cpp library "hello_world.h";
fn Run() -> i32 {
Cpp.some_namespace.hello_world();
return 0;
}
```
```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
Hello World!
```
Closes #5102
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/diagnostics/diagnostic.h"
|
||||
#include "toolchain/diagnostics/format_providers.h"
|
||||
#include "toolchain/parse/node_ids.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/name_scope.h"
|
||||
|
||||
@@ -102,7 +103,7 @@ static auto AddNamespace(Context& context, PackageNameId cpp_package_id,
|
||||
{.node_id = import.node_id, .library_id = import.library_id});
|
||||
}
|
||||
|
||||
return AddImportNamespace(
|
||||
return AddImportNamespaceToScope(
|
||||
context,
|
||||
GetSingletonType(context, SemIR::NamespaceType::SingletonInstId),
|
||||
SemIR::NameId::ForPackageName(cpp_package_id),
|
||||
@@ -112,7 +113,7 @@ static auto AddNamespace(Context& context, PackageNameId cpp_package_id,
|
||||
return AddInst<SemIR::ImportCppDecl>(
|
||||
context, imports.front().node_id, {});
|
||||
})
|
||||
.name_scope_id;
|
||||
.add_result.name_scope_id;
|
||||
}
|
||||
|
||||
auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path,
|
||||
@@ -136,7 +137,8 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path,
|
||||
auto name_scope_id = AddNamespace(context, package_id, imports);
|
||||
SemIR::NameScope& name_scope = context.name_scopes().Get(name_scope_id);
|
||||
name_scope.set_is_closed_import(true);
|
||||
name_scope.set_is_cpp_scope(true);
|
||||
name_scope.set_cpp_decl_context(
|
||||
generated_ast->getASTContext().getTranslationUnitDecl());
|
||||
|
||||
context.sem_ir().set_cpp_ast(generated_ast.get());
|
||||
|
||||
@@ -147,10 +149,10 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path,
|
||||
return std::move(generated_ast);
|
||||
}
|
||||
|
||||
// Look ups the given name in the Clang AST. Returns the lookup result if lookup
|
||||
// was successful.
|
||||
// Look ups the given name in the Clang AST in a specific scope. Returns the
|
||||
// lookup result if lookup was successful.
|
||||
static auto ClangLookup(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::NameId name_id)
|
||||
SemIR::NameScopeId scope_id, SemIR::NameId name_id)
|
||||
-> std::optional<clang::LookupResult> {
|
||||
std::optional<llvm::StringRef> name =
|
||||
context.names().GetAsStringIfIdentifier(name_id);
|
||||
@@ -172,7 +174,7 @@ static auto ClangLookup(Context& context, SemIR::LocId loc_id,
|
||||
clang::Sema::LookupNameKind::LookupOrdinaryName);
|
||||
|
||||
bool found = sema.LookupQualifiedName(
|
||||
lookup, ast->getASTContext().getTranslationUnitDecl());
|
||||
lookup, context.name_scopes().Get(scope_id).cpp_decl_context());
|
||||
|
||||
if (lookup.isClassLookup()) {
|
||||
// TODO: To support class lookup, also return the AccessKind for storage.
|
||||
@@ -250,17 +252,37 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
return decl_id;
|
||||
}
|
||||
|
||||
// Imports a namespace declaration from Clang to Carbon. If successful, returns
|
||||
// the new Carbon namespace declaration `InstId`.
|
||||
static auto ImportNamespaceDecl(Context& context,
|
||||
SemIR::NameScopeId parent_scope_id,
|
||||
SemIR::NameId name_id,
|
||||
clang::NamespaceDecl* clang_decl)
|
||||
-> SemIR::InstId {
|
||||
auto result = AddImportNamespace(
|
||||
context, GetSingletonType(context, SemIR::NamespaceType::SingletonInstId),
|
||||
name_id, parent_scope_id, /*import_id=*/SemIR::InstId::None);
|
||||
context.name_scopes()
|
||||
.Get(result.name_scope_id)
|
||||
.set_cpp_decl_context(clang_decl);
|
||||
return result.inst_id;
|
||||
}
|
||||
|
||||
// Imports a declaration from Clang to Carbon. If successful, returns the
|
||||
// instruction for the new Carbon declaration.
|
||||
static auto ImportNameDecl(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::NameScopeId scope_id, SemIR::NameId name_id,
|
||||
const clang::NamedDecl* clang_decl)
|
||||
-> SemIR::InstId {
|
||||
clang::NamedDecl* clang_decl) -> SemIR::InstId {
|
||||
if (const auto* clang_function_decl =
|
||||
clang::dyn_cast<clang::FunctionDecl>(clang_decl)) {
|
||||
return ImportFunctionDecl(context, loc_id, scope_id, name_id,
|
||||
clang_function_decl);
|
||||
}
|
||||
if (auto* clang_namespace_decl =
|
||||
clang::dyn_cast<clang::NamespaceDecl>(clang_decl)) {
|
||||
return ImportNamespaceDecl(context, scope_id, name_id,
|
||||
clang_namespace_decl);
|
||||
}
|
||||
|
||||
context.TODO(loc_id, llvm::formatv("Unsupported: Declaration type {0}",
|
||||
clang_decl->getDeclKindName())
|
||||
@@ -271,7 +293,7 @@ static auto ImportNameDecl(Context& context, SemIR::LocId loc_id,
|
||||
auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::NameScopeId scope_id, SemIR::NameId name_id)
|
||||
-> SemIR::InstId {
|
||||
auto lookup = ClangLookup(context, loc_id, name_id);
|
||||
auto lookup = ClangLookup(context, loc_id, scope_id, name_id);
|
||||
if (!lookup) {
|
||||
return SemIR::InstId::None;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user