mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
Add a new type, `custom_layout_type`, representing a struct type whose
size, alignment, and field offsets can be manually controlled. Use this
as the object representation type for imported C++ class types (which
also includes struct and union types), allowing us to model C++ class
type layouts. In passing, also add support for incomplete C++ class
types, mapping them into incomplete Carbon class types.
Map C++ fields into Carbon field declarations, allowing direct access to
C++ fields from Carbon. So far, no support is added for base classes nor
anonymous struct or union declarations; those will be added in
subsequent PRs. Also, we don't map C++ access control into Carbon yet,
so all C++ fields are accessible regardless of their access control.
For now we still use a `struct_type` as the object representation for
empty C++ classes, in order to continue to support our existing tests
that convert `{}` to empty C++ class types. This is temporary and should
be removed once we support interop with C++ class initialization.
123 lines
5.4 KiB
C++
123 lines
5.4 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_CHECK_IMPORT_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_IMPORT_H_
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/parse/node_ids.h"
|
|
#include "toolchain/sem_ir/file.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
struct AddImportNamespaceResult {
|
|
// The namespace scope id.
|
|
SemIR::NameScopeId name_scope_id;
|
|
|
|
// The namespace instruction id.
|
|
SemIR::InstId inst_id;
|
|
};
|
|
|
|
// Adds a namespace to the IR. Associates the namespace with the import referred
|
|
// in `import_id`, if any. Do not try to add the namespace `name_id` to the
|
|
// scope and don't check if it already exists. Used when the name is added
|
|
// afterwards.
|
|
auto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id,
|
|
SemIR::NameId name_id,
|
|
SemIR::NameScopeId parent_scope_id,
|
|
SemIR::InstId import_id) -> AddImportNamespaceResult;
|
|
|
|
struct AddImportNamespaceToScopeResult {
|
|
AddImportNamespaceResult add_result;
|
|
|
|
// When trying to add the namespace name, whether it already exists and refers
|
|
// to a namespace.
|
|
bool is_duplicate_of_namespace_in_current_package = false;
|
|
};
|
|
|
|
// Adds a namespace to the IR. Associates the namespace with the import returned
|
|
// from `make_import_id`, which must return a value. Tries to add the namespace
|
|
// `name_id` to the scope. If the name already exists, diagnose only if
|
|
// `diagnose_duplicate_namespace` is true or if it doesn't refer to a namespace.
|
|
// `diagnose_duplicate_namespace` is used when handling a cross-package import,
|
|
// where an existing namespace is in the current package and the new namespace
|
|
// is a different package.
|
|
auto AddImportNamespaceToScope(
|
|
Context& context, SemIR::TypeId namespace_type_id, SemIR::NameId name_id,
|
|
SemIR::NameScopeId parent_scope_id, bool diagnose_duplicate_namespace,
|
|
llvm::function_ref<SemIR::InstId()> make_import_id)
|
|
-> AddImportNamespaceToScopeResult;
|
|
|
|
// Imports the API file's name lookup information into a corresponding
|
|
// implementation file. Only information for the current package will be copied;
|
|
// information for other packages should be handled through
|
|
// ImportLibrariesFromOtherPackage.
|
|
auto ImportApiFile(Context& context, SemIR::TypeId namespace_type_id,
|
|
const SemIR::File& api_sem_ir) -> void;
|
|
|
|
// Add the current package's imports to name lookup. This pulls in all names;
|
|
// conflicts for things such as `package.a.b.c` will be flagged even though they
|
|
// are several layers deep.
|
|
auto ImportLibrariesFromCurrentPackage(
|
|
Context& context, SemIR::TypeId namespace_type_id,
|
|
llvm::ArrayRef<SemIR::ImportIR> import_irs) -> void;
|
|
|
|
// Adds another package's imports to name lookup. This only adds the package
|
|
// name to lookup, so that `package.ImportedPackage` will resolve, and will
|
|
// provide a name scope that can be used for further qualified name lookups.
|
|
//
|
|
// import_irs may be empty. has_load_error is used to indicate if any library in
|
|
// the package failed to import correctly.
|
|
auto ImportLibrariesFromOtherPackage(Context& context,
|
|
SemIR::TypeId namespace_type_id,
|
|
SemIR::InstId import_decl_id,
|
|
PackageNameId package_id,
|
|
llvm::ArrayRef<SemIR::ImportIR> import_irs,
|
|
bool has_load_error) -> void;
|
|
|
|
// Given a name scope that corresponds to another package (having one or more
|
|
// `import_irs`), looks for the name in imports. Name resolution results are
|
|
// added to the scope, and the `InstId` (possibly `None`) is returned.
|
|
//
|
|
// In general, this will add an `ImportRef` and load it; it's never left
|
|
// unloaded because the result is expected to be immediately used. Namespaces
|
|
// will be directly produced, similar to how they function for imports from the
|
|
// current package. Conflicts will be resolved and diagnosed.
|
|
//
|
|
// Arguments are all in the context of the current IR. Scope lookup is expected
|
|
// to be resolved first.
|
|
auto ImportNameFromOtherPackage(
|
|
Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,
|
|
llvm::ArrayRef<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>>
|
|
import_ir_scopes,
|
|
SemIR::NameId name_id) -> SemIR::InstId;
|
|
|
|
namespace Internal {
|
|
|
|
// Checks that the provided imported location has a node kind that is
|
|
// compatible with that of the given instruction.
|
|
auto CheckCompatibleImportedNodeKind(Context& context,
|
|
SemIR::ImportIRInstId imported_loc_id,
|
|
SemIR::InstKind kind) -> void;
|
|
} // namespace Internal
|
|
|
|
// Returns a LocIdAndInst for an instruction with an imported location. Checks
|
|
// that the imported location is compatible with the kind of instruction being
|
|
// created.
|
|
template <typename InstT>
|
|
requires SemIR::Internal::HasNodeId<InstT>
|
|
auto MakeImportedLocIdAndInst(Context& context,
|
|
SemIR::ImportIRInstId imported_loc_id, InstT inst)
|
|
-> SemIR::LocIdAndInst {
|
|
if constexpr (!SemIR::Internal::HasUntypedNodeId<InstT>) {
|
|
Internal::CheckCompatibleImportedNodeKind(context, imported_loc_id,
|
|
InstT::Kind);
|
|
}
|
|
return SemIR::LocIdAndInst::UncheckedLoc(imported_loc_id, inst);
|
|
}
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_IMPORT_H_
|