Initial support for interop with class/struct/union fields. (#5849)

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.
This commit is contained in:
Richard Smith
2025-07-25 21:09:24 +00:00
committed by GitHub
parent ef748ab36d
commit 36f0a73092
36 changed files with 1772 additions and 592 deletions
+1
View File
@@ -136,6 +136,7 @@ cc_library(
"//toolchain/sem_ir:file",
"//toolchain/sem_ir:formatter",
"//toolchain/sem_ir:typed_insts",
"@llvm-project//clang:ast",
"@llvm-project//clang:basic",
"@llvm-project//clang:frontend",
"@llvm-project//clang:lex",
+3
View File
@@ -275,6 +275,9 @@ class Context {
auto struct_type_fields() -> SemIR::StructTypeFieldsStore& {
return sem_ir().struct_type_fields();
}
auto custom_layouts() -> SemIR::CustomLayoutStore& {
return sem_ir().custom_layouts();
}
auto types() -> SemIR::TypeStore& { return sem_ir().types(); }
// Instructions should be added with `AddInst` or `AddInstInNoBlock` from
// `inst.h`. This is `const` to prevent accidental misuse.
+4
View File
@@ -574,6 +574,10 @@ static auto ConvertStructToClass(
if (object_repr_id == SemIR::ErrorInst::TypeId) {
return SemIR::ErrorInst::InstId;
}
if (context.types().Is<SemIR::CustomLayoutType>(object_repr_id)) {
// Builtin conversion does not apply.
return value_id;
}
auto dest_struct_type =
context.types().GetAs<SemIR::StructType>(object_repr_id);
+40
View File
@@ -700,4 +700,44 @@ auto ImportNameFromOtherPackage(
return result_id;
}
// Returns whether a parse node associated with an imported instruction of kind
// `imported_kind` is usable as the location of a corresponding local
// instruction of kind `local_kind`.
static auto HasCompatibleImportedNodeKind(SemIR::InstKind imported_kind,
SemIR::InstKind local_kind) -> bool {
if (imported_kind == local_kind) {
return true;
}
if (imported_kind == SemIR::ImportDecl::Kind &&
local_kind == SemIR::Namespace::Kind) {
static_assert(
std::is_convertible_v<decltype(SemIR::ImportDecl::Kind)::TypedNodeId,
decltype(SemIR::Namespace::Kind)::TypedNodeId>);
return true;
}
return false;
}
namespace Internal {
auto CheckCompatibleImportedNodeKind(Context& context,
SemIR::ImportIRInstId imported_loc_id,
SemIR::InstKind kind) -> void {
auto& import_ir_inst = context.import_ir_insts().Get(imported_loc_id);
if (import_ir_inst.ir_id() == SemIR::ImportIRId::Cpp) {
// We don't require a matching node kind if the location is in C++, because
// there isn't a node.
return;
}
const auto* import_ir =
context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;
auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id()).kind();
CARBON_CHECK(
HasCompatibleImportedNodeKind(imported_kind, kind),
"Node of kind {0} created with location of imported node of kind {1}",
kind, imported_kind);
}
} // namespace Internal
} // namespace Carbon::Check
+24
View File
@@ -93,6 +93,30 @@ auto ImportNameFromOtherPackage(
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_
+194 -71
View File
@@ -10,6 +10,8 @@
#include <tuple>
#include <utility>
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -42,6 +44,7 @@
#include "toolchain/parse/node_ids.h"
#include "toolchain/sem_ir/clang_decl.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/name_scope.h"
#include "toolchain/sem_ir/typed_insts.h"
@@ -105,9 +108,9 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
public:
// Creates an instance with the location that triggers calling Clang.
// `context` must not be null.
explicit CarbonClangDiagnosticConsumer(Context* context,
clang::CompilerInvocation* invocation)
: context_(context), invocation_(invocation) {}
explicit CarbonClangDiagnosticConsumer(
Context* context, std::shared_ptr<clang::CompilerInvocation> invocation)
: context_(context), invocation_(std::move(invocation)) {}
// Generates a Carbon warning for each Clang warning and a Carbon error for
// each Clang error or fatal.
@@ -185,7 +188,7 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
Context* context_;
// The compiler invocation that is producing the diagnostics.
clang::CompilerInvocation* invocation_;
std::shared_ptr<clang::CompilerInvocation> invocation_;
// Information on a Clang diagnostic that can be converted to a Carbon
// diagnostic.
@@ -219,11 +222,11 @@ static auto GenerateAst(Context& context,
std::shared_ptr<clang::CompilerInvocation> invocation)
-> std::pair<std::unique_ptr<clang::ASTUnit>, bool> {
// Build a diagnostics engine.
CarbonClangDiagnosticConsumer diagnostics_consumer(&context,
invocation.get());
auto diagnostics_consumer =
std::make_unique<CarbonClangDiagnosticConsumer>(&context, invocation);
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(
clang::CompilerInstance::createDiagnostics(
*fs, invocation->getDiagnosticOpts(), &diagnostics_consumer,
*fs, invocation->getDiagnosticOpts(), diagnostics_consumer.get(),
/*ShouldOwnClient=*/false));
// Extract the input from the frontend invocation and make sure it makes
@@ -247,9 +250,6 @@ static auto GenerateAst(Context& context,
invocation, std::make_shared<clang::PCHContainerOperations>(), nullptr,
diags, new clang::FileManager(invocation->getFileSystemOpts(), fs));
// Remove link to the diagnostics consumer before its destruction.
ast->getDiagnostics().setClient(nullptr);
// Remove remapped file before its underlying storage is destroyed.
invocation->getPreprocessorOpts().clearRemappedFiles();
@@ -259,9 +259,15 @@ static auto GenerateAst(Context& context,
context.sem_ir().set_cpp_ast(ast.get());
// Emit any diagnostics we queued up while building the AST.
diagnostics_consumer.EmitDiagnostics();
diagnostics_consumer->EmitDiagnostics();
bool any_errors = diagnostics_consumer->getNumErrors() > 0;
return {std::move(ast), !ast || diagnostics_consumer.getNumErrors() > 0};
// Transfer ownership of the consumer to the AST unit, in case more
// diagnostics are produced by AST queries.
ast->getDiagnostics().setClient(diagnostics_consumer.release(),
/*ShouldOwnClient=*/true);
return {std::move(ast), !ast || any_errors};
}
// Adds a namespace for the `Cpp` import and returns its `NameScopeId`.
@@ -373,7 +379,10 @@ static auto ClangLookup(Context& context, SemIR::NameScopeId scope_id,
// Returns whether `decl` already mapped to an instruction.
static auto IsClangDeclImported(const Context& context, clang::Decl* decl)
-> bool {
return context.sem_ir().clang_decls().Lookup(decl).has_value();
return context.sem_ir()
.clang_decls()
.Lookup(decl->getCanonicalDecl())
.has_value();
}
// If `decl` already mapped to an instruction, returns that instruction.
@@ -381,7 +390,7 @@ static auto IsClangDeclImported(const Context& context, clang::Decl* decl)
static auto LookupClangDeclInstId(const Context& context, clang::Decl* decl)
-> SemIR::InstId {
const auto& clang_decls = context.sem_ir().clang_decls();
if (auto context_clang_decl_id = clang_decls.Lookup(decl);
if (auto context_clang_decl_id = clang_decls.Lookup(decl->getCanonicalDecl());
context_clang_decl_id.has_value()) {
return clang_decls.Get(context_clang_decl_id).inst_id;
}
@@ -442,22 +451,27 @@ static auto ImportNamespaceDecl(Context& context,
context.name_scopes()
.Get(result.name_scope_id)
.set_clang_decl_context_id(context.sem_ir().clang_decls().Add(
{.decl = clang_decl, .inst_id = result.inst_id}));
{.decl = clang_decl->getCanonicalDecl(), .inst_id = result.inst_id}));
return result.inst_id;
}
static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)
-> TypeExpr;
// Creates a class declaration for the given class name in the given scope.
// Returns the `InstId` for the declaration.
static auto BuildClassDecl(Context& context, SemIR::NameScopeId parent_scope_id,
static auto BuildClassDecl(Context& context,
SemIR::ImportIRInstId import_ir_inst_id,
SemIR::NameScopeId parent_scope_id,
SemIR::NameId name_id)
-> std::tuple<SemIR::ClassId, SemIR::InstId> {
-> std::tuple<SemIR::ClassId, SemIR::TypeInstId> {
// Add the class declaration.
auto class_decl = SemIR::ClassDecl{.type_id = SemIR::TypeType::TypeId,
.class_id = SemIR::ClassId::None,
.decl_block_id = SemIR::InstBlockId::None};
// TODO: Consider setting a proper location.
auto class_decl_id = AddPlaceholderInstInNoBlock(
context, SemIR::LocIdAndInst::NoLoc(class_decl));
context,
SemIR::LocIdAndInst::UncheckedLoc(import_ir_inst_id, class_decl));
context.imports().push_back(class_decl_id);
SemIR::Class class_info = {
@@ -486,76 +500,159 @@ static auto BuildClassDecl(Context& context, SemIR::NameScopeId parent_scope_id,
SetClassSelfType(context, class_decl.class_id);
return {class_decl.class_id, class_decl_id};
return {class_decl.class_id, context.types().GetAsTypeInstId(class_decl_id)};
}
// Checks that the specified finished class definition is valid and builds and
// returns a corresponding complete type witness instruction.
// TODO: Remove recursion into mapping field types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto ImportClassObjectRepr(Context& context,
SemIR::ImportIRInstId import_ir_inst_id,
SemIR::TypeInstId class_type_inst_id,
const clang::CXXRecordDecl* clang_def)
-> SemIR::TypeInstId {
// For now, if the class is empty, produce an empty struct as the object
// representation. This allows our tests to continue to pass while we don't
// properly support initializing imported C++ classes.
// TODO: Remove this.
if (clang_def->isEmpty()) {
return context.types().GetAsTypeInstId(AddInst(
context,
MakeImportedLocIdAndInst(
context, import_ir_inst_id,
SemIR::StructType{.type_id = SemIR::TypeType::TypeId,
.fields_id = SemIR::StructTypeFieldsId::Empty})));
}
const auto& clang_layout =
context.ast_context().getASTRecordLayout(clang_def);
llvm::SmallVector<uint64_t> layout;
llvm::SmallVector<SemIR::StructTypeField> fields;
static_assert(SemIR::CustomLayoutId::SizeIndex == 0);
layout.push_back(clang_layout.getSize().getQuantity());
static_assert(SemIR::CustomLayoutId::AlignIndex == 1);
layout.push_back(clang_layout.getAlignment().getQuantity());
static_assert(SemIR::CustomLayoutId::FirstFieldIndex == 2);
// TODO: Import vptr(s).
// TODO: Import bases.
// Import fields.
for (auto* field : clang_def->fields()) {
if (field->isBitField()) {
// TODO: Add a representation for named bitfield members.
continue;
}
if (field->isAnonymousStructOrUnion()) {
// TODO: Visit IndirectFieldDecls and add them to the layout.
continue;
}
auto field_name_id = AddIdentifierName(context, field->getName());
auto [field_type_inst_id, field_type_id] =
MapType(context, import_ir_inst_id, field->getType());
// Create a field now, as we know the index to use.
// TODO: Consider doing this lazily instead.
auto field_decl_id = AddInst(
context, MakeImportedLocIdAndInst(
context, import_ir_inst_id,
SemIR::FieldDecl{
.type_id = GetUnboundElementType(
context, class_type_inst_id, field_type_inst_id),
.name_id = field_name_id,
.index = SemIR::ElementIndex(fields.size())}));
context.sem_ir().clang_decls().Add(
{.decl = field->getCanonicalDecl(), .inst_id = field_decl_id});
layout.push_back(context.ast_context()
.toCharUnitsFromBits(clang_layout.getFieldOffset(
field->getFieldIndex()))
.getQuantity());
fields.push_back(
{.name_id = field_name_id, .type_inst_id = field_type_inst_id});
}
// TODO: Add a field to prevent tail padding reuse if necessary.
return AddTypeInst<SemIR::CustomLayoutType>(
context, import_ir_inst_id,
{.type_id = SemIR::TypeType::TypeId,
.fields_id = context.struct_type_fields().Add(fields),
.layout_id = context.custom_layouts().Add(layout)});
}
// Creates a class definition based on the information in the given Clang
// declaration, which is assumed to be for a class definition. Returns the new
// class id and instruction id.
// declaration, which is assumed to be for a class definition.
// TODO: Remove recursion into mapping field types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto BuildClassDefinition(Context& context,
clang::CXXRecordDecl* clang_decl)
-> std::tuple<SemIR::ClassId, SemIR::InstId> {
auto [class_id, class_inst_id] =
BuildClassDecl(context, GetParentNameScopeId(context, clang_decl),
AddIdentifierName(context, clang_decl->getName()));
SemIR::ImportIRInstId import_ir_inst_id,
SemIR::ClassId class_id,
SemIR::TypeInstId class_inst_id,
SemIR::ClangDeclId clang_decl_id,
clang::CXXRecordDecl* clang_def) -> void {
auto& class_info = context.classes().Get(class_id);
StartClassDefinition(context, class_info, class_inst_id);
// Name lookup into the Carbon class looks in the C++ class definition.
context.name_scopes()
.Get(class_info.scope_id)
.set_clang_decl_context_id(context.sem_ir().clang_decls().Add(
{.decl = clang_decl, .inst_id = class_inst_id}));
.set_clang_decl_context_id(clang_decl_id);
return {class_id, class_inst_id};
context.inst_block_stack().Push();
// Compute the class's object representation.
auto object_repr_id = ImportClassObjectRepr(context, import_ir_inst_id,
class_inst_id, clang_def);
class_info.complete_type_witness_id = AddInst<SemIR::CompleteTypeWitness>(
context, import_ir_inst_id,
{.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
.object_repr_type_inst_id = object_repr_id});
class_info.body_block_id = context.inst_block_stack().Pop();
}
// Mark the given `Decl` as failed in `clang_decls`.
static auto MarkFailedDecl(Context& context, clang::Decl* clang_decl) {
context.sem_ir().clang_decls().Add(
{.decl = clang_decl, .inst_id = SemIR::ErrorInst::InstId});
context.sem_ir().clang_decls().Add({.decl = clang_decl->getCanonicalDecl(),
.inst_id = SemIR::ErrorInst::InstId});
}
// Imports a record declaration from Clang to Carbon. If successful, returns
// the new Carbon class declaration `InstId`.
// TODO: Change `clang_decl` to `const &` when lookup is using `clang::DeclID`
// and we don't need to store the decl for lookup context.
static auto ImportCXXRecordDecl(Context& context, SemIR::LocId loc_id,
// TODO: Remove recursion into mapping field types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto ImportCXXRecordDecl(Context& context,
clang::CXXRecordDecl* clang_decl)
-> SemIR::InstId {
clang::CXXRecordDecl* clang_def = clang_decl->getDefinition();
if (!clang_def) {
context.TODO(loc_id,
"Unsupported: Record declarations without a definition");
MarkFailedDecl(context, clang_decl);
return SemIR::ErrorInst::InstId;
if (clang_def) {
clang_decl = clang_def;
}
auto import_ir_inst_id = AddImportIRInst(context, clang_decl->getLocation());
auto [class_id, class_inst_id] = BuildClassDecl(
context, import_ir_inst_id, GetParentNameScopeId(context, clang_decl),
AddIdentifierName(context, clang_decl->getName()));
// TODO: The caller does the same lookup. Avoid doing it twice.
auto clang_decl_id = context.sem_ir().clang_decls().Add(
{.decl = clang_decl->getCanonicalDecl(), .inst_id = class_inst_id});
if (clang_def) {
BuildClassDefinition(context, import_ir_inst_id, class_id, class_inst_id,
clang_decl_id, clang_def);
}
if (clang_def->isDynamicClass()) {
context.TODO(loc_id, "Unsupported: Dynamic Class");
MarkFailedDecl(context, clang_decl);
return SemIR::ErrorInst::InstId;
}
if (clang_def->isUnion() && !clang_def->fields().empty()) {
context.TODO(loc_id, "Unsupported: Non-empty union");
MarkFailedDecl(context, clang_decl);
return SemIR::ErrorInst::InstId;
}
auto [class_id, class_def_id] = BuildClassDefinition(context, clang_def);
// The class type is now fully defined. Compute its object representation.
ComputeClassObjectRepr(context,
// TODO: Consider having a proper location here.
Parse::ClassDefinitionId::None, class_id,
// TODO: Set fields.
/*field_decls=*/{},
// TODO: Set vtable.
/*vtable_contents=*/{},
// TODO: Set block.
/*body=*/{});
return class_def_id;
return class_inst_id;
}
// Creates an integer type of the given size.
@@ -587,8 +684,10 @@ static auto MapBuiltinType(Context& context, clang::QualType qual_type,
// Maps a C++ record type to a Carbon type.
// TODO: Support more record types.
static auto MapRecordType(Context& context, SemIR::LocId loc_id,
const clang::RecordType& type) -> TypeExpr {
// TODO: Remove recursion mapping fields of class types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto MapRecordType(Context& context, const clang::RecordType& type)
-> TypeExpr {
auto* record_decl = clang::dyn_cast<clang::CXXRecordDecl>(type.getDecl());
if (!record_decl) {
return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
@@ -597,7 +696,7 @@ static auto MapRecordType(Context& context, SemIR::LocId loc_id,
// Check if the declaration is already mapped.
SemIR::InstId record_inst_id = LookupClangDeclInstId(context, record_decl);
if (!record_inst_id.has_value()) {
record_inst_id = ImportCXXRecordDecl(context, loc_id, record_decl);
record_inst_id = ImportCXXRecordDecl(context, record_decl);
}
SemIR::TypeInstId record_type_inst_id =
context.types().GetAsTypeInstId(record_inst_id);
@@ -609,14 +708,16 @@ static auto MapRecordType(Context& context, SemIR::LocId loc_id,
// Maps a C++ type that is not a wrapper type such as a pointer to a Carbon
// type.
// TODO: Support more types.
static auto MapNonWrapperType(Context& context, SemIR::LocId loc_id,
clang::QualType type) -> TypeExpr {
// TODO: Remove recursion mapping fields of class types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto MapNonWrapperType(Context& context, clang::QualType type)
-> TypeExpr {
if (const auto* builtin_type = type->getAs<clang::BuiltinType>()) {
return MapBuiltinType(context, type, *builtin_type);
}
if (const auto* record_type = type->getAs<clang::RecordType>()) {
return MapRecordType(context, loc_id, *record_type);
return MapRecordType(context, *record_type);
}
CARBON_CHECK(!type.hasQualifiers() && !type->isPointerType(),
@@ -673,6 +774,8 @@ static auto MapPointerType(Context& context, SemIR::LocId loc_id,
// Maps a C++ type to a Carbon type. `type` should not be canonicalized because
// we check for pointer nullability and nullability will be lost by
// canonicalization.
// TODO: Remove recursion mapping fields of class types.
// NOLINTNEXTLINE(misc-no-recursion)
static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)
-> TypeExpr {
// Unwrap any type modifiers and wrappers.
@@ -689,7 +792,7 @@ static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)
wrapper_types.push_back(orig_type);
}
auto mapped = MapNonWrapperType(context, loc_id, type);
auto mapped = MapNonWrapperType(context, type);
for (auto wrapper : llvm::reverse(wrapper_types)) {
if (!mapped.inst_id.has_value() ||
@@ -961,6 +1064,7 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
MarkFailedDecl(context, clang_decl);
return SemIR::ErrorInst::InstId;
}
if (clang_decl->getTemplatedKind() ==
clang::FunctionDecl::TK_FunctionTemplate) {
context.TODO(loc_id, "Unsupported: Template function");
@@ -968,6 +1072,14 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
return SemIR::ErrorInst::InstId;
}
if (auto* method_decl = dyn_cast<clang::CXXMethodDecl>(clang_decl)) {
if (method_decl->isVirtual()) {
context.TODO(loc_id, "Unsupported: Virtual function");
MarkFailedDecl(context, clang_decl);
return SemIR::ErrorInst::InstId;
}
}
context.scope_stack().PushForDeclName();
context.inst_block_stack().Push();
context.pattern_block_stack().Push();
@@ -1047,6 +1159,7 @@ static auto GetDependentUnimportedTypeDecls(const Context& context,
if (!IsClangDeclImported(context, record_decl)) {
return {record_decl};
}
// TODO: Also collect field types.
}
}
@@ -1115,6 +1228,16 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id,
}
return type_inst_id;
}
if (clang::isa<clang::FieldDecl>(clang_decl)) {
// Usable fields get imported as a side effect of importing the class.
if (SemIR::InstId existing_inst_id =
LookupClangDeclInstId(context, clang_decl);
existing_inst_id.has_value()) {
return existing_inst_id;
}
context.TODO(loc_id, "Unsupported: Unhandled kind of field declaration");
return SemIR::InstId::None;
}
context.TODO(loc_id, llvm::formatv("Unsupported: Declaration type {0}",
clang_decl->getDeclKindName())
+1 -35
View File
@@ -15,6 +15,7 @@
#include "toolchain/check/context.h"
#include "toolchain/check/eval.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/import.h"
#include "toolchain/check/inst.h"
#include "toolchain/check/name_lookup.h"
#include "toolchain/check/type.h"
@@ -3440,39 +3441,4 @@ auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id,
.first_decl_id());
}
// Returns whether a parse node associated with an imported instruction of kind
// `imported_kind` is usable as the location of a corresponding local
// instruction of kind `local_kind`.
static auto HasCompatibleImportedNodeKind(SemIR::InstKind imported_kind,
SemIR::InstKind local_kind) -> bool {
if (imported_kind == local_kind) {
return true;
}
if (imported_kind == SemIR::ImportDecl::Kind &&
local_kind == SemIR::Namespace::Kind) {
static_assert(
std::is_convertible_v<decltype(SemIR::ImportDecl::Kind)::TypedNodeId,
decltype(SemIR::Namespace::Kind)::TypedNodeId>);
return true;
}
return false;
}
namespace Internal {
auto CheckCompatibleImportedNodeKind(Context& context,
SemIR::ImportIRInstId imported_loc_id,
SemIR::InstKind kind) -> void {
auto& import_ir_inst = context.import_ir_insts().Get(imported_loc_id);
const auto* import_ir =
context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;
auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id()).kind();
CARBON_CHECK(
HasCompatibleImportedNodeKind(imported_kind, kind),
"Node of kind {0} created with location of imported node of kind {1}",
kind, imported_kind);
}
} // namespace Internal
} // namespace Carbon::Check
-24
View File
@@ -52,30 +52,6 @@ auto ImportImplsFromApiFile(Context& context) -> void;
auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id,
SemIR::ImplId impl_id) -> void;
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_REF_H_
+66 -74
View File
@@ -18,23 +18,32 @@
class Bar;
// --- fail_todo_import_declaration.carbon
// --- import_declaration.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+7]]:13: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// --- fail_use_declaration_as_definition.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
fn MyF() {
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE+6]]:12: error: binding pattern has incomplete type `Bar` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: var bar: Cpp.Bar;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./declaration.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
var bar: Cpp.Bar;
}
// ============================================================================
// Definition
// ============================================================================
@@ -158,28 +167,17 @@ fn MyF() {
class Bar {
public:
Bar* foo;
Bar* _Nonnull foo;
};
// --- fail_todo_import_public_data_member.carbon
// --- import_public_data_member.carbon
library "[[@TEST_NAME]]";
import Cpp library "public_static_data_member.h";
import Cpp library "public_data_member.h";
//@dump-sem-ir-begin
fn MyF(bar : Cpp.Bar*) {
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+11]]:27: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+8]]:27: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+4]]:27: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
let foo_bar: Cpp.Bar* = bar->foo;
}
//@dump-sem-ir-end
@@ -230,7 +228,7 @@ library "[[@TEST_NAME]]";
import Cpp library "inheritance_pointers.h";
//@dump-sem-ir-begin
fn MyF1(bar : Cpp.Bar1*);
fn MyF1(bar: Cpp.Bar1*);
// TODO: Support C++ inheritance.
// CHECK:STDERR: fail_todo_import_inheritance_pointers.carbon:[[@LINE+10]]:33: error: cannot implicitly convert expression of type `Cpp.Bar2*` to `Cpp.Bar1*` [ConversionFailure]
// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
@@ -239,8 +237,8 @@ fn MyF1(bar : Cpp.Bar1*);
// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
// CHECK:STDERR: ^~~
// CHECK:STDERR: fail_todo_import_inheritance_pointers.carbon:[[@LINE-8]]:9: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR: fn MyF1(bar : Cpp.Bar1*);
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR: fn MyF1(bar: Cpp.Bar1*);
// CHECK:STDERR: ^~~~~~~~~~~~~~
// CHECK:STDERR:
fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
//@dump-sem-ir-end
@@ -256,21 +254,14 @@ class Bar {
virtual ~Bar();
};
// --- fail_todo_import_dynamic.carbon
// --- import_dynamic.carbon
library "[[@TEST_NAME]]";
import Cpp library "dynamic.h";
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_dynamic.carbon:[[@LINE+7]]:14: error: semantics TODO: `Unsupported: Dynamic Class` [SemanticsTodo]
// CHECK:STDERR: fn MyF(bar : Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_dynamic.carbon:[[@LINE+4]]:14: note: in `Cpp` name lookup for `Bar` [InCppNameLookup]
// CHECK:STDERR: fn MyF(bar : Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn MyF(bar : Cpp.Bar*);
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// ============================================================================
@@ -355,36 +346,40 @@ import Cpp library "template.h";
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// CHECK:STDOUT: --- fail_todo_import_declaration.carbon
// CHECK:STDOUT: --- import_declaration.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = <error>
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: <error> = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: <error> = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: <error> = value_param call_param0
// CHECK:STDOUT: %.loc14: type = splice_block %ptr [concrete = <error>] {
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: <error> = name_ref Bar, <error> [concrete = <error>]
// CHECK:STDOUT: %ptr: type = ptr_type <error> [concrete = <error>]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: <error> = bind_name bar, %bar.param
// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: <error>);
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr);
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition.carbon
// CHECK:STDOUT:
@@ -412,7 +407,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -448,7 +442,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -479,7 +472,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %foo.ref: %Bar.foo.type = name_ref foo, imports.%Bar.foo.decl [concrete = constants.%Bar.foo]
// CHECK:STDOUT: %Bar.foo.call: init %empty_tuple.type = call %foo.ref()
@@ -512,7 +504,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19_12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -520,11 +511,12 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_public_data_member.carbon
// CHECK:STDOUT: --- import_public_data_member.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %Bar.elem: type = unbound_element_type %Bar, %ptr.f68 [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.f68 [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
@@ -546,7 +538,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr.loc7 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc7: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc7: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc7: type = ptr_type %Bar.ref.loc7 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -560,14 +551,16 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo_bar.patt: %pattern_type = binding_pattern foo_bar [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar
// CHECK:STDOUT: %.loc19_30: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19_23: type = splice_block %ptr.loc19 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc19: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc19: type = ptr_type %Bar.ref.loc19 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: %.loc8_30.1: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: %Bar.elem = name_ref foo, @Bar.%.1 [concrete = @Bar.%.1]
// CHECK:STDOUT: %.loc8_30.2: ref %ptr.f68 = class_element_access %.loc8_30.1, element0
// CHECK:STDOUT: %.loc8_23: type = splice_block %ptr.loc8 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc8: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc8: type = ptr_type %Bar.ref.loc8 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc8_30.3: %ptr.f68 = bind_value %.loc8_30.2
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, %.loc8_30.3
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -598,12 +591,10 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, imports.%Bar1.decl [concrete = constants.%Bar1]
// CHECK:STDOUT: %foo1.ref.loc8: %Bar1.foo1.type = name_ref foo1, imports.%Bar1.foo1.decl [concrete = constants.%Bar1.foo1]
// CHECK:STDOUT: %Bar1.foo1.call.loc8: init %empty_tuple.type = call %foo1.ref.loc8()
// CHECK:STDOUT: %Cpp.ref.loc9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar2.ref.loc9: type = name_ref Bar2, imports.%Bar2.decl [concrete = constants.%Bar2]
// CHECK:STDOUT: %foo1.ref.loc9: %Bar1.foo1.type = name_ref foo1, imports.%Bar1.foo1.decl [concrete = constants.%Bar1.foo1]
// CHECK:STDOUT: %Bar1.foo1.call.loc9: init %empty_tuple.type = call %foo1.ref.loc9()
@@ -648,7 +639,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, imports.%Bar1.decl [concrete = constants.%Bar1]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar1.ref [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -661,7 +651,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.eca = value_param call_param0
// CHECK:STDOUT: %.loc19_23: type = splice_block %ptr [concrete = constants.%ptr.eca] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar2.ref: type = name_ref Bar2, imports.%Bar2.decl [concrete = constants.%Bar2]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar2.ref [concrete = constants.%ptr.eca]
// CHECK:STDOUT: }
@@ -680,36 +669,40 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_dynamic.carbon
// CHECK:STDOUT: --- import_dynamic.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = <error>
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: <error> = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: <error> = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: <error> = value_param call_param0
// CHECK:STDOUT: %.loc14: type = splice_block %ptr [concrete = <error>] {
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: <error> = name_ref Bar, <error> [concrete = <error>]
// CHECK:STDOUT: %ptr: type = ptr_type <error> [concrete = <error>]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: <error> = bind_name bar, %bar.param
// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: <error>);
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr);
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_to_inherit_public.carbon
// CHECK:STDOUT:
@@ -742,12 +735,11 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT:
// CHECK:STDOUT: class @Derived {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %.loc8: %Derived.elem = base_decl %Bar.ref, element0 [concrete]
// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %Bar} [concrete = constants.%struct_type.base.36d]
// CHECK:STDOUT: %complete_type.loc9: <witness> = complete_type_witness %struct_type.base [concrete = constants.%complete_type.fff]
// CHECK:STDOUT: complete_type_witness = %complete_type.loc9
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %struct_type.base [concrete = constants.%complete_type.fff]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
+670
View File
@@ -0,0 +1,670 @@
// 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
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
// EXTRA-ARGS: --dump-sem-ir-ranges=ignore
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/class/field.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/class/field.carbon
// --- struct.h
struct Struct {
int a;
int b;
int* _Nonnull p;
};
// --- use_struct_fields.carbon
library "[[@TEST_NAME]]";
import Cpp library "struct.h";
fn F(s: Cpp.Struct) -> (i32, i32, i32) {
//@dump-sem-ir-begin
return (s.a, s.b, *s.p);
//@dump-sem-ir-end
}
// --- union.h
union Union {
int a;
int b;
int* _Nonnull p;
};
// --- use_union_fields.carbon
library "[[@TEST_NAME]]";
import Cpp library "union.h";
fn F(u: Cpp.Union) -> i32 {
//@dump-sem-ir-begin
return u.a;
//@dump-sem-ir-end
}
fn G(u: Cpp.Union) -> i32 {
//@dump-sem-ir-begin
return u.b;
//@dump-sem-ir-end
}
fn H(u: Cpp.Union) -> i32 {
//@dump-sem-ir-begin
return *u.p;
//@dump-sem-ir-end
}
// --- with_bitfields.h
struct Struct {
int a;
int b : 2;
};
union Union {
int c;
int d : 3;
};
// --- use_non_bitfields_in_type_with_bitfields.carbon
library "[[@TEST_NAME]]";
import Cpp library "with_bitfields.h";
fn F(s: Cpp.Struct) -> i32 {
//@dump-sem-ir-begin
return s.a;
//@dump-sem-ir-end
}
fn G(s: Cpp.Union) -> i32 {
//@dump-sem-ir-begin
return s.c;
//@dump-sem-ir-end
}
// --- fail_todo_use_bitfields.carbon
library "[[@TEST_NAME]]";
import Cpp library "with_bitfields.h";
fn F(s: Cpp.Struct) -> i32 {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Unhandled kind of field declaration` [SemanticsTodo]
// CHECK:STDERR: return s.b;
// CHECK:STDERR: ^~~
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `b` [InCppNameLookup]
// CHECK:STDERR: return s.b;
// CHECK:STDERR: ^~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: error: member name `b` not found in `Cpp.Struct` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: return s.b;
// CHECK:STDERR: ^~~
// CHECK:STDERR:
return s.b;
//@dump-sem-ir-end
}
fn G(s: Cpp.Union) -> i32 {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Unhandled kind of field declaration` [SemanticsTodo]
// CHECK:STDERR: return s.d;
// CHECK:STDERR: ^~~
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `d` [InCppNameLookup]
// CHECK:STDERR: return s.d;
// CHECK:STDERR: ^~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: error: member name `d` not found in `Cpp.Union` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: return s.d;
// CHECK:STDERR: ^~~
// CHECK:STDERR:
return s.d;
//@dump-sem-ir-end
}
// CHECK:STDOUT: --- use_struct_fields.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Struct: type = class_type @Struct [concrete]
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete]
// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %Struct.elem.86b: type = unbound_element_type %Struct, %i32 [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %Struct.elem.765: type = unbound_element_type %Struct, %ptr.235 [concrete]
// CHECK:STDOUT: %.550: type = custom_layout_type {size=16, align=8, .a@0: %i32, .b@4: %i32, .p@8: %ptr.235} [concrete]
// CHECK:STDOUT: %complete_type.8cf: <witness> = complete_type_witness %.550 [concrete]
// CHECK:STDOUT: %pattern_type.60c: type = pattern_type %Struct [concrete]
// CHECK:STDOUT: %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]
// CHECK:STDOUT: %tuple.type.189: type = tuple_type (%i32, %i32, %i32) [concrete]
// CHECK:STDOUT: %pattern_type.b5a: type = pattern_type %tuple.type.189 [concrete]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Struct = %Struct.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Struct.decl: type = class_decl @Struct [concrete = constants.%Struct] {} {}
// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Cpp = imports.%Cpp
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Cpp.import_cpp = import_cpp {
// CHECK:STDOUT: import Cpp "struct.h"
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %s.patt: %pattern_type.60c = binding_pattern s [concrete]
// CHECK:STDOUT: %s.param_patt: %pattern_type.60c = value_param_pattern %s.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.b5a = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.b5a = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc6_25: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc6_25: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc6_30: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc6_30: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc6_35: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc6_35: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc6_38.1: %tuple.type.ff9 = tuple_literal (%i32.loc6_25, %i32.loc6_30, %i32.loc6_35)
// CHECK:STDOUT: %.loc6_38.2: type = converted %.loc6_38.1, constants.%tuple.type.189 [concrete = constants.%tuple.type.189]
// CHECK:STDOUT: %s.param: %Struct = value_param call_param0
// CHECK:STDOUT: %.loc6_12: type = splice_block %Struct.ref [concrete = constants.%Struct] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Struct.ref: type = name_ref Struct, imports.%Struct.decl [concrete = constants.%Struct]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: %Struct = bind_name s, %s.param
// CHECK:STDOUT: %return.param: ref %tuple.type.189 = out_param call_param1
// CHECK:STDOUT: %return: ref %tuple.type.189 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Struct {
// CHECK:STDOUT: %int_32.1: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Struct.elem.86b = field_decl a, element0 [concrete]
// CHECK:STDOUT: %int_32.2: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.2: %Struct.elem.86b = field_decl b, element1 [concrete]
// CHECK:STDOUT: %int_32.3: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.3: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.3: %Struct.elem.765 = field_decl p, element2 [concrete]
// CHECK:STDOUT: %.4: type = custom_layout_type {size=16, align=8, .a@0: %i32, .b@4: %i32, .p@8: %ptr.235} [concrete = constants.%.550]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.4 [concrete = constants.%complete_type.8cf]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Struct
// CHECK:STDOUT: .a = %.1
// CHECK:STDOUT: .b = %.2
// CHECK:STDOUT: .p = %.3
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%s.param: %Struct) -> %return.param: %tuple.type.189 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %s.ref.loc8_11: %Struct = name_ref s, %s
// CHECK:STDOUT: %a.ref: %Struct.elem.86b = name_ref a, @Struct.%.1 [concrete = @Struct.%.1]
// CHECK:STDOUT: %.loc8_12.1: ref %i32 = class_element_access %s.ref.loc8_11, element0
// CHECK:STDOUT: %.loc8_12.2: %i32 = bind_value %.loc8_12.1
// CHECK:STDOUT: %s.ref.loc8_16: %Struct = name_ref s, %s
// CHECK:STDOUT: %b.ref: %Struct.elem.86b = name_ref b, @Struct.%.2 [concrete = @Struct.%.2]
// CHECK:STDOUT: %.loc8_17.1: ref %i32 = class_element_access %s.ref.loc8_16, element1
// CHECK:STDOUT: %.loc8_17.2: %i32 = bind_value %.loc8_17.1
// CHECK:STDOUT: %s.ref.loc8_22: %Struct = name_ref s, %s
// CHECK:STDOUT: %p.ref: %Struct.elem.765 = name_ref p, @Struct.%.3 [concrete = @Struct.%.3]
// CHECK:STDOUT: %.loc8_23.1: ref %ptr.235 = class_element_access %s.ref.loc8_22, element2
// CHECK:STDOUT: %.loc8_23.2: %ptr.235 = bind_value %.loc8_23.1
// CHECK:STDOUT: %.loc8_21.1: ref %i32 = deref %.loc8_23.2
// CHECK:STDOUT: %.loc8_25.1: %tuple.type.189 = tuple_literal (%.loc8_12.2, %.loc8_17.2, %.loc8_21.1)
// CHECK:STDOUT: %tuple.elem0: ref %i32 = tuple_access %return, element0
// CHECK:STDOUT: %.loc8_25.2: init %i32 = initialize_from %.loc8_12.2 to %tuple.elem0
// CHECK:STDOUT: %tuple.elem1: ref %i32 = tuple_access %return, element1
// CHECK:STDOUT: %.loc8_25.3: init %i32 = initialize_from %.loc8_17.2 to %tuple.elem1
// CHECK:STDOUT: %.loc8_21.2: %i32 = bind_value %.loc8_21.1
// CHECK:STDOUT: %tuple.elem2: ref %i32 = tuple_access %return, element2
// CHECK:STDOUT: %.loc8_25.4: init %i32 = initialize_from %.loc8_21.2 to %tuple.elem2
// CHECK:STDOUT: %.loc8_25.5: init %tuple.type.189 = tuple_init (%.loc8_25.2, %.loc8_25.3, %.loc8_25.4) to %return
// CHECK:STDOUT: %.loc8_26: init %tuple.type.189 = converted %.loc8_25.1, %.loc8_25.5
// CHECK:STDOUT: return %.loc8_26 to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_union_fields.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Union: type = class_type @Union [concrete]
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete]
// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %Union.elem.041: type = unbound_element_type %Union, %i32 [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %Union.elem.92a: type = unbound_element_type %Union, %ptr.235 [concrete]
// CHECK:STDOUT: %.c84: type = custom_layout_type {size=8, align=8, .a@0: %i32, .b@0: %i32, .p@0: %ptr.235} [concrete]
// CHECK:STDOUT: %complete_type.1b0: <witness> = complete_type_witness %.c84 [concrete]
// CHECK:STDOUT: %pattern_type.a90: type = pattern_type %Union [concrete]
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %H.type: type = fn_type @H [concrete]
// CHECK:STDOUT: %H: %H.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Union = %Union.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Union.decl: type = class_decl @Union [concrete = constants.%Union] {} {}
// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Cpp = imports.%Cpp
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .G = %G.decl
// CHECK:STDOUT: .H = %H.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Cpp.import_cpp = import_cpp {
// CHECK:STDOUT: import Cpp "union.h"
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %u.patt: %pattern_type.a90 = binding_pattern u [concrete]
// CHECK:STDOUT: %u.param_patt: %pattern_type.a90 = value_param_pattern %u.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %u.param: %Union = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %Union.ref [concrete = constants.%Union] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Union.ref: type = name_ref Union, imports.%Union.decl [concrete = constants.%Union]
// CHECK:STDOUT: }
// CHECK:STDOUT: %u: %Union = bind_name u, %u.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
// CHECK:STDOUT: %u.patt: %pattern_type.a90 = binding_pattern u [concrete]
// CHECK:STDOUT: %u.param_patt: %pattern_type.a90 = value_param_pattern %u.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %u.param: %Union = value_param call_param0
// CHECK:STDOUT: %.loc12: type = splice_block %Union.ref [concrete = constants.%Union] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Union.ref: type = name_ref Union, imports.%Union.decl [concrete = constants.%Union]
// CHECK:STDOUT: }
// CHECK:STDOUT: %u: %Union = bind_name u, %u.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {
// CHECK:STDOUT: %u.patt: %pattern_type.a90 = binding_pattern u [concrete]
// CHECK:STDOUT: %u.param_patt: %pattern_type.a90 = value_param_pattern %u.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %u.param: %Union = value_param call_param0
// CHECK:STDOUT: %.loc18: type = splice_block %Union.ref [concrete = constants.%Union] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Union.ref: type = name_ref Union, imports.%Union.decl [concrete = constants.%Union]
// CHECK:STDOUT: }
// CHECK:STDOUT: %u: %Union = bind_name u, %u.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Union {
// CHECK:STDOUT: %int_32.1: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Union.elem.041 = field_decl a, element0 [concrete]
// CHECK:STDOUT: %int_32.2: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.2: %Union.elem.041 = field_decl b, element1 [concrete]
// CHECK:STDOUT: %int_32.3: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.3: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.3: %Union.elem.92a = field_decl p, element2 [concrete]
// CHECK:STDOUT: %.4: type = custom_layout_type {size=8, align=8, .a@0: %i32, .b@0: %i32, .p@0: %ptr.235} [concrete = constants.%.c84]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.4 [concrete = constants.%complete_type.1b0]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Union
// CHECK:STDOUT: .a = %.1
// CHECK:STDOUT: .b = %.2
// CHECK:STDOUT: .p = %.3
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%u.param: %Union) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %u.ref: %Union = name_ref u, %u
// CHECK:STDOUT: %a.ref: %Union.elem.041 = name_ref a, @Union.%.1 [concrete = @Union.%.1]
// CHECK:STDOUT: %.loc8_11.1: ref %i32 = class_element_access %u.ref, element0
// CHECK:STDOUT: %.loc8_11.2: %i32 = bind_value %.loc8_11.1
// CHECK:STDOUT: return %.loc8_11.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%u.param: %Union) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %u.ref: %Union = name_ref u, %u
// CHECK:STDOUT: %b.ref: %Union.elem.041 = name_ref b, @Union.%.2 [concrete = @Union.%.2]
// CHECK:STDOUT: %.loc14_11.1: ref %i32 = class_element_access %u.ref, element1
// CHECK:STDOUT: %.loc14_11.2: %i32 = bind_value %.loc14_11.1
// CHECK:STDOUT: return %.loc14_11.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @H(%u.param: %Union) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %u.ref: %Union = name_ref u, %u
// CHECK:STDOUT: %p.ref: %Union.elem.92a = name_ref p, @Union.%.3 [concrete = @Union.%.3]
// CHECK:STDOUT: %.loc20_12.1: ref %ptr.235 = class_element_access %u.ref, element2
// CHECK:STDOUT: %.loc20_12.2: %ptr.235 = bind_value %.loc20_12.1
// CHECK:STDOUT: %.loc20_10.1: ref %i32 = deref %.loc20_12.2
// CHECK:STDOUT: %.loc20_10.2: %i32 = bind_value %.loc20_10.1
// CHECK:STDOUT: return %.loc20_10.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_non_bitfields_in_type_with_bitfields.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Struct: type = class_type @Struct [concrete]
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete]
// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %Struct.elem: type = unbound_element_type %Struct, %i32 [concrete]
// CHECK:STDOUT: %.f9e: type = custom_layout_type {size=8, align=4, .a@0: %i32} [concrete]
// CHECK:STDOUT: %complete_type.d3c: <witness> = complete_type_witness %.f9e [concrete]
// CHECK:STDOUT: %pattern_type.60c: type = pattern_type %Struct [concrete]
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %Union: type = class_type @Union [concrete]
// CHECK:STDOUT: %Union.elem: type = unbound_element_type %Union, %i32 [concrete]
// CHECK:STDOUT: %.891: type = custom_layout_type {size=4, align=4, .c@0: %i32} [concrete]
// CHECK:STDOUT: %complete_type.591: <witness> = complete_type_witness %.891 [concrete]
// CHECK:STDOUT: %pattern_type.a90: type = pattern_type %Union [concrete]
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Struct = %Struct.decl
// CHECK:STDOUT: .Union = %Union.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Struct.decl: type = class_decl @Struct [concrete = constants.%Struct] {} {}
// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
// CHECK:STDOUT: %Union.decl: type = class_decl @Union [concrete = constants.%Union] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Cpp = imports.%Cpp
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .G = %G.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Cpp.import_cpp = import_cpp {
// CHECK:STDOUT: import Cpp "with_bitfields.h"
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %s.patt: %pattern_type.60c = binding_pattern s [concrete]
// CHECK:STDOUT: %s.param_patt: %pattern_type.60c = value_param_pattern %s.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %s.param: %Struct = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %Struct.ref [concrete = constants.%Struct] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Struct.ref: type = name_ref Struct, imports.%Struct.decl [concrete = constants.%Struct]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: %Struct = bind_name s, %s.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
// CHECK:STDOUT: %s.patt: %pattern_type.a90 = binding_pattern s [concrete]
// CHECK:STDOUT: %s.param_patt: %pattern_type.a90 = value_param_pattern %s.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %s.param: %Union = value_param call_param0
// CHECK:STDOUT: %.loc12: type = splice_block %Union.ref [concrete = constants.%Union] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Union.ref: type = name_ref Union, imports.%Union.decl [concrete = constants.%Union]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: %Union = bind_name s, %s.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Struct {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Struct.elem = field_decl a, element0 [concrete]
// CHECK:STDOUT: %.2: type = custom_layout_type {size=8, align=4, .a@0: %i32} [concrete = constants.%.f9e]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.2 [concrete = constants.%complete_type.d3c]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Struct
// CHECK:STDOUT: .a = %.1
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Union {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Union.elem = field_decl c, element0 [concrete]
// CHECK:STDOUT: %.2: type = custom_layout_type {size=4, align=4, .c@0: %i32} [concrete = constants.%.891]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.2 [concrete = constants.%complete_type.591]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Union
// CHECK:STDOUT: .c = %.1
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%s.param: %Struct) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %s.ref: %Struct = name_ref s, %s
// CHECK:STDOUT: %a.ref: %Struct.elem = name_ref a, @Struct.%.1 [concrete = @Struct.%.1]
// CHECK:STDOUT: %.loc8_11.1: ref %i32 = class_element_access %s.ref, element0
// CHECK:STDOUT: %.loc8_11.2: %i32 = bind_value %.loc8_11.1
// CHECK:STDOUT: return %.loc8_11.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%s.param: %Union) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %s.ref: %Union = name_ref s, %s
// CHECK:STDOUT: %c.ref: %Union.elem = name_ref c, @Union.%.1 [concrete = @Union.%.1]
// CHECK:STDOUT: %.loc14_11.1: ref %i32 = class_element_access %s.ref, element0
// CHECK:STDOUT: %.loc14_11.2: %i32 = bind_value %.loc14_11.1
// CHECK:STDOUT: return %.loc14_11.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_bitfields.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Struct: type = class_type @Struct [concrete]
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete]
// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %Struct.elem: type = unbound_element_type %Struct, %i32 [concrete]
// CHECK:STDOUT: %.f9e: type = custom_layout_type {size=8, align=4, .a@0: %i32} [concrete]
// CHECK:STDOUT: %complete_type.d3c: <witness> = complete_type_witness %.f9e [concrete]
// CHECK:STDOUT: %pattern_type.60c: type = pattern_type %Struct [concrete]
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %Union: type = class_type @Union [concrete]
// CHECK:STDOUT: %Union.elem: type = unbound_element_type %Union, %i32 [concrete]
// CHECK:STDOUT: %.891: type = custom_layout_type {size=4, align=4, .c@0: %i32} [concrete]
// CHECK:STDOUT: %complete_type.591: <witness> = complete_type_witness %.891 [concrete]
// CHECK:STDOUT: %pattern_type.a90: type = pattern_type %Union [concrete]
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Struct = %Struct.decl
// CHECK:STDOUT: .Union = %Union.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Struct.decl: type = class_decl @Struct [concrete = constants.%Struct] {} {}
// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
// CHECK:STDOUT: %Union.decl: type = class_decl @Union [concrete = constants.%Union] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Cpp = imports.%Cpp
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .G = %G.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Cpp.import_cpp = import_cpp {
// CHECK:STDOUT: import Cpp "with_bitfields.h"
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %s.patt: %pattern_type.60c = binding_pattern s [concrete]
// CHECK:STDOUT: %s.param_patt: %pattern_type.60c = value_param_pattern %s.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %s.param: %Struct = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %Struct.ref [concrete = constants.%Struct] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Struct.ref: type = name_ref Struct, imports.%Struct.decl [concrete = constants.%Struct]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: %Struct = bind_name s, %s.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
// CHECK:STDOUT: %s.patt: %pattern_type.a90 = binding_pattern s [concrete]
// CHECK:STDOUT: %s.param_patt: %pattern_type.a90 = value_param_pattern %s.patt, call_param0 [concrete]
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %s.param: %Union = value_param call_param0
// CHECK:STDOUT: %.loc23: type = splice_block %Union.ref [concrete = constants.%Union] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Union.ref: type = name_ref Union, imports.%Union.decl [concrete = constants.%Union]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: %Union = bind_name s, %s.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Struct {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Struct.elem = field_decl a, element0 [concrete]
// CHECK:STDOUT: %.2: type = custom_layout_type {size=8, align=4, .a@0: %i32} [concrete = constants.%.f9e]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.2 [concrete = constants.%complete_type.d3c]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Struct
// CHECK:STDOUT: .b = <poisoned>
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Union {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.1: %Union.elem = field_decl c, element0 [concrete]
// CHECK:STDOUT: %.2: type = custom_layout_type {size=4, align=4, .c@0: %i32} [concrete = constants.%.891]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %.2 [concrete = constants.%complete_type.591]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Union
// CHECK:STDOUT: .d = <poisoned>
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%s.param: %Struct) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %s.ref: %Struct = name_ref s, %s
// CHECK:STDOUT: %b.ref: <error> = name_ref b, <error> [concrete = <error>]
// CHECK:STDOUT: return <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%s.param: %Union) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %s.ref: %Union = name_ref s, %s
// CHECK:STDOUT: %d.ref: <error> = name_ref d, <error> [concrete = <error>]
// CHECK:STDOUT: return <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+12 -12
View File
@@ -226,8 +226,6 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: %v.param: %HasQualifiers = value_param call_param0
// CHECK:STDOUT: %.loc6_12: type = splice_block %HasQualifiers.ref.loc6_12 [concrete = constants.%HasQualifiers] {
// CHECK:STDOUT: %Cpp.ref.loc6_9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: %HasQualifiers.ref.loc6_12: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v: %HasQualifiers = bind_name v, %v.param
@@ -242,7 +240,9 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @HasQualifiers {
// CHECK:STDOUT: complete_type_witness = @F.%complete_type
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%HasQualifiers
@@ -378,8 +378,6 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: %v.param: %HasQualifiers = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %HasQualifiers.ref [concrete = constants.%HasQualifiers] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
// CHECK:STDOUT: %HasQualifiers.ref: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v: %HasQualifiers = bind_name v, %v.param
@@ -387,7 +385,9 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @HasQualifiers {
// CHECK:STDOUT: complete_type_witness = @Value.%complete_type
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%HasQualifiers
@@ -500,8 +500,6 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: %p.param: %ptr.ec3 = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.ec3] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: %HasQualifiers.ref: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers]
// CHECK:STDOUT: %ptr: type = ptr_type %HasQualifiers.ref [concrete = constants.%ptr.ec3]
// CHECK:STDOUT: }
@@ -510,7 +508,9 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @HasQualifiers {
// CHECK:STDOUT: complete_type_witness = @Ref.%complete_type
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%HasQualifiers
@@ -572,8 +572,6 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: %p.param: %ptr.ec3 = value_param call_param0
// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.ec3] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: %HasQualifiers.ref: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers]
// CHECK:STDOUT: %ptr: type = ptr_type %HasQualifiers.ref [concrete = constants.%ptr.ec3]
// CHECK:STDOUT: }
@@ -582,7 +580,9 @@ fn Ref(p: Cpp.HasQualifiers*) {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @HasQualifiers {
// CHECK:STDOUT: complete_type_witness = @Ref.%complete_type
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%HasQualifiers
+129 -75
View File
@@ -18,23 +18,32 @@
struct Bar;
// --- fail_todo_import_declaration.carbon
// --- import_declaration.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+7]]:13: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// --- fail_use_declaration_as_definition.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
fn MyF() {
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE+6]]:12: error: binding pattern has incomplete type `Bar` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: var bar: Cpp.Bar;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./declaration.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
var bar: Cpp.Bar;
}
// ============================================================================
// Definition
// ============================================================================
@@ -112,6 +121,7 @@ library "[[@TEST_NAME]]";
import Cpp library "private_static_member_function.h";
fn MyF() {
// TODO: Should fail because `foo` is inaccessible.
Cpp.Bar.foo();
}
@@ -122,7 +132,7 @@ fn MyF() {
// --- public_static_data_member.h
struct Bar {
static Bar* foo;
static Bar* _Nonnull foo;
};
// --- fail_todo_import_public_static_data_member.carbon
@@ -155,10 +165,10 @@ fn MyF() {
// --- public_data_member.h
struct Bar {
Bar* foo;
Bar* _Nonnull foo;
};
// --- fail_todo_import_public_data_member.carbon
// --- import_public_data_member.carbon
library "[[@TEST_NAME]]";
@@ -166,17 +176,6 @@ import Cpp library "public_data_member.h";
//@dump-sem-ir-begin
fn MyF(bar : Cpp.Bar*) {
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+11]]:27: error: semantics TODO: `Unsupported: Declaration type Field` [SemanticsTodo]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+8]]:27: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+4]]:27: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
let foo_bar: Cpp.Bar* = bar->foo;
}
//@dump-sem-ir-end
@@ -225,7 +224,7 @@ library "[[@TEST_NAME]]";
import Cpp library "inheritance_pointers.h";
//@dump-sem-ir-begin
fn MyF1(bar : Cpp.Bar1*);
fn MyF1(bar: Cpp.Bar1*);
// TODO: Support C++ inheritance.
// CHECK:STDERR: fail_todo_import_inheritance_pointers.carbon:[[@LINE+10]]:33: error: cannot implicitly convert expression of type `Cpp.Bar2*` to `Cpp.Bar1*` [ConversionFailure]
// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
@@ -234,8 +233,8 @@ fn MyF1(bar : Cpp.Bar1*);
// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
// CHECK:STDERR: ^~~
// CHECK:STDERR: fail_todo_import_inheritance_pointers.carbon:[[@LINE-8]]:9: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR: fn MyF1(bar : Cpp.Bar1*);
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR: fn MyF1(bar: Cpp.Bar1*);
// CHECK:STDERR: ^~~~~~~~~~~~~~
// CHECK:STDERR:
fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
//@dump-sem-ir-end
@@ -247,24 +246,36 @@ fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); }
// --- dynamic.h
struct Bar {
virtual ~Bar();
virtual void f();
};
// --- fail_todo_import_dynamic.carbon
// --- import_dynamic.carbon
library "[[@TEST_NAME]]";
import Cpp library "dynamic.h";
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_dynamic.carbon:[[@LINE+7]]:14: error: semantics TODO: `Unsupported: Dynamic Class` [SemanticsTodo]
// CHECK:STDERR: fn MyF(bar : Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_dynamic.carbon:[[@LINE+4]]:14: note: in `Cpp` name lookup for `Bar` [InCppNameLookup]
// CHECK:STDERR: fn MyF(bar : Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn MyF(bar : Cpp.Bar*);
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// --- fail_todo_call_dynamic.carbon
library "[[@TEST_NAME]]";
import Cpp library "dynamic.h";
//@dump-sem-ir-begin
fn MyF(bar: Cpp.Bar*) {
// CHECK:STDERR: fail_todo_call_dynamic.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Virtual function` [SemanticsTodo]
// CHECK:STDERR: bar->f();
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: fail_todo_call_dynamic.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `f` [InCppNameLookup]
// CHECK:STDERR: bar->f();
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR:
bar->f();
}
//@dump-sem-ir-end
// ============================================================================
@@ -313,6 +324,7 @@ class Derived {
}
fn MyF() {
// TODO: Should fail because `foo` is inaccessible.
Derived.foo();
}
@@ -346,36 +358,40 @@ import Cpp library "template.h";
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// CHECK:STDOUT: --- fail_todo_import_declaration.carbon
// CHECK:STDOUT: --- import_declaration.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = <error>
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: <error> = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: <error> = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: <error> = value_param call_param0
// CHECK:STDOUT: %.loc14: type = splice_block %ptr [concrete = <error>] {
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: <error> = name_ref Bar, <error> [concrete = <error>]
// CHECK:STDOUT: %ptr: type = ptr_type <error> [concrete = <error>]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: <error> = bind_name bar, %bar.param
// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: <error>);
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr);
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition.carbon
// CHECK:STDOUT:
@@ -403,7 +419,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -439,7 +454,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -470,7 +484,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %foo.ref: %Bar.foo.type = name_ref foo, imports.%Bar.foo.decl [concrete = constants.%Bar.foo]
// CHECK:STDOUT: %Bar.foo.call: init %empty_tuple.type = call %foo.ref()
@@ -503,7 +516,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19_12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -511,11 +523,12 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_public_data_member.carbon
// CHECK:STDOUT: --- import_public_data_member.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %Bar.elem: type = unbound_element_type %Bar, %ptr.f68 [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.f68 [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
@@ -537,7 +550,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr.loc7 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc7: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc7: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc7: type = ptr_type %Bar.ref.loc7 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -551,14 +563,16 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo_bar.patt: %pattern_type = binding_pattern foo_bar [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar
// CHECK:STDOUT: %.loc19_30: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19_23: type = splice_block %ptr.loc19 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc19: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc19: type = ptr_type %Bar.ref.loc19 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: %.loc8_30.1: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: %Bar.elem = name_ref foo, @Bar.%.1 [concrete = @Bar.%.1]
// CHECK:STDOUT: %.loc8_30.2: ref %ptr.f68 = class_element_access %.loc8_30.1, element0
// CHECK:STDOUT: %.loc8_23: type = splice_block %ptr.loc8 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc8: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc8: type = ptr_type %Bar.ref.loc8 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc8_30.3: %ptr.f68 = bind_value %.loc8_30.2
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, %.loc8_30.3
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -589,12 +603,10 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, imports.%Bar1.decl [concrete = constants.%Bar1]
// CHECK:STDOUT: %foo1.ref.loc8: %Bar1.foo1.type = name_ref foo1, imports.%Bar1.foo1.decl [concrete = constants.%Bar1.foo1]
// CHECK:STDOUT: %Bar1.foo1.call.loc8: init %empty_tuple.type = call %foo1.ref.loc8()
// CHECK:STDOUT: %Cpp.ref.loc9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar2.ref.loc9: type = name_ref Bar2, imports.%Bar2.decl [concrete = constants.%Bar2]
// CHECK:STDOUT: %foo1.ref.loc9: %Bar1.foo1.type = name_ref foo1, imports.%Bar1.foo1.decl [concrete = constants.%Bar1.foo1]
// CHECK:STDOUT: %Bar1.foo1.call.loc9: init %empty_tuple.type = call %foo1.ref.loc9()
@@ -639,7 +651,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, imports.%Bar1.decl [concrete = constants.%Bar1]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar1.ref [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -652,7 +663,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.eca = value_param call_param0
// CHECK:STDOUT: %.loc19_23: type = splice_block %ptr [concrete = constants.%ptr.eca] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar2.ref: type = name_ref Bar2, imports.%Bar2.decl [concrete = constants.%Bar2]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar2.ref [concrete = constants.%ptr.eca]
// CHECK:STDOUT: }
@@ -671,36 +681,81 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_dynamic.carbon
// CHECK:STDOUT: --- import_dynamic.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = <error>
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: <error> = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: <error> = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: <error> = value_param call_param0
// CHECK:STDOUT: %.loc14: type = splice_block %ptr [concrete = <error>] {
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: <error> = name_ref Bar, <error> [concrete = <error>]
// CHECK:STDOUT: %ptr: type = ptr_type <error> [concrete = <error>]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: <error> = bind_name bar, %bar.param
// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: <error>);
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr);
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_call_dynamic.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.f68 [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr.f68) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar
// CHECK:STDOUT: %.loc15: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %f.ref: <error> = name_ref f, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_to_inherit_public.carbon
// CHECK:STDOUT:
@@ -733,12 +788,11 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT:
// CHECK:STDOUT: class @Derived {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %.loc8: %Derived.elem = base_decl %Bar.ref, element0 [concrete]
// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %Bar} [concrete = constants.%struct_type.base.36d]
// CHECK:STDOUT: %complete_type.loc9: <witness> = complete_type_witness %struct_type.base [concrete = constants.%complete_type.fff]
// CHECK:STDOUT: complete_type_witness = %complete_type.loc9
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %struct_type.base [concrete = constants.%complete_type.fff]
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
+49 -47
View File
@@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
@@ -18,23 +18,32 @@
union Bar;
// --- fail_todo_import_declaration.carbon
// --- import_declaration.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+7]]:13: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_declaration.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup]
// CHECK:STDERR: fn MyF(bar: Cpp.Bar*);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// --- fail_use_declaration_as_definition.carbon
library "[[@TEST_NAME]]";
import Cpp library "declaration.h";
fn MyF() {
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE+6]]:12: error: binding pattern has incomplete type `Bar` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: var bar: Cpp.Bar;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_use_declaration_as_definition.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./declaration.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
var bar: Cpp.Bar;
}
// ============================================================================
// Definition
// ============================================================================
@@ -113,6 +122,7 @@ library "[[@TEST_NAME]]";
import Cpp library "private_static_member_function.h";
fn MyF() {
// TODO: Should fail because `foo` is inaccessible.
Cpp.Bar.foo();
}
@@ -124,7 +134,7 @@ fn MyF() {
union Bar {
public:
static Bar* foo;
static Bar* _Nonnull foo;
};
// --- fail_todo_import_public_static_data_member.carbon
@@ -158,28 +168,17 @@ fn MyF() {
union Bar {
public:
Bar* foo;
Bar* _Nonnull foo;
};
// --- fail_todo_import_public_data_member.carbon
// --- import_public_data_member.carbon
library "[[@TEST_NAME]]";
import Cpp library "public_static_data_member.h";
import Cpp library "public_data_member.h";
//@dump-sem-ir-begin
fn MyF(bar : Cpp.Bar*) {
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+11]]:27: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+8]]:27: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_public_data_member.carbon:[[@LINE+4]]:27: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: let foo_bar: Cpp.Bar* = bar->foo;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
let foo_bar: Cpp.Bar* = bar->foo;
}
//@dump-sem-ir-end
@@ -202,6 +201,7 @@ library "[[@TEST_NAME]]";
import Cpp library "to_inherit_public.h";
class Derived {
// TODO: Presumably we should disallow deriving from a union.
extend base: Cpp.Bar;
}
@@ -239,36 +239,40 @@ import Cpp library "template.h";
fn MyF(bar: Cpp.Bar*);
//@dump-sem-ir-end
// CHECK:STDOUT: --- fail_todo_import_declaration.carbon
// CHECK:STDOUT: --- import_declaration.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .Bar = <error>
// CHECK:STDOUT: .Bar = %Bar.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {
// CHECK:STDOUT: %bar.patt: <error> = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: <error> = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete]
// CHECK:STDOUT: %bar.param_patt: %pattern_type = value_param_pattern %bar.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %bar.param: <error> = value_param call_param0
// CHECK:STDOUT: %.loc14: type = splice_block %ptr [concrete = <error>] {
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref: <error> = name_ref Bar, <error> [concrete = <error>]
// CHECK:STDOUT: %ptr: type = ptr_type <error> [concrete = <error>]
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar: <error> = bind_name bar, %bar.param
// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MyF(%bar.param: <error>);
// CHECK:STDOUT: fn @MyF(%bar.param: %ptr);
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition.carbon
// CHECK:STDOUT:
@@ -296,7 +300,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -332,7 +335,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
@@ -363,7 +365,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %foo.ref: %Bar.foo.type = name_ref foo, imports.%Bar.foo.decl [concrete = constants.%Bar.foo]
// CHECK:STDOUT: %Bar.foo.call: init %empty_tuple.type = call %foo.ref()
@@ -396,7 +397,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19_12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -404,11 +404,12 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_public_data_member.carbon
// CHECK:STDOUT: --- import_public_data_member.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete]
// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete]
// CHECK:STDOUT: %Bar.elem: type = unbound_element_type %Bar, %ptr.f68 [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.f68 [concrete]
// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete]
// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete]
@@ -430,7 +431,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0
// CHECK:STDOUT: %.loc7: type = splice_block %ptr.loc7 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc7: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Bar.ref.loc7: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc7: type = ptr_type %Bar.ref.loc7 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
@@ -444,14 +444,16 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT: %foo_bar.patt: %pattern_type = binding_pattern foo_bar [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar
// CHECK:STDOUT: %.loc19_30: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc19_23: type = splice_block %ptr.loc19 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc19: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc19: type = ptr_type %Bar.ref.loc19 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: %.loc8_30.1: ref %Bar = deref %bar.ref
// CHECK:STDOUT: %foo.ref: %Bar.elem = name_ref foo, @Bar.%.1 [concrete = @Bar.%.1]
// CHECK:STDOUT: %.loc8_30.2: ref %ptr.f68 = class_element_access %.loc8_30.1, element0
// CHECK:STDOUT: %.loc8_23: type = splice_block %ptr.loc8 [concrete = constants.%ptr.f68] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Bar.ref.loc8: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar]
// CHECK:STDOUT: %ptr.loc8: type = ptr_type %Bar.ref.loc8 [concrete = constants.%ptr.f68]
// CHECK:STDOUT: }
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc8_30.3: %ptr.f68 = bind_value %.loc8_30.2
// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, %.loc8_30.3
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
+67 -90
View File
@@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
@@ -27,12 +27,12 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:11: error: forming value of incomplete type `Cpp.C` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
}
@@ -44,12 +44,11 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: let c: Cpp.C;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `C` [InCppNameLookup]
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+10]]:10: error: binding pattern has incomplete type `C` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: let c: Cpp.C;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:15: error: expected `=`; `let` declaration must have an initializer [ExpectedInitializerAfterLet]
// CHECK:STDERR: let c: Cpp.C;
@@ -77,14 +76,21 @@ library "[[@TEST_NAME]]";
import Cpp library "double_decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.C` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo1` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo1({});
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.C` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo2({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-14]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo2({});
}
@@ -124,7 +130,7 @@ class C {
auto foo(C) -> void;
// --- import_definition_single_data_member_value_param_type.carbon
// --- fail_todo_import_definition_single_data_member_value_param_type.carbon
library "[[@TEST_NAME]]";
@@ -132,6 +138,14 @@ import Cpp library "definition_single_data_member_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+8]]:11: error: cannot implicitly convert expression of type `{}` to `Cpp.C` [ConversionFailure]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+5]]:11: note: type `{}` does not implement interface `Core.ImplicitAs(Cpp.C)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
}
@@ -152,7 +166,7 @@ class C {
auto foo(C) -> void;
// --- import_definition_multiple_data_members_value_param_type.carbon
// --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
library "[[@TEST_NAME]]";
@@ -160,6 +174,14 @@ import Cpp library "definition_multiple_data_members_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+8]]:11: error: cannot implicitly convert expression of type `{}` to `Cpp.C` [ConversionFailure]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+5]]:11: note: type `{}` does not implement interface `Core.ImplicitAs(Cpp.C)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
}
@@ -285,19 +307,12 @@ class C;
auto foo(C* _Nonnull) -> void;
// --- fail_todo_import_decl_pointer_param_type.carbon
// --- import_decl_pointer_param_type.carbon
library "[[@TEST_NAME]]";
import Cpp library "decl_pointer_param_type.h";
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+7]]:9: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn F(c: Cpp.C*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+4]]:9: note: in `Cpp` name lookup for `C` [InCppNameLookup]
// CHECK:STDERR: fn F(c: Cpp.C*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR:
fn F(c: Cpp.C*) {
//@dump-sem-ir-begin
Cpp.foo(c);
@@ -343,12 +358,12 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_return_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: function returns incomplete type `Cpp.C` [IncompleteTypeInFunctionReturnType]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_return_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon: note: return type declared here [IncompleteReturnTypeHere]
// CHECK:STDERR:
Cpp.foo();
}
@@ -385,7 +400,7 @@ class C;
auto foo() -> C* _Nonnull;
// --- fail_todo_import_decl_pointer_return_type.carbon
// --- import_decl_pointer_return_type.carbon
library "[[@TEST_NAME]]";
@@ -393,13 +408,6 @@ import Cpp library "decl_pointer_return_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
Cpp.foo();
//@dump-sem-ir-end
}
@@ -455,7 +463,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
@@ -472,7 +479,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition_single_data_member_value_param_type.carbon
// CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -480,10 +487,6 @@ fn F() {
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.1b3: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%C) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.21b: %T.as.Destroy.impl.Op.type.1b3 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -501,24 +504,14 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
// CHECK:STDOUT: %.loc8_12.3: init %C = class_init (), %.loc8_12.2 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc8_12.4: ref %C = temporary %.loc8_12.2, %.loc8_12.3
// CHECK:STDOUT: %.loc8_12.5: ref %C = converted %.loc8_12.1, %.loc8_12.4
// CHECK:STDOUT: %.loc8_12.6: %C = bind_value %.loc8_12.5
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%.loc8_12.6)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.2, constants.%T.as.Destroy.impl.Op.21b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.2, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.d9e = addr_of %.loc8_12.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: %.loc16_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc16_12.2: %C = converted %.loc16_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition_multiple_data_members_value_param_type.carbon
// CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -526,10 +519,6 @@ fn F() {
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.1b3: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%C) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.21b: %T.as.Destroy.impl.Op.type.1b3 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -547,20 +536,10 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
// CHECK:STDOUT: %.loc8_12.3: init %C = class_init (), %.loc8_12.2 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc8_12.4: ref %C = temporary %.loc8_12.2, %.loc8_12.3
// CHECK:STDOUT: %.loc8_12.5: ref %C = converted %.loc8_12.1, %.loc8_12.4
// CHECK:STDOUT: %.loc8_12.6: %C = bind_value %.loc8_12.5
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%.loc8_12.6)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.2, constants.%T.as.Destroy.impl.Op.21b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.2, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.d9e = addr_of %.loc8_12.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: %.loc16_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc16_12.2: %C = converted %.loc16_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -600,7 +579,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
@@ -667,7 +645,6 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %N1.ref: <namespace> = name_ref N1, imports.%N1 [concrete = imports.%N1]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_15.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_15.2: ref %C = temporary_storage
@@ -720,7 +697,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
@@ -786,7 +762,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %bar.ref: %C.bar.type = name_ref bar, imports.%C.bar.decl [concrete = constants.%C.bar]
// CHECK:STDOUT: %C.bar.call: init %empty_tuple.type = call %bar.ref()
@@ -841,7 +816,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %C = temporary_storage
@@ -862,9 +836,11 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_decl_pointer_param_type.carbon
// CHECK:STDOUT: --- import_decl_pointer_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %C [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
@@ -872,10 +848,11 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .C = <error>
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: .foo = %foo.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
@@ -883,12 +860,12 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%c.param: <error>) {
// CHECK:STDOUT: fn @F(%c.param: %ptr) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc15: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %c.ref: <error> = name_ref c, %c
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: %c.ref: %ptr = name_ref c, %c
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%c.ref)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -952,7 +929,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_11.1: ref %C = temporary_storage
// CHECK:STDOUT: %foo.call: init %C = call %foo.ref() to %.loc8_11.1
@@ -965,9 +941,11 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_decl_pointer_return_type.carbon
// CHECK:STDOUT: --- import_decl_pointer_return_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -988,7 +966,7 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %foo.call: init <error> = call %foo.ref()
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -1016,7 +994,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
// CHECK:STDOUT: <elided>
@@ -77,7 +77,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %Y.ref: type = name_ref Y, imports.%X.decl [concrete = constants.%X]
// CHECK:STDOUT: %f.ref: %X.f.type = name_ref f, imports.%X.f.decl [concrete = constants.%X.f]
// CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42.20e]
@@ -229,7 +229,6 @@ fn F() {
// CHECK:STDOUT: assign %s.var, %.loc8_3
// CHECK:STDOUT: %.loc8_13: type = splice_block %S.ref [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var
@@ -292,7 +291,6 @@ fn F() {
// CHECK:STDOUT: assign %s.var, %.loc8_3
// CHECK:STDOUT: %.loc8_13: type = splice_block %S.ref.loc8 [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %S.ref.loc8: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var
@@ -560,7 +558,6 @@ fn F() {
// CHECK:STDOUT: assign %s.var, %.loc8_3
// CHECK:STDOUT: %.loc8_13: type = splice_block %S.ref [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var
+60 -89
View File
@@ -27,12 +27,12 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:11: error: forming value of incomplete type `Cpp.S` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
}
@@ -44,12 +44,11 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: let s: Cpp.S;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `S` [InCppNameLookup]
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+10]]:10: error: binding pattern has incomplete type `S` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: let s: Cpp.S;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:15: error: expected `=`; `let` declaration must have an initializer [ExpectedInitializerAfterLet]
// CHECK:STDERR: let s: Cpp.S;
@@ -77,14 +76,21 @@ library "[[@TEST_NAME]]";
import Cpp library "double_decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.S` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo1` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo1({});
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.S` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo2({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-14]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo2({});
}
@@ -124,7 +130,7 @@ struct S {
auto foo(S) -> void;
// --- import_definition_single_data_member_value_param_type.carbon
// --- fail_todo_import_definition_single_data_member_value_param_type.carbon
library "[[@TEST_NAME]]";
@@ -132,6 +138,11 @@ import Cpp library "definition_single_data_member_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon:[[@LINE+5]]:11: error: name `Core.ImplicitAs` implicitly referenced here, but not found [CoreNameNotFound]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_single_data_member_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
}
@@ -152,7 +163,7 @@ struct S {
auto foo(S) -> void;
// --- import_definition_multiple_data_members_value_param_type.carbon
// --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
library "[[@TEST_NAME]]";
@@ -160,6 +171,11 @@ import Cpp library "definition_multiple_data_members_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+5]]:11: error: name `Core.ImplicitAs` implicitly referenced here, but not found [CoreNameNotFound]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_definition_multiple_data_members_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
}
@@ -284,19 +300,12 @@ struct S;
auto foo(S* _Nonnull) -> void;
// --- fail_todo_import_decl_pointer_param_type.carbon
// --- import_decl_pointer_param_type.carbon
library "[[@TEST_NAME]]";
import Cpp library "decl_pointer_param_type.h";
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+7]]:9: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn F(s: Cpp.S*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+4]]:9: note: in `Cpp` name lookup for `S` [InCppNameLookup]
// CHECK:STDERR: fn F(s: Cpp.S*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR:
fn F(s: Cpp.S*) {
//@dump-sem-ir-begin
Cpp.foo(s);
@@ -342,12 +351,12 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_return_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: function returns incomplete type `Cpp.S` [IncompleteTypeInFunctionReturnType]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_return_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon: note: return type declared here [IncompleteReturnTypeHere]
// CHECK:STDERR:
Cpp.foo();
}
@@ -384,7 +393,7 @@ struct S;
auto foo() -> S* _Nonnull;
// --- fail_todo_import_decl_pointer_return_type.carbon
// --- import_decl_pointer_return_type.carbon
library "[[@TEST_NAME]]";
@@ -392,13 +401,6 @@ import Cpp library "decl_pointer_return_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
Cpp.foo();
//@dump-sem-ir-end
}
@@ -454,7 +456,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
@@ -471,7 +472,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition_single_data_member_value_param_type.carbon
// CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -479,10 +480,6 @@ fn F() {
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.642: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%S) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.ab5: %T.as.Destroy.impl.Op.type.642 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -500,24 +497,14 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
// CHECK:STDOUT: %.loc8_12.3: init %S = class_init (), %.loc8_12.2 [concrete = constants.%S.val]
// CHECK:STDOUT: %.loc8_12.4: ref %S = temporary %.loc8_12.2, %.loc8_12.3
// CHECK:STDOUT: %.loc8_12.5: ref %S = converted %.loc8_12.1, %.loc8_12.4
// CHECK:STDOUT: %.loc8_12.6: %S = bind_value %.loc8_12.5
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%.loc8_12.6)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.2, constants.%T.as.Destroy.impl.Op.ab5
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.2, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.5c7 = addr_of %.loc8_12.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: %.loc13_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.2: %S = converted %.loc13_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_definition_multiple_data_members_value_param_type.carbon
// CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -525,10 +512,6 @@ fn F() {
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.642: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%S) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.ab5: %T.as.Destroy.impl.Op.type.642 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -546,20 +529,10 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
// CHECK:STDOUT: %.loc8_12.3: init %S = class_init (), %.loc8_12.2 [concrete = constants.%S.val]
// CHECK:STDOUT: %.loc8_12.4: ref %S = temporary %.loc8_12.2, %.loc8_12.3
// CHECK:STDOUT: %.loc8_12.5: ref %S = converted %.loc8_12.1, %.loc8_12.4
// CHECK:STDOUT: %.loc8_12.6: %S = bind_value %.loc8_12.5
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%.loc8_12.6)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.2, constants.%T.as.Destroy.impl.Op.ab5
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.2, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.5c7 = addr_of %.loc8_12.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: %.loc13_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.2: %S = converted %.loc13_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -599,7 +572,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
@@ -666,7 +638,6 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %N1.ref: <namespace> = name_ref N1, imports.%N1 [concrete = imports.%N1]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_15.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_15.2: ref %S = temporary_storage
@@ -719,7 +690,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
@@ -785,7 +755,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: %bar.ref: %S.bar.type = name_ref bar, imports.%S.bar.decl [concrete = constants.%S.bar]
// CHECK:STDOUT: %S.bar.call: init %empty_tuple.type = call %bar.ref()
@@ -840,7 +809,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %S = temporary_storage
@@ -861,9 +829,11 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_decl_pointer_param_type.carbon
// CHECK:STDOUT: --- import_decl_pointer_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
@@ -871,10 +841,11 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .S = <error>
// CHECK:STDOUT: .S = %S.decl
// CHECK:STDOUT: .foo = %foo.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
@@ -882,12 +853,12 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%s.param: <error>) {
// CHECK:STDOUT: fn @F(%s.param: %ptr) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc15: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %s.ref: <error> = name_ref s, %s
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: %s.ref: %ptr = name_ref s, %s
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%s.ref)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -951,7 +922,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_11.1: ref %S = temporary_storage
// CHECK:STDOUT: %foo.call: init %S = call %foo.ref() to %.loc8_11.1
@@ -964,9 +934,11 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_decl_pointer_return_type.carbon
// CHECK:STDOUT: --- import_decl_pointer_return_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -987,7 +959,7 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %foo.call: init <error> = call %foo.ref()
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -1015,7 +987,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
// CHECK:STDOUT: <elided>
+50 -56
View File
@@ -28,12 +28,12 @@ import Cpp library "decl_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:11: error: forming value of incomplete type `Cpp.U` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE-7]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
@@ -46,12 +46,11 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: let u: Cpp.U;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `U` [InCppNameLookup]
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+10]]:10: error: binding pattern has incomplete type `U` in name binding declaration [IncompleteTypeInBindingDecl]
// CHECK:STDERR: let u: Cpp.U;
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:15: error: expected `=`; `let` declaration must have an initializer [ExpectedInitializerAfterLet]
// CHECK:STDERR: let u: Cpp.U;
@@ -79,14 +78,21 @@ library "[[@TEST_NAME]]";
import Cpp library "double_decl_value_param_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.U` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo1` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo1({});
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo1({});
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:12: error: forming value of incomplete type `Cpp.U` [IncompleteTypeInValueConversion]
// CHECK:STDERR: Cpp.foo2({});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE-14]]:1: in import [InImport]
// CHECK:STDERR: ./double_decl_value_param_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo2({});
}
@@ -134,12 +140,10 @@ import Cpp library "definition_single_data_member_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_import_definition_single_data_member_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Non-empty union` [SemanticsTodo]
// CHECK:STDERR: fail_import_definition_single_data_member_value_param_type.carbon:[[@LINE+5]]:11: error: name `Core.ImplicitAs` implicitly referenced here, but not found [CoreNameNotFound]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_import_definition_single_data_member_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_import_definition_single_data_member_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
@@ -169,12 +173,10 @@ import Cpp library "definition_multiple_data_members_value_param_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Non-empty union` [SemanticsTodo]
// CHECK:STDERR: fail_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+5]]:11: error: name `Core.ImplicitAs` implicitly referenced here, but not found [CoreNameNotFound]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_import_definition_multiple_data_members_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo({});
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_import_definition_multiple_data_members_value_param_type.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.foo({});
//@dump-sem-ir-end
@@ -301,19 +303,12 @@ union U;
auto foo(U* _Nonnull) -> void;
// --- fail_todo_import_decl_pointer_param_type.carbon
// --- import_decl_pointer_param_type.carbon
library "[[@TEST_NAME]]";
import Cpp library "decl_pointer_param_type.h";
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+7]]:9: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fn F(u: Cpp.U*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+4]]:9: note: in `Cpp` name lookup for `U` [InCppNameLookup]
// CHECK:STDERR: fn F(u: Cpp.U*) {
// CHECK:STDERR: ^~~~~
// CHECK:STDERR:
fn F(u: Cpp.U*) {
//@dump-sem-ir-begin
Cpp.foo(u);
@@ -359,12 +354,12 @@ library "[[@TEST_NAME]]";
import Cpp library "decl_value_return_type.h";
fn F() {
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: function returns incomplete type `Cpp.U` [IncompleteTypeInFunctionReturnType]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE-6]]:1: in import [InImport]
// CHECK:STDERR: ./decl_value_return_type.h:2: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon: note: return type declared here [IncompleteReturnTypeHere]
// CHECK:STDERR:
Cpp.foo();
}
@@ -409,7 +404,7 @@ import Cpp library "decl_pointer_return_type.h";
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: nullable pointer: U *` [SemanticsTodo]
// CHECK:STDERR: Cpp.foo();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
@@ -501,7 +496,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %U = temporary_storage
@@ -522,9 +516,10 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %U: type = class_type @U [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -543,7 +538,8 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc15: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.2: %U = converted %.loc13_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -552,9 +548,10 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %U: type = class_type @U [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -573,7 +570,8 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc15: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc13_12.2: %U = converted %.loc13_12.1, <error> [concrete = <error>]
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
@@ -614,7 +612,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %U = temporary_storage
@@ -681,7 +678,6 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %N1.ref: <namespace> = name_ref N1, imports.%N1 [concrete = imports.%N1]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_15.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_15.2: ref %U = temporary_storage
@@ -734,7 +730,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %U = temporary_storage
@@ -800,7 +795,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
// CHECK:STDOUT: %bar.ref: %U.bar.type = name_ref bar, imports.%U.bar.decl [concrete = constants.%U.bar]
// CHECK:STDOUT: %U.bar.call: init %empty_tuple.type = call %bar.ref()
@@ -855,7 +849,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_12.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc8_12.2: ref %U = temporary_storage
@@ -876,9 +869,11 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_decl_pointer_param_type.carbon
// CHECK:STDOUT: --- import_decl_pointer_param_type.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %U: type = class_type @U [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %U [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
@@ -886,10 +881,11 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .U = <error>
// CHECK:STDOUT: .U = %U.decl
// CHECK:STDOUT: .foo = %foo.decl
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {}
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
@@ -897,12 +893,12 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%u.param: <error>) {
// CHECK:STDOUT: fn @F(%u.param: %ptr) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref.loc15: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %u.ref: <error> = name_ref u, %u
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(<error>)
// CHECK:STDOUT: %u.ref: %ptr = name_ref u, %u
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%u.ref)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -966,7 +962,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_11.1: ref %U = temporary_storage
// CHECK:STDOUT: %foo.call: init %U = call %foo.ref() to %.loc8_11.1
@@ -1030,7 +1025,6 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
// CHECK:STDOUT: <elided>
-1
View File
@@ -331,7 +331,6 @@ fn MyF() {
// CHECK:STDOUT: fn @MyF() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
// CHECK:STDOUT: %.loc8_11.1: ref %X = temporary_storage
// CHECK:STDOUT: %foo.call: init %X = call %foo.ref() to %.loc8_11.1
+18
View File
@@ -140,6 +140,10 @@ class TypeCompleter {
auto BuildInfoForInst(SemIR::TypeId /*type_id*/, SemIR::ConstType inst) const
-> SemIR::CompleteTypeInfo;
auto BuildInfoForInst(SemIR::TypeId type_id,
SemIR::CustomLayoutType inst) const
-> SemIR::CompleteTypeInfo;
auto BuildInfoForInst(SemIR::TypeId /*type_id*/,
SemIR::PartialType inst) const
-> SemIR::CompleteTypeInfo;
@@ -294,6 +298,12 @@ auto TypeCompleter::AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
Push(context_->types().GetTypeIdForTypeInstId(inst.inner_id));
break;
}
case CARBON_KIND(SemIR::CustomLayoutType inst): {
for (auto field : context_->struct_type_fields().Get(inst.fields_id)) {
Push(context_->types().GetTypeIdForTypeInstId(field.type_inst_id));
}
break;
}
case CARBON_KIND(SemIR::PartialType inst): {
Push(context_->types().GetTypeIdForTypeInstId(inst.inner_id));
break;
@@ -520,6 +530,14 @@ auto TypeCompleter::BuildInfoForInst(SemIR::TypeId /*type_id*/,
return GetNestedInfo(context_->types().GetTypeIdForTypeInstId(inst.inner_id));
}
auto TypeCompleter::BuildInfoForInst(SemIR::TypeId type_id,
SemIR::CustomLayoutType /*inst*/) const
-> SemIR::CompleteTypeInfo {
// TODO: Should we support other value representations for custom layout
// types?
return {.value_repr = MakePointerValueRepr(type_id)};
}
auto TypeCompleter::BuildInfoForInst(SemIR::TypeId /*type_id*/,
SemIR::PartialType inst) const
-> SemIR::CompleteTypeInfo {
+7
View File
@@ -768,6 +768,13 @@ static auto BuildTypeForInst(FileContext& context, SemIR::ConstType inst)
context.sem_ir().types().GetTypeIdForTypeInstId(inst.inner_id));
}
static auto BuildTypeForInst(FileContext& context, SemIR::CustomLayoutType inst)
-> llvm::Type* {
auto layout = context.sem_ir().custom_layouts().Get(inst.layout_id);
return llvm::ArrayType::get(llvm::Type::getInt8Ty(context.llvm_context()),
layout[SemIR::CustomLayoutId::SizeIndex]);
}
static auto BuildTypeForInst(FileContext& context, SemIR::PartialType inst)
-> llvm::Type* {
return context.GetType(
+2
View File
@@ -218,6 +218,8 @@ auto FunctionContext::CreateAlloca(llvm::Type* type, const llvm::Twine& name)
builder().SetCurrentDebugLocation(debug_loc);
// Create an alloca for this variable in the entry block.
// TODO: Compute alignment of the type, which may be greater than the
// alignment computed by LLVM.
alloca = builder().CreateAlloca(type, /*ArraySize=*/nullptr, name);
}
+40 -9
View File
@@ -10,6 +10,7 @@
#include "toolchain/lower/function_context.h"
#include "toolchain/sem_ir/expr_info.h"
#include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/typed_insts.h"
@@ -26,6 +27,30 @@ static auto GetPointeeType(FunctionContext::TypeInFile type)
.type_id = type.file->GetPointeeType(type.type_id)};
}
// Given an index within a SemIR aggregate type, returns the corresponding index
// of the element within the LLVM type suitable for use with the getelementptr
// instruction.
static auto GetElementIndex(FunctionContext::TypeInFile type,
SemIR::ElementIndex idx) -> unsigned int {
auto type_inst = type.file->types().GetAsInst(type.type_id);
if (auto custom_layout_type = type_inst.TryAs<SemIR::CustomLayoutType>()) {
// For custom layout types, we form an array of i8 as the LLVM type, so the
// offset in the type is the getelementptr index.
// TODO: This offset might not fit into an `unsigned int`.
return type.file->custom_layouts().Get(
custom_layout_type
->layout_id)[SemIR::CustomLayoutId::FirstFieldIndex + idx.index];
}
// For now, struct and tuple types map directly into LLVM struct types with
// identical field numbering.
CARBON_CHECK(
type_inst.Is<SemIR::StructType>() || type_inst.Is<SemIR::TupleType>(),
"Indexing unexpected aggregate type {0}", type_inst);
return idx.index;
}
// Extracts an element of an aggregate, such as a struct, tuple, or class, by
// index. Depending on the expression category and value representation of the
// aggregate input, this will either produce a value or a reference.
@@ -58,14 +83,16 @@ static auto GetAggregateElement(FunctionContext& context,
return aggr_value;
case SemIR::ValueRepr::Copy:
// We are holding the values of the aggregate directly, elementwise.
return context.builder().CreateExtractValue(aggr_value, idx.index,
name);
return context.builder().CreateExtractValue(
aggr_value, GetElementIndex(value_repr.type(), idx), name);
case SemIR::ValueRepr::Pointer: {
// The value representation is a pointer to an aggregate that we want
// to index into.
auto* value_type = context.GetType(GetPointeeType(value_repr.type()));
auto value_rep_type = GetPointeeType(value_repr.type());
auto* value_type = context.GetType(value_rep_type);
auto* elem_ptr = context.builder().CreateStructGEP(
value_type, aggr_value, idx.index, name);
value_type, aggr_value, GetElementIndex(value_rep_type, idx),
name);
if (!value_repr.repr.elements_are_values()) {
// `elem_ptr` points to an object representation, which is our
@@ -88,17 +115,21 @@ static auto GetAggregateElement(FunctionContext& context,
case SemIR::ExprCategory::DurableRef:
case SemIR::ExprCategory::EphemeralRef: {
// Just locate the aggregate element.
auto* aggr_type = context.GetTypeOfInst(aggr_inst_id);
return context.builder().CreateStructGEP(aggr_type, aggr_value, idx.index,
name);
auto aggr_type = context.GetTypeIdOfInst(aggr_inst_id);
auto object_repr = FunctionContext::TypeInFile{
.file = aggr_type.file,
.type_id = aggr_type.file->types().GetObjectRepr(aggr_type.type_id)};
return context.builder().CreateStructGEP(
context.GetType(object_repr), aggr_value,
GetElementIndex(object_repr, idx), name);
}
}
}
static auto GetStructFieldName(FunctionContext::TypeInFile struct_type,
SemIR::ElementIndex index) -> llvm::StringRef {
auto struct_type_inst =
struct_type.file->types().GetAs<SemIR::StructType>(struct_type.type_id);
auto struct_type_inst = struct_type.file->types().GetAs<SemIR::AnyStructType>(
struct_type.type_id);
auto fields =
struct_type.file->struct_type_fields().Get(struct_type_inst.fields_id);
// We intentionally don't add this to the fingerprint because it's only used
+234
View File
@@ -0,0 +1,234 @@
// 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
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/interop/cpp/field.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/interop/cpp/field.carbon
// --- struct.h
struct A {
int n;
alignas(16) int m;
};
// --- access_struct.carbon
library "[[@TEST_NAME]]";
import Cpp library "struct.h";
// TODO: We generate 4-byte-aligned loads here, and should generate
// 16-byte-aligned loads as Clang does.
fn AccessN(a: Cpp.A) -> i32 {
return a.n;
}
fn AccessM(a: Cpp.A) -> i32 {
return a.m;
}
// --- assign_struct.carbon
library "[[@TEST_NAME]]";
import Cpp library "struct.h";
// TODO: We generate 4-byte-aligned stores here, and should generate
// 16-byte-aligned stores as Clang does.
fn AssignN(p: Cpp.A*) {
p->n = 1;
}
fn AssignM(p: Cpp.A*) {
p->m = 1;
}
// --- union.h
union A {
int n;
int m;
};
// --- access_union.carbon
library "[[@TEST_NAME]]";
import Cpp library "union.h";
fn AccessN(a: Cpp.A) -> i32 {
return a.n;
}
fn AccessM(a: Cpp.A) -> i32 {
return a.m;
}
// --- assign_union.carbon
library "[[@TEST_NAME]]";
import Cpp library "union.h";
fn AssignN(p: Cpp.A*) {
p->n = 1;
}
fn AssignM(p: Cpp.A*) {
p->m = 1;
}
// CHECK:STDOUT: ; ModuleID = 'access_struct.carbon'
// CHECK:STDOUT: source_filename = "access_struct.carbon"
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @_CAccessN.Main(ptr %a) !dbg !7 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc9_11.1.n = getelementptr inbounds nuw [32 x i8], ptr %a, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: %.loc9_11.2 = load i32, ptr %.loc9_11.1.n, align 4, !dbg !10
// CHECK:STDOUT: ret i32 %.loc9_11.2, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @_CAccessM.Main(ptr %a) !dbg !12 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc13_11.1.m = getelementptr inbounds nuw [32 x i8], ptr %a, i32 0, i32 16, !dbg !13
// CHECK:STDOUT: %.loc13_11.2 = load i32, ptr %.loc13_11.1.m, align 4, !dbg !13
// CHECK:STDOUT: ret i32 %.loc13_11.2, !dbg !14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
// CHECK:STDOUT:
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
// CHECK:STDOUT: !2 = !{i32 1, !"wchar_size", i32 4}
// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 0}
// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2}
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !6 = !DIFile(filename: "access_struct.carbon", directory: "")
// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "AccessN", linkageName: "_CAccessN.Main", scope: null, file: !6, line: 8, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !8 = !DISubroutineType(types: !9)
// CHECK:STDOUT: !9 = !{}
// CHECK:STDOUT: !10 = !DILocation(line: 9, column: 10, scope: !7)
// CHECK:STDOUT: !11 = !DILocation(line: 9, column: 3, scope: !7)
// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "AccessM", linkageName: "_CAccessM.Main", scope: null, file: !6, line: 12, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !13 = !DILocation(line: 13, column: 10, scope: !12)
// CHECK:STDOUT: !14 = !DILocation(line: 13, column: 3, scope: !12)
// CHECK:STDOUT: ; ModuleID = 'assign_struct.carbon'
// CHECK:STDOUT: source_filename = "assign_struct.carbon"
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
// CHECK:STDOUT:
// CHECK:STDOUT: define void @_CAssignN.Main(ptr %p) !dbg !7 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc9_4.2.n = getelementptr inbounds nuw [32 x i8], ptr %p, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: store i32 1, ptr %.loc9_4.2.n, align 4, !dbg !10
// CHECK:STDOUT: ret void, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define void @_CAssignM.Main(ptr %p) !dbg !12 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc13_4.2.m = getelementptr inbounds nuw [32 x i8], ptr %p, i32 0, i32 16, !dbg !13
// CHECK:STDOUT: store i32 1, ptr %.loc13_4.2.m, align 4, !dbg !13
// CHECK:STDOUT: ret void, !dbg !14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
// CHECK:STDOUT:
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
// CHECK:STDOUT: !2 = !{i32 1, !"wchar_size", i32 4}
// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 0}
// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2}
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !6 = !DIFile(filename: "assign_struct.carbon", directory: "")
// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "AssignN", linkageName: "_CAssignN.Main", scope: null, file: !6, line: 8, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !8 = !DISubroutineType(types: !9)
// CHECK:STDOUT: !9 = !{}
// CHECK:STDOUT: !10 = !DILocation(line: 9, column: 3, scope: !7)
// CHECK:STDOUT: !11 = !DILocation(line: 8, column: 1, scope: !7)
// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "AssignM", linkageName: "_CAssignM.Main", scope: null, file: !6, line: 12, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !13 = !DILocation(line: 13, column: 3, scope: !12)
// CHECK:STDOUT: !14 = !DILocation(line: 12, column: 1, scope: !12)
// CHECK:STDOUT: ; ModuleID = 'access_union.carbon'
// CHECK:STDOUT: source_filename = "access_union.carbon"
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @_CAccessN.Main(ptr %a) !dbg !7 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc7_11.1.n = getelementptr inbounds nuw [4 x i8], ptr %a, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: %.loc7_11.2 = load i32, ptr %.loc7_11.1.n, align 4, !dbg !10
// CHECK:STDOUT: ret i32 %.loc7_11.2, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @_CAccessM.Main(ptr %a) !dbg !12 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc11_11.1.m = getelementptr inbounds nuw [4 x i8], ptr %a, i32 0, i32 0, !dbg !13
// CHECK:STDOUT: %.loc11_11.2 = load i32, ptr %.loc11_11.1.m, align 4, !dbg !13
// CHECK:STDOUT: ret i32 %.loc11_11.2, !dbg !14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
// CHECK:STDOUT:
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
// CHECK:STDOUT: !2 = !{i32 1, !"wchar_size", i32 4}
// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 0}
// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2}
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !6 = !DIFile(filename: "access_union.carbon", directory: "")
// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "AccessN", linkageName: "_CAccessN.Main", scope: null, file: !6, line: 6, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !8 = !DISubroutineType(types: !9)
// CHECK:STDOUT: !9 = !{}
// CHECK:STDOUT: !10 = !DILocation(line: 7, column: 10, scope: !7)
// CHECK:STDOUT: !11 = !DILocation(line: 7, column: 3, scope: !7)
// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "AccessM", linkageName: "_CAccessM.Main", scope: null, file: !6, line: 10, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !13 = !DILocation(line: 11, column: 10, scope: !12)
// CHECK:STDOUT: !14 = !DILocation(line: 11, column: 3, scope: !12)
// CHECK:STDOUT: ; ModuleID = 'assign_union.carbon'
// CHECK:STDOUT: source_filename = "assign_union.carbon"
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
// CHECK:STDOUT:
// CHECK:STDOUT: define void @_CAssignN.Main(ptr %p) !dbg !7 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc7_4.2.n = getelementptr inbounds nuw [4 x i8], ptr %p, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: store i32 1, ptr %.loc7_4.2.n, align 4, !dbg !10
// CHECK:STDOUT: ret void, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define void @_CAssignM.Main(ptr %p) !dbg !12 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc11_4.2.m = getelementptr inbounds nuw [4 x i8], ptr %p, i32 0, i32 0, !dbg !13
// CHECK:STDOUT: store i32 1, ptr %.loc11_4.2.m, align 4, !dbg !13
// CHECK:STDOUT: ret void, !dbg !14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
// CHECK:STDOUT:
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
// CHECK:STDOUT: !2 = !{i32 1, !"wchar_size", i32 4}
// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 0}
// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2}
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !6 = !DIFile(filename: "assign_union.carbon", directory: "")
// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "AssignN", linkageName: "_CAssignN.Main", scope: null, file: !6, line: 6, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !8 = !DISubroutineType(types: !9)
// CHECK:STDOUT: !9 = !{}
// CHECK:STDOUT: !10 = !DILocation(line: 7, column: 3, scope: !7)
// CHECK:STDOUT: !11 = !DILocation(line: 6, column: 1, scope: !7)
// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "AssignM", linkageName: "_CAssignM.Main", scope: null, file: !6, line: 10, type: !8, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !13 = !DILocation(line: 11, column: 3, scope: !12)
// CHECK:STDOUT: !14 = !DILocation(line: 10, column: 1, scope: !12)
+1
View File
@@ -109,6 +109,7 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
case CompleteTypeWitness::Kind:
case ConstType::Kind:
case ConvertToValueAction::Kind:
case CustomLayoutType::Kind:
case FacetAccessType::Kind:
case FacetType::Kind:
case FacetValue::Kind:
+9
View File
@@ -61,6 +61,8 @@ struct ExprRegion {
using ExprRegionStore = ValueStore<ExprRegionId, ExprRegion>;
using CustomLayoutStore = BlockValueStore<CustomLayoutId, uint64_t>;
// Provides semantic analysis on a Parse::Tree.
class File : public Printable<File> {
public:
@@ -210,6 +212,10 @@ class File : public Printable<File> {
auto struct_type_fields() const -> const StructTypeFieldsStore& {
return struct_type_fields_;
}
auto custom_layouts() -> CustomLayoutStore& { return custom_layouts_; }
auto custom_layouts() const -> const CustomLayoutStore& {
return custom_layouts_;
}
auto types() -> TypeStore& { return types_; }
auto types() const -> const TypeStore& { return types_; }
auto insts() -> InstStore& { return insts_; }
@@ -361,6 +367,9 @@ class File : public Printable<File> {
// Storage for StructTypeField lists.
StructTypeFieldsStore struct_type_fields_ = StructTypeFieldsStore(allocator_);
// Storage for custom layouts.
CustomLayoutStore custom_layouts_ = CustomLayoutStore(allocator_);
// Descriptions of types used in this file.
TypeStore types_ = TypeStore(this);
+17
View File
@@ -1006,6 +1006,23 @@ auto Formatter::FormatInstRhs(Inst inst) -> void {
return;
}
case CARBON_KIND(CustomLayoutType type): {
out_ << " {";
auto layout = sem_ir_->custom_layouts().Get(type.layout_id);
out_ << "size=" << layout[CustomLayoutId::SizeIndex]
<< ", align=" << layout[CustomLayoutId::AlignIndex];
for (auto [field, offset] :
llvm::zip(sem_ir_->struct_type_fields().Get(type.fields_id),
layout.drop_front(CustomLayoutId::FirstFieldIndex))) {
out_ << ", .";
FormatName(field.name_id);
out_ << "@" << offset << ": ";
FormatInstAsType(field.type_inst_id);
}
out_ << "}";
return;
}
case CARBON_KIND(FloatLiteral value): {
llvm::SmallVector<char, 16> buffer;
sem_ir_->floats().Get(value.float_id).toString(buffer);
+4 -2
View File
@@ -401,8 +401,10 @@ auto Formatter::FormatEntityStart(llvm::StringRef entity_kind,
if (import_ir_inst_id.has_value()) {
auto import_ir_id =
sem_ir_->import_ir_insts().Get(import_ir_inst_id).ir_id();
const auto* import_file = sem_ir_->import_irs().Get(import_ir_id).sem_ir;
pending_imported_from_ = import_file->filename();
if (const auto* import_file =
sem_ir_->import_irs().Get(import_ir_id).sem_ir) {
pending_imported_from_ = import_file->filename();
}
}
}
+1
View File
@@ -35,6 +35,7 @@ using IdKind = TypeEnum<
ClassId,
CompileTimeBindIndex,
ConstantId,
CustomLayoutId,
DeclInstBlockId,
DestInstId,
ElementIndex,
+20
View File
@@ -728,6 +728,26 @@ struct StructTypeFieldsId : public IdBase<StructTypeFieldsId> {
constexpr StructTypeFieldsId StructTypeFieldsId::Empty = StructTypeFieldsId(0);
// The ID of a `CustomLayout` block.
struct CustomLayoutId : public IdBase<CustomLayoutId> {
static constexpr llvm::StringLiteral Label = "custom_layout";
// The canonical empty block. This is never used, but needed by
// BlockValueStore.
static const CustomLayoutId Empty;
// The index in a custom layout of the overall size field.
static constexpr int SizeIndex = 0;
// The index in a custom layout of the overall alignment field.
static constexpr int AlignIndex = 1;
// The index in a custom layout of the offset of the first struct field.
static constexpr int FirstFieldIndex = 2;
using IdBase::IdBase;
};
constexpr CustomLayoutId CustomLayoutId::Empty = CustomLayoutId(0);
// The ID of a type.
struct TypeId : public IdBase<TypeId> {
static constexpr llvm::StringLiteral Label = "type";
+7 -3
View File
@@ -33,9 +33,13 @@ auto GetCanonicalFileAndInstId(const File* sem_ir, SemIR::InstId inst_id)
if (auto import_ir_inst_id = sem_ir->insts().GetImportSource(inst_id);
import_ir_inst_id.has_value()) {
auto import_ir_inst = sem_ir->import_ir_insts().Get(import_ir_inst_id);
sem_ir = sem_ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir;
inst_id = import_ir_inst.inst_id();
continue;
// TODO: For imports from C++, we return the importing instruction, which
// isn't necessarily canonical.
if (import_ir_inst.ir_id() != ImportIRId::Cpp) {
sem_ir = sem_ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir;
inst_id = import_ir_inst.inst_id();
continue;
}
}
// Step through export declarations to their exported value.
+11
View File
@@ -167,6 +167,17 @@ struct AnyParamPattern {
CallParamIndex index;
};
// A struct-like type with a list of named fields.
struct AnyStructType {
using CategoryInfo = CategoryOf<StructType, CustomLayoutType>;
InstKind kind;
TypeId type_id;
StructTypeFieldsId fields_id;
AnyRawId arg1;
};
} // namespace Carbon::SemIR
#endif // CARBON_TOOLCHAIN_SEM_IR_INST_CATEGORIES_H_
+10
View File
@@ -150,6 +150,16 @@ struct Worklist {
AddBlock(sem_ir->struct_type_fields().Get(struct_type_fields_id));
}
auto Add(CustomLayoutId custom_layout_id) -> void {
if (!custom_layout_id.has_value()) {
AddInvalid();
return;
}
auto block = sem_ir->custom_layouts().Get(custom_layout_id);
contents.push_back(block.size());
contents.insert(contents.end(), block.begin(), block.end());
}
auto Add(NameScopeId name_scope_id) -> void {
if (!name_scope_id.has_value()) {
AddInvalid();
+1
View File
@@ -55,6 +55,7 @@ CARBON_SEM_IR_INST_KIND(CompleteTypeWitness)
CARBON_SEM_IR_INST_KIND(ConstType)
CARBON_SEM_IR_INST_KIND(ConvertToValueAction)
CARBON_SEM_IR_INST_KIND(Converted)
CARBON_SEM_IR_INST_KIND(CustomLayoutType)
CARBON_SEM_IR_INST_KIND(Deref)
CARBON_SEM_IR_INST_KIND(ErrorInst)
CARBON_SEM_IR_INST_KIND(ExportDecl)
+6
View File
@@ -299,6 +299,12 @@ class Stringifier {
step_stack_->PushInstId(inst.inner_id);
}
auto StringifyInst(InstId /*inst_id*/, CustomLayoutType inst) -> void {
auto layout = sem_ir_->custom_layouts().Get(inst.layout_id);
*out_ << "<size " << layout[CustomLayoutId::SizeIndex] << ", align "
<< layout[CustomLayoutId::AlignIndex] << ">";
}
auto StringifyInst(InstId /*inst_id*/, FacetAccessType inst) -> void {
// Given `T:! I`, print `T as type` as simply `T`.
step_stack_->PushInstId(inst.facet_value_inst_id);
+14
View File
@@ -552,6 +552,20 @@ struct ConvertToValueAction {
TypeInstId target_type_inst_id;
};
// A type whose layout is determined externally. This is used as the object
// representation of class types imported from C++.
struct CustomLayoutType {
static constexpr auto Kind = InstKind::CustomLayoutType.Define<Parse::NodeId>(
{.ir_name = "custom_layout_type",
.is_type = InstIsType::Always,
.constant_kind = InstConstantKind::WheneverPossible,
.deduce_through = true});
TypeId type_id;
StructTypeFieldsId fields_id;
CustomLayoutId layout_id;
};
// The `*` dereference operator, as in `*pointer`.
struct Deref {
static constexpr auto Kind =