-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for importing a trivial global C++ function #5033
Changes from 13 commits
9358e9d
afd4441
a1cf815
ddb345b
2ffec0e
b6b93aa
a216d6c
b12945e
b369be6
63701ab
3ec0ec8
29e1548
30881c1
b7e5bc4
0384049
2c59d1d
4cf320d
16867c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -116,16 +116,13 @@ static auto AddNamespace(Context& context, PackageNameId cpp_package_id, | |||||||||||||
} | ||||||||||||||
|
||||||||||||||
auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path, | ||||||||||||||
std::unique_ptr<clang::ASTUnit>* ast, | ||||||||||||||
llvm::ArrayRef<Parse::Tree::PackagingNames> imports, | ||||||||||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs) | ||||||||||||||
-> void { | ||||||||||||||
-> std::unique_ptr<clang::ASTUnit> { | ||||||||||||||
if (imports.empty()) { | ||||||||||||||
return; | ||||||||||||||
return nullptr; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
CARBON_CHECK(ast); | ||||||||||||||
CARBON_CHECK(!ast->get()); | ||||||||||||||
CARBON_CHECK(!context.sem_ir().cpp_ast()); | ||||||||||||||
|
||||||||||||||
auto [generated_ast, ast_has_error] = | ||||||||||||||
|
@@ -141,64 +138,75 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path, | |||||||||||||
name_scope.set_is_closed_import(true); | ||||||||||||||
name_scope.set_is_cpp_scope(true); | ||||||||||||||
|
||||||||||||||
*ast = std::move(generated_ast); | ||||||||||||||
context.sem_ir().set_cpp_ast(ast->get()); | ||||||||||||||
context.sem_ir().set_cpp_ast(generated_ast.get()); | ||||||||||||||
|
||||||||||||||
if (ast_has_error) { | ||||||||||||||
name_scope.set_has_error(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return std::move(generated_ast); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
static auto ClangLookup(Context& context, SemIR::NameId name_id) | ||||||||||||||
// Lookups the given name in the Clang AST. Returns the lookup result if lookup | ||||||||||||||
// was successful. | ||||||||||||||
static auto ClangLookup(Context& context, SemIR::LocId loc_id, | ||||||||||||||
SemIR::NameId name_id) | ||||||||||||||
-> std::optional<clang::LookupResult> { | ||||||||||||||
clang::ASTUnit* ast = context.sem_ir().cpp_ast(); | ||||||||||||||
CARBON_CHECK(ast); | ||||||||||||||
CARBON_CHECK(ast->hasSema()); | ||||||||||||||
clang::Sema& sema = ast->getSema(); | ||||||||||||||
|
||||||||||||||
auto name = context.names().GetAsStringIfIdentifier(name_id); | ||||||||||||||
CARBON_CHECK(name); | ||||||||||||||
llvm::StringRef name = context.names().GetIRBaseName(name_id); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(see comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||||||||
|
||||||||||||||
clang::LookupResult lookup( | ||||||||||||||
sema, | ||||||||||||||
clang::DeclarationNameInfo( | ||||||||||||||
clang::DeclarationName( | ||||||||||||||
sema.getPreprocessor().getIdentifierInfo(*name)), | ||||||||||||||
sema.getPreprocessor().getIdentifierInfo(name)), | ||||||||||||||
clang::SourceLocation()), | ||||||||||||||
clang::Sema::LookupNameKind::LookupOrdinaryName); | ||||||||||||||
|
||||||||||||||
if (!sema.LookupQualifiedName( | ||||||||||||||
lookup, ast->getASTContext().getTranslationUnitDecl())) { | ||||||||||||||
bool found = sema.LookupQualifiedName( | ||||||||||||||
lookup, ast->getASTContext().getTranslationUnitDecl()); | ||||||||||||||
|
||||||||||||||
if (lookup.isClassLookup()) { | ||||||||||||||
// TODO: When support class lookup, also check access. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
To be sure, access can't be checked here; that could lead to something like a (also, small grammar thing -- "to support" or "when supporting") There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||||||||
context.TODO(loc_id, "Unsupported: Lookup in Class"); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe (given the "unsupported" string):
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
if (!found) { | ||||||||||||||
return std::nullopt; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return lookup; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Imports a function declaration from Clang to Carbon. If successful, returns | ||||||||||||||
// the new Carbon function declaration `InstId`. | ||||||||||||||
static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, | ||||||||||||||
SemIR::NameScopeId scope_id, | ||||||||||||||
SemIR::NameId name_id, | ||||||||||||||
const clang::FunctionDecl* clang_decl) | ||||||||||||||
-> SemIR::InstId { | ||||||||||||||
if (clang_decl->isVariadic()) { | ||||||||||||||
context.TODO(loc_id, "Unsupported: Variadic function"); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
if (!clang_decl->isGlobal()) { | ||||||||||||||
context.TODO(loc_id, "Unsupported: Non-global function"); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
if (clang_decl->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate) { | ||||||||||||||
context.TODO(loc_id, "Unsupported: Template function"); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
if (!clang_decl->param_empty()) { | ||||||||||||||
context.TODO(loc_id, "Unsupported: Function with parameters"); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
if (!clang_decl->getReturnType()->isVoidType()) { | ||||||||||||||
context.TODO(loc_id, "Unsupported: Function with non-void return type"); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
auto function_decl = SemIR::FunctionDecl{ | ||||||||||||||
|
@@ -207,25 +215,23 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, | |||||||||||||
context, SemIR::LocIdAndInst(Parse::NodeId::None, function_decl)); | ||||||||||||||
|
||||||||||||||
auto function_info = SemIR::Function{ | ||||||||||||||
SemIR::EntityWithParamsBase{ | ||||||||||||||
.name_id = name_id, | ||||||||||||||
.parent_scope_id = scope_id, | ||||||||||||||
.generic_id = SemIR::GenericId::None, | ||||||||||||||
.first_param_node_id = Parse::NodeId::None, | ||||||||||||||
.last_param_node_id = Parse::NodeId::None, | ||||||||||||||
.pattern_block_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.implicit_param_patterns_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.param_patterns_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.call_params_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.is_extern = false, | ||||||||||||||
.extern_library_id = SemIR::LibraryNameId ::None, | ||||||||||||||
.non_owning_decl_id = SemIR::InstId::None, | ||||||||||||||
.first_owning_decl_id = decl_id, | ||||||||||||||
.definition_id = SemIR::InstId::None}, | ||||||||||||||
SemIR::FunctionFields{ | ||||||||||||||
.return_slot_pattern_id = SemIR::InstId::None, | ||||||||||||||
.virtual_modifier = SemIR::FunctionFields::VirtualModifier::None, | ||||||||||||||
.self_param_id = SemIR::InstId::None}}; | ||||||||||||||
{.name_id = name_id, | ||||||||||||||
.parent_scope_id = scope_id, | ||||||||||||||
.generic_id = SemIR::GenericId::None, | ||||||||||||||
.first_param_node_id = Parse::NodeId::None, | ||||||||||||||
.last_param_node_id = Parse::NodeId::None, | ||||||||||||||
.pattern_block_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.implicit_param_patterns_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.param_patterns_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.call_params_id = SemIR::InstBlockId::Empty, | ||||||||||||||
.is_extern = false, | ||||||||||||||
.extern_library_id = SemIR::LibraryNameId::None, | ||||||||||||||
.non_owning_decl_id = SemIR::InstId::None, | ||||||||||||||
.first_owning_decl_id = decl_id, | ||||||||||||||
.definition_id = SemIR::InstId::None}, | ||||||||||||||
{.return_slot_pattern_id = SemIR::InstId::None, | ||||||||||||||
.virtual_modifier = SemIR::FunctionFields::VirtualModifier::None, | ||||||||||||||
.self_param_id = SemIR::InstId::None}}; | ||||||||||||||
|
||||||||||||||
function_decl.function_id = context.functions().Add(function_info); | ||||||||||||||
|
||||||||||||||
|
@@ -237,6 +243,8 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, | |||||||||||||
return decl_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) | ||||||||||||||
|
@@ -256,7 +264,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, name_id); | ||||||||||||||
auto lookup = ClangLookup(context, loc_id, name_id); | ||||||||||||||
if (!lookup) { | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
} | ||||||||||||||
|
@@ -274,7 +282,7 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id, | |||||||||||||
"find a single result; LookupResultKind: {0}", | ||||||||||||||
lookup->getResultKind()) | ||||||||||||||
.str()); | ||||||||||||||
return SemIR::InstId::None; | ||||||||||||||
return SemIR::ErrorInst::SingletonInstId; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return ImportNameDecl(context, loc_id, scope_id, name_id, | ||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small grammar thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.