From 68111a994c2d97f6d90d91a54b2582d220fc41f6 Mon Sep 17 00:00:00 2001 From: Boaz Brickner Date: Thu, 10 Apr 2025 10:15:12 +0200 Subject: [PATCH] C++ Interop: Basic C++ record (class/struct/union) import support (#5156) Focus: Calling static C++ function defined in C++ classes. Limitations: * Ignores visibility (public / protected / private). * No support for: dynamic classes, member methods, data members, declarations without definitions, importing inheritance. Based on #5142. C++ Interop Demo with a class: ```c++ // hello_world.h namespace some_namespace { class MyClass { public: static void hello_world(); }; } // namespace some_namespace ``` ```c++ // hello_world.cpp #include "hello_world.h" #include namespace some_namespace { void MyClass::hello_world() { printf("Hello World!\n"); } } // namespace some_namespace ``` ```carbon // main.carbon library "Main"; import Cpp library "hello_world.h"; fn Run() -> i32 { Cpp.some_namespace.MyClass.hello_world(); return 0; } ``` ```shell $ clang -c hello_world.cpp $ bazel-bin/toolchain/carbon compile main.carbon $ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo $ ./demo Hello World! ``` Part of #5150. --- toolchain/check/BUILD | 2 + toolchain/check/class.cpp | 260 ++++ toolchain/check/class.h | 32 + toolchain/check/handle_class.cpp | 241 +--- toolchain/check/import_cpp.cpp | 125 +- .../interop/cpp/no_prelude/class.carbon | 1136 +++++++++++++++++ .../interop/cpp/no_prelude/struct.carbon | 1126 ++++++++++++++++ .../interop/cpp/no_prelude/union.carbon | 759 +++++++++++ .../no_prelude/unsupported_decl_type.carbon | 4 +- 9 files changed, 3441 insertions(+), 244 deletions(-) create mode 100644 toolchain/check/class.cpp create mode 100644 toolchain/check/class.h create mode 100644 toolchain/check/testdata/interop/cpp/no_prelude/class.carbon create mode 100644 toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon create mode 100644 toolchain/check/testdata/interop/cpp/no_prelude/union.carbon diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index a20e882835c7..ff19f2b76d83 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -17,6 +17,7 @@ cc_library( srcs = [ "action.cpp", "call.cpp", + "class.cpp", "context.cpp", "control_flow.cpp", "convert.cpp", @@ -53,6 +54,7 @@ cc_library( hdrs = [ "action.h", "call.h", + "class.h", "context.h", "control_flow.h", "convert.h", diff --git a/toolchain/check/class.cpp b/toolchain/check/class.cpp new file mode 100644 index 000000000000..a9be43b52455 --- /dev/null +++ b/toolchain/check/class.cpp @@ -0,0 +1,260 @@ +// 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 "toolchain/check/class.h" + +#include "toolchain/check/context.h" +#include "toolchain/check/eval.h" +#include "toolchain/check/function.h" +#include "toolchain/check/import_ref.h" +#include "toolchain/check/inst.h" +#include "toolchain/check/type.h" + +namespace Carbon::Check { + +auto TryGetAsClass(Context& context, SemIR::TypeId type_id) -> SemIR::Class* { + auto class_type = context.types().TryGetAs(type_id); + if (!class_type) { + return nullptr; + } + return &context.classes().Get(class_type->class_id); +} + +auto SetClassSelfType(Context& context, SemIR::ClassId class_id) -> void { + auto& class_info = context.classes().Get(class_id); + auto specific_id = context.generics().GetSelfSpecific(class_info.generic_id); + class_info.self_type_id = GetClassType(context, class_id, specific_id); +} + +auto StartClassDefinition(Context& context, SemIR::Class& class_info, + SemIR::InstId definition_id) -> void { + // Track that this declaration is the definition. + CARBON_CHECK(!class_info.has_definition_started()); + class_info.definition_id = definition_id; + class_info.scope_id = context.name_scopes().Add( + definition_id, SemIR::NameId::None, class_info.parent_scope_id); + + // Introduce `Self`. + context.name_scopes().AddRequiredName( + class_info.scope_id, SemIR::NameId::SelfType, + context.types().GetInstId(class_info.self_type_id)); +} + +// Checks that the specified finished adapter definition is valid and builds and +// returns a corresponding complete type witness instruction. +static auto CheckCompleteAdapterClassType( + Context& context, Parse::NodeId node_id, SemIR::ClassId class_id, + llvm::ArrayRef field_decls, + llvm::ArrayRef body) -> SemIR::InstId { + const auto& class_info = context.classes().Get(class_id); + if (class_info.base_id.has_value()) { + CARBON_DIAGNOSTIC(AdaptWithBase, Error, "adapter with base class"); + CARBON_DIAGNOSTIC(AdaptWithBaseHere, Note, "`base` declaration is here"); + context.emitter() + .Build(class_info.adapt_id, AdaptWithBase) + .Note(class_info.base_id, AdaptWithBaseHere) + .Emit(); + return SemIR::ErrorInst::SingletonInstId; + } + + if (!field_decls.empty()) { + CARBON_DIAGNOSTIC(AdaptWithFields, Error, "adapter with fields"); + CARBON_DIAGNOSTIC(AdaptWithFieldHere, Note, + "first field declaration is here"); + context.emitter() + .Build(class_info.adapt_id, AdaptWithFields) + .Note(field_decls.front(), AdaptWithFieldHere) + .Emit(); + return SemIR::ErrorInst::SingletonInstId; + } + + for (auto inst_id : body) { + if (auto function_decl = + context.insts().TryGetAs(inst_id)) { + auto& function = context.functions().Get(function_decl->function_id); + if (function.virtual_modifier == + SemIR::Function::VirtualModifier::Virtual) { + CARBON_DIAGNOSTIC(AdaptWithVirtual, Error, + "adapter with virtual function"); + CARBON_DIAGNOSTIC(AdaptWithVirtualHere, Note, + "first virtual function declaration is here"); + context.emitter() + .Build(class_info.adapt_id, AdaptWithVirtual) + .Note(inst_id, AdaptWithVirtualHere) + .Emit(); + return SemIR::ErrorInst::SingletonInstId; + } + } + } + + // The object representation of the adapter is the object representation + // of the adapted type. + auto adapted_type_id = + class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::None); + auto object_repr_id = context.types().GetObjectRepr(adapted_type_id); + + return AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::WitnessType::SingletonInstId), + .object_repr_id = object_repr_id}); +} + +static auto AddStructTypeFields( + Context& context, + llvm::SmallVector& struct_type_fields, + llvm::ArrayRef field_decls) -> SemIR::StructTypeFieldsId { + for (auto field_decl_id : field_decls) { + auto field_decl = context.insts().GetAs(field_decl_id); + field_decl.index = + SemIR::ElementIndex{static_cast(struct_type_fields.size())}; + ReplaceInstPreservingConstantValue(context, field_decl_id, field_decl); + if (field_decl.type_id == SemIR::ErrorInst::SingletonTypeId) { + struct_type_fields.push_back( + {.name_id = field_decl.name_id, + .type_id = SemIR::ErrorInst::SingletonTypeId}); + continue; + } + auto unbound_element_type = + context.sem_ir().types().GetAs( + field_decl.type_id); + struct_type_fields.push_back( + {.name_id = field_decl.name_id, + .type_id = context.types().GetTypeIdForTypeInstId( + unbound_element_type.element_type_inst_id)}); + } + auto fields_id = + context.struct_type_fields().AddCanonical(struct_type_fields); + return fields_id; +} + +// Builds and returns a vtable for the current class. Assumes that the virtual +// functions for the class are listed as the top element of the `vtable_stack`. +static auto BuildVtable(Context& context, Parse::NodeId node_id, + SemIR::InstId base_vtable_id, + llvm::ArrayRef vtable_contents) + -> SemIR::InstId { + llvm::SmallVector vtable; + if (base_vtable_id.has_value()) { + LoadImportRef(context, base_vtable_id); + auto canonical_base_vtable_id = + context.constant_values().GetConstantInstId(base_vtable_id); + if (canonical_base_vtable_id == SemIR::ErrorInst::SingletonInstId) { + return SemIR::ErrorInst::SingletonInstId; + } + auto base_vtable_inst_block = context.inst_blocks().Get( + context.insts() + .GetAs(canonical_base_vtable_id) + .virtual_functions_id); + // TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the + // elements of the top of `vtable_stack`. + for (auto fn_decl_id : base_vtable_inst_block) { + auto fn_decl = GetCalleeFunction(context.sem_ir(), fn_decl_id); + const auto& fn = context.functions().Get(fn_decl.function_id); + for (auto override_fn_decl_id : vtable_contents) { + auto override_fn_decl = + context.insts().GetAs(override_fn_decl_id); + const auto& override_fn = + context.functions().Get(override_fn_decl.function_id); + if (override_fn.virtual_modifier == + SemIR::FunctionFields::VirtualModifier::Impl && + override_fn.name_id == fn.name_id) { + // TODO: Support generic base classes, rather than passing + // `SpecificId::None`. + CheckFunctionTypeMatches(context, override_fn, fn, + SemIR::SpecificId::None, + /*check_syntax=*/false, + /*check_self=*/false); + fn_decl_id = override_fn_decl_id; + } + } + vtable.push_back(fn_decl_id); + } + } + + for (auto inst_id : vtable_contents) { + auto fn_decl = context.insts().GetAs(inst_id); + const auto& fn = context.functions().Get(fn_decl.function_id); + if (fn.virtual_modifier != SemIR::FunctionFields::VirtualModifier::Impl) { + vtable.push_back(inst_id); + } + } + return AddInst( + context, node_id, + {.type_id = GetSingletonType(context, SemIR::VtableType::SingletonInstId), + .virtual_functions_id = context.inst_blocks().Add(vtable)}); +} + +// Checks that the specified finished class definition is valid and builds and +// returns a corresponding complete type witness instruction. +static auto CheckCompleteClassType( + Context& context, Parse::NodeId node_id, SemIR::ClassId class_id, + llvm::ArrayRef field_decls, + llvm::ArrayRef vtable_contents, + llvm::ArrayRef body) -> SemIR::InstId { + auto& class_info = context.classes().Get(class_id); + if (class_info.adapt_id.has_value()) { + return CheckCompleteAdapterClassType(context, node_id, class_id, + field_decls, body); + } + + bool defining_vptr = class_info.is_dynamic; + auto base_type_id = + class_info.GetBaseType(context.sem_ir(), SemIR::SpecificId::None); + SemIR::Class* base_class_info = nullptr; + if (base_type_id.has_value()) { + // TODO: If the base class is template dependent, we will need to decide + // whether to add a vptr as part of instantiation. + base_class_info = TryGetAsClass(context, base_type_id); + if (base_class_info && base_class_info->is_dynamic) { + defining_vptr = false; + } + } + + llvm::SmallVector struct_type_fields; + struct_type_fields.reserve(defining_vptr + class_info.base_id.has_value() + + field_decls.size()); + if (defining_vptr) { + struct_type_fields.push_back( + {.name_id = SemIR::NameId::Vptr, + .type_id = + GetPointerType(context, SemIR::VtableType::SingletonInstId)}); + } + if (base_type_id.has_value()) { + auto base_decl = context.insts().GetAs(class_info.base_id); + base_decl.index = + SemIR::ElementIndex{static_cast(struct_type_fields.size())}; + ReplaceInstPreservingConstantValue(context, class_info.base_id, base_decl); + struct_type_fields.push_back( + {.name_id = SemIR::NameId::Base, .type_id = base_type_id}); + } + + if (class_info.is_dynamic) { + class_info.vtable_id = BuildVtable( + context, node_id, + defining_vptr ? SemIR::InstId::None : base_class_info->vtable_id, + vtable_contents); + } + + return AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::WitnessType::SingletonInstId), + .object_repr_id = GetStructType( + context, + AddStructTypeFields(context, struct_type_fields, field_decls))}); +} + +auto ComputeClassObjectRepr(Context& context, Parse::NodeId node_id, + SemIR::ClassId class_id, + llvm::ArrayRef field_decls, + llvm::ArrayRef vtable_contents, + llvm::ArrayRef body) -> void { + auto complete_type_witness_id = CheckCompleteClassType( + context, node_id, class_id, field_decls, vtable_contents, body); + auto& class_info = context.classes().Get(class_id); + class_info.complete_type_witness_id = complete_type_witness_id; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/class.h b/toolchain/check/class.h new file mode 100644 index 000000000000..5e2101fc0325 --- /dev/null +++ b/toolchain/check/class.h @@ -0,0 +1,32 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_CLASS_H_ +#define CARBON_TOOLCHAIN_CHECK_CLASS_H_ + +#include "toolchain/check/context.h" + +namespace Carbon::Check { + +// If `type_id` is a class type, get its corresponding `SemIR::Class` object. +// Otherwise returns `nullptr`. +auto TryGetAsClass(Context& context, SemIR::TypeId type_id) -> SemIR::Class*; + +// Sets the `Self` type for the class. +auto SetClassSelfType(Context& context, SemIR::ClassId class_id) -> void; + +// Starts the class definition, adding `Self` to name lookup. +auto StartClassDefinition(Context& context, SemIR::Class& class_info, + SemIR::InstId definition_id) -> void; + +// Computes the object representation for a fully defined class. +auto ComputeClassObjectRepr(Context& context, Parse::NodeId node_id, + SemIR::ClassId class_id, + llvm::ArrayRef field_decls, + llvm::ArrayRef vtable_contents, + llvm::ArrayRef body) -> void; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_CLASS_H_ diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 9eb6f805bc14..c67b421d339c 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "toolchain/base/kind_switch.h" +#include "toolchain/check/class.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/decl_name_stack.h" @@ -27,17 +28,6 @@ namespace Carbon::Check { -// If `type_id` is a class type, get its corresponding `SemIR::Class` object. -// Otherwise returns `nullptr`. -static auto TryGetAsClass(Context& context, SemIR::TypeId type_id) - -> SemIR::Class* { - auto class_type = context.types().TryGetAs(type_id); - if (!class_type) { - return nullptr; - } - return &context.classes().Get(class_type->class_id); -} - auto HandleParseNode(Context& context, Parse::ClassIntroducerId node_id) -> bool { // Create an instruction block to hold the instructions created as part of the @@ -260,14 +250,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl); if (is_new_class) { - // Build the `Self` type using the resulting type constant. // TODO: Form this as part of building the definition, not as part of the // declaration. - auto& class_info = context.classes().Get(class_decl.class_id); - auto specific_id = - context.generics().GetSelfSpecific(class_info.generic_id); - class_info.self_type_id = - GetClassType(context, class_decl.class_id, specific_id); + SetClassSelfType(context, class_decl.class_id); } if (!is_definition && context.sem_ir().is_impl() && !is_extern) { @@ -288,12 +273,7 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id) auto [class_id, class_decl_id] = BuildClassDecl(context, node_id, /*is_definition=*/true); auto& class_info = context.classes().Get(class_id); - - // Track that this declaration is the definition. - CARBON_CHECK(!class_info.has_definition_started()); - class_info.definition_id = class_decl_id; - class_info.scope_id = context.name_scopes().Add( - class_decl_id, SemIR::NameId::None, class_info.parent_scope_id); + StartClassDefinition(context, class_info, class_decl_id); // Enter the class scope. context.scope_stack().Push( @@ -301,11 +281,6 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id) context.generics().GetSelfSpecific(class_info.generic_id)); StartGenericDefinition(context); - // Introduce `Self`. - context.name_scopes().AddRequiredName( - class_info.scope_id, SemIR::NameId::SelfType, - context.types().GetInstId(class_info.self_type_id)); - context.inst_block_stack().Push(); context.node_stack().Push(node_id, class_id); context.field_decls_stack().PushArray(); @@ -578,222 +553,22 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { return true; } -// Checks that the specified finished adapter definition is valid and builds and -// returns a corresponding complete type witness instruction. -static auto CheckCompleteAdapterClassType(Context& context, - Parse::NodeId node_id, - SemIR::ClassId class_id) - -> SemIR::InstId { - const auto& class_info = context.classes().Get(class_id); - if (class_info.base_id.has_value()) { - CARBON_DIAGNOSTIC(AdaptWithBase, Error, "adapter with base class"); - CARBON_DIAGNOSTIC(AdaptWithBaseHere, Note, "`base` declaration is here"); - context.emitter() - .Build(class_info.adapt_id, AdaptWithBase) - .Note(class_info.base_id, AdaptWithBaseHere) - .Emit(); - return SemIR::ErrorInst::SingletonInstId; - } - - auto field_decls = context.field_decls_stack().PeekArray(); - if (!field_decls.empty()) { - CARBON_DIAGNOSTIC(AdaptWithFields, Error, "adapter with fields"); - CARBON_DIAGNOSTIC(AdaptWithFieldHere, Note, - "first field declaration is here"); - context.emitter() - .Build(class_info.adapt_id, AdaptWithFields) - .Note(field_decls.front(), AdaptWithFieldHere) - .Emit(); - return SemIR::ErrorInst::SingletonInstId; - } - - for (auto inst_id : context.inst_block_stack().PeekCurrentBlockContents()) { - if (auto function_decl = - context.insts().TryGetAs(inst_id)) { - auto& function = context.functions().Get(function_decl->function_id); - if (function.virtual_modifier == - SemIR::Function::VirtualModifier::Virtual) { - CARBON_DIAGNOSTIC(AdaptWithVirtual, Error, - "adapter with virtual function"); - CARBON_DIAGNOSTIC(AdaptWithVirtualHere, Note, - "first virtual function declaration is here"); - context.emitter() - .Build(class_info.adapt_id, AdaptWithVirtual) - .Note(inst_id, AdaptWithVirtualHere) - .Emit(); - return SemIR::ErrorInst::SingletonInstId; - } - } - } - - // The object representation of the adapter is the object representation - // of the adapted type. - auto adapted_type_id = - class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::None); - auto object_repr_id = context.types().GetObjectRepr(adapted_type_id); - - return AddInst( - context, node_id, - {.type_id = - GetSingletonType(context, SemIR::WitnessType::SingletonInstId), - .object_repr_id = object_repr_id}); -} - -static auto AddStructTypeFields( - Context& context, - llvm::SmallVector& struct_type_fields) - -> SemIR::StructTypeFieldsId { - for (auto field_decl_id : context.field_decls_stack().PeekArray()) { - auto field_decl = context.insts().GetAs(field_decl_id); - field_decl.index = - SemIR::ElementIndex{static_cast(struct_type_fields.size())}; - ReplaceInstPreservingConstantValue(context, field_decl_id, field_decl); - if (field_decl.type_id == SemIR::ErrorInst::SingletonTypeId) { - struct_type_fields.push_back( - {.name_id = field_decl.name_id, - .type_id = SemIR::ErrorInst::SingletonTypeId}); - continue; - } - auto unbound_element_type = - context.sem_ir().types().GetAs( - field_decl.type_id); - struct_type_fields.push_back( - {.name_id = field_decl.name_id, - .type_id = context.types().GetTypeIdForTypeInstId( - unbound_element_type.element_type_inst_id)}); - } - auto fields_id = - context.struct_type_fields().AddCanonical(struct_type_fields); - return fields_id; -} - -// Builds and returns a vtable for the current class. Assumes that the virtual -// functions for the class are listed as the top element of the `vtable_stack`. -static auto BuildVtable(Context& context, Parse::NodeId node_id, - SemIR::InstId base_vtable_id) -> SemIR::InstId { - llvm::SmallVector vtable; - if (base_vtable_id.has_value()) { - LoadImportRef(context, base_vtable_id); - auto canonical_base_vtable_id = - context.constant_values().GetConstantInstId(base_vtable_id); - if (canonical_base_vtable_id == SemIR::ErrorInst::SingletonInstId) { - return SemIR::ErrorInst::SingletonInstId; - } - auto base_vtable_inst_block = context.inst_blocks().Get( - context.insts() - .GetAs(canonical_base_vtable_id) - .virtual_functions_id); - // TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the - // elements of the top of `vtable_stack`. - for (auto fn_decl_id : base_vtable_inst_block) { - auto fn_decl = GetCalleeFunction(context.sem_ir(), fn_decl_id); - const auto& fn = context.functions().Get(fn_decl.function_id); - for (auto override_fn_decl_id : - context.vtable_stack().PeekCurrentBlockContents()) { - auto override_fn_decl = - context.insts().GetAs(override_fn_decl_id); - const auto& override_fn = - context.functions().Get(override_fn_decl.function_id); - if (override_fn.virtual_modifier == - SemIR::FunctionFields::VirtualModifier::Impl && - override_fn.name_id == fn.name_id) { - // TODO: Support generic base classes, rather than passing - // `SpecificId::None`. - CheckFunctionTypeMatches(context, override_fn, fn, - SemIR::SpecificId::None, - /*check_syntax=*/false, - /*check_self=*/false); - fn_decl_id = override_fn_decl_id; - } - } - vtable.push_back(fn_decl_id); - } - } - - for (auto inst_id : context.vtable_stack().PeekCurrentBlockContents()) { - auto fn_decl = context.insts().GetAs(inst_id); - const auto& fn = context.functions().Get(fn_decl.function_id); - if (fn.virtual_modifier != SemIR::FunctionFields::VirtualModifier::Impl) { - vtable.push_back(inst_id); - } - } - return AddInst( - context, node_id, - {.type_id = GetSingletonType(context, SemIR::VtableType::SingletonInstId), - .virtual_functions_id = context.inst_blocks().Add(vtable)}); -} - -// Checks that the specified finished class definition is valid and builds and -// returns a corresponding complete type witness instruction. -static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id, - SemIR::ClassId class_id) -> SemIR::InstId { - auto& class_info = context.classes().Get(class_id); - if (class_info.adapt_id.has_value()) { - return CheckCompleteAdapterClassType(context, node_id, class_id); - } - - bool defining_vptr = class_info.is_dynamic; - auto base_type_id = - class_info.GetBaseType(context.sem_ir(), SemIR::SpecificId::None); - SemIR::Class* base_class_info = nullptr; - if (base_type_id.has_value()) { - // TODO: If the base class is template dependent, we will need to decide - // whether to add a vptr as part of instantiation. - base_class_info = TryGetAsClass(context, base_type_id); - if (base_class_info && base_class_info->is_dynamic) { - defining_vptr = false; - } - } - - auto field_decls = context.field_decls_stack().PeekArray(); - llvm::SmallVector struct_type_fields; - struct_type_fields.reserve(defining_vptr + class_info.base_id.has_value() + - field_decls.size()); - if (defining_vptr) { - struct_type_fields.push_back( - {.name_id = SemIR::NameId::Vptr, - .type_id = - GetPointerType(context, SemIR::VtableType::SingletonInstId)}); - } - if (base_type_id.has_value()) { - auto base_decl = context.insts().GetAs(class_info.base_id); - base_decl.index = - SemIR::ElementIndex{static_cast(struct_type_fields.size())}; - ReplaceInstPreservingConstantValue(context, class_info.base_id, base_decl); - struct_type_fields.push_back( - {.name_id = SemIR::NameId::Base, .type_id = base_type_id}); - } - - if (class_info.is_dynamic) { - class_info.vtable_id = BuildVtable( - context, node_id, - defining_vptr ? SemIR::InstId::None : base_class_info->vtable_id); - } - - return AddInst( - context, node_id, - {.type_id = - GetSingletonType(context, SemIR::WitnessType::SingletonInstId), - .object_repr_id = GetStructType( - context, AddStructTypeFields(context, struct_type_fields))}); -} - auto HandleParseNode(Context& context, Parse::ClassDefinitionId node_id) -> bool { auto class_id = context.node_stack().Pop(); // The class type is now fully defined. Compute its object representation. - auto complete_type_witness_id = - CheckCompleteClassType(context, node_id, class_id); - auto& class_info = context.classes().Get(class_id); - class_info.complete_type_witness_id = complete_type_witness_id; + ComputeClassObjectRepr(context, node_id, class_id, + context.field_decls_stack().PeekArray(), + context.vtable_stack().PeekCurrentBlockContents(), + context.inst_block_stack().PeekCurrentBlockContents()); context.inst_block_stack().Pop(); context.field_decls_stack().PopArray(); context.vtable_stack().Pop(); - FinishGenericDefinition(context, class_info.generic_id); + FinishGenericDefinition(context, context.classes().Get(class_id).generic_id); // The decl_name_stack and scopes are popped by `ProcessNodeIds`. return true; diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index 05d1df379c9f..f1b7df447e35 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -15,9 +15,11 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" +#include "toolchain/check/class.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/diagnostic_helpers.h" +#include "toolchain/check/eval.h" #include "toolchain/check/import.h" #include "toolchain/check/inst.h" #include "toolchain/check/literal.h" @@ -218,8 +220,8 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path, // Look ups the given name in the Clang AST in a specific scope. Returns the // lookup result if lookup was successful. -static auto ClangLookup(Context& context, SemIR::LocId loc_id, - SemIR::NameScopeId scope_id, SemIR::NameId name_id) +static auto ClangLookup(Context& context, SemIR::NameScopeId scope_id, + SemIR::NameId name_id) -> std::optional { std::optional name = context.names().GetAsStringIfIdentifier(name_id); @@ -239,16 +241,14 @@ static auto ClangLookup(Context& context, SemIR::LocId loc_id, sema.getPreprocessor().getIdentifierInfo(*name)), clang::SourceLocation()), clang::Sema::LookupNameKind::LookupOrdinaryName); + // TODO: Diagnose on access and return the `AccessKind` for storage. We'll + // probably need a dedicated `DiagnosticConsumer` because + // `TextDiagnosticPrinter` assumes we're processing a C++ source file. + lookup.suppressDiagnostics(); bool found = sema.LookupQualifiedName( lookup, context.name_scopes().Get(scope_id).cpp_decl_context()); - if (lookup.isClassLookup()) { - // TODO: To support class lookup, also return the AccessKind for storage. - context.TODO(loc_id, "Unsupported: Lookup in Class"); - return std::nullopt; - } - if (!found) { return std::nullopt; } @@ -433,6 +433,108 @@ static auto ImportNamespaceDecl(Context& context, return result.inst_id; } +// 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, + SemIR::NameId name_id) + -> std::tuple { + // Add the class declaration. + auto class_decl = + SemIR::ClassDecl{.type_id = SemIR::TypeType::SingletonTypeId, + .class_id = SemIR::ClassId::None, + .decl_block_id = SemIR::InstBlockId::None}; + // TODO: Consider setting a proper location. + auto class_decl_id = + AddPlaceholderInst(context, SemIR::LocIdAndInst::NoLoc(class_decl)); + + SemIR::Class class_info = { + {.name_id = name_id, + .parent_scope_id = parent_scope_id, + .generic_id = SemIR::GenericId::None, + .first_param_node_id = Parse::NodeId::None, + .last_param_node_id = Parse::NodeId::None, + .pattern_block_id = SemIR::InstBlockId::None, + .implicit_param_patterns_id = SemIR::InstBlockId::None, + .param_patterns_id = SemIR::InstBlockId::None, + .is_extern = false, + .extern_library_id = SemIR::LibraryNameId::None, + .non_owning_decl_id = SemIR::InstId::None, + .first_owning_decl_id = class_decl_id}, + {// `.self_type_id` depends on the ClassType, so is set below. + .self_type_id = SemIR::TypeId::None, + // TODO: Support Dynamic classes. + // TODO: Support Final classes. + .inheritance_kind = SemIR::Class::Base}}; + + class_decl.class_id = context.classes().Add(class_info); + + // Write the class ID into the ClassDecl. + ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl); + + SetClassSelfType(context, class_decl.class_id); + + return {class_decl.class_id, class_decl_id}; +} + +// Creates a class definition for the given class name in the given scope based +// on the information in the given Clang declaration. Returns the `InstId` for +// the declaration, which is assumed to be for a class definition. Returns the +// new class id and instruction id. +static auto BuildClassDefinition(Context& context, + SemIR::NameScopeId parent_scope_id, + SemIR::NameId name_id, + clang::CXXRecordDecl* clang_decl) + -> std::tuple { + auto [class_id, class_decl_id] = + BuildClassDecl(context, parent_scope_id, name_id); + auto& class_info = context.classes().Get(class_id); + StartClassDefinition(context, class_info, class_decl_id); + + context.name_scopes() + .Get(class_info.scope_id) + .set_cpp_decl_context(clang_decl); + + return {class_id, class_decl_id}; +} + +// 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, + SemIR::NameScopeId parent_scope_id, + SemIR::NameId name_id, + 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"); + return SemIR::ErrorInst::SingletonInstId; + } + + if (clang_def->isDynamicClass()) { + context.TODO(loc_id, "Unsupported: Dynamic Class"); + return SemIR::ErrorInst::SingletonInstId; + } + + auto [class_id, class_def_id] = + BuildClassDefinition(context, parent_scope_id, name_id, clang_def); + + // The class type is now fully defined. Compute its object representation. + ComputeClassObjectRepr(context, + // TODO: Consider having a proper location here. + Parse::NodeId::None, class_id, + // TODO: Set fields. + /*field_decls=*/{}, + // TODO: Set vtable. + /*vtable_contents=*/{}, + // TODO: Set block. + /*body=*/{}); + + return class_def_id; +} + // Imports a declaration from Clang to Carbon. If successful, returns the // instruction for the new Carbon declaration. static auto ImportNameDecl(Context& context, SemIR::LocId loc_id, @@ -448,6 +550,11 @@ static auto ImportNameDecl(Context& context, SemIR::LocId loc_id, return ImportNamespaceDecl(context, scope_id, name_id, clang_namespace_decl); } + if (auto* clang_record_decl = + clang::dyn_cast(clang_decl)) { + return ImportCXXRecordDecl(context, loc_id, scope_id, name_id, + clang_record_decl); + } context.TODO(loc_id, llvm::formatv("Unsupported: Declaration type {0}", clang_decl->getDeclKindName()) @@ -465,7 +572,7 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id, builder.Note(loc_id, InCppNameLookup, name_id); }); - auto lookup = ClangLookup(context, loc_id, scope_id, name_id); + auto lookup = ClangLookup(context, scope_id, name_id); if (!lookup) { return SemIR::InstId::None; } diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/class.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/class.carbon new file mode 100644 index 000000000000..4b036cf5ac43 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/no_prelude/class.carbon @@ -0,0 +1,1136 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/no_prelude/class.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/no_prelude/class.carbon + +// --- class_declaration.h + +class Bar; + +// --- fail_import_class_declaration.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_declaration.h"; + +// CHECK:STDERR: fail_import_class_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_import_class_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*); + +// --- class_definition.h + +class Bar {}; + +// --- import_class_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- class_declaration_and_definition.h + +class Bar; +class Bar {}; + +// --- import_class_declaration_and_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_declaration_and_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- class_public_static_member_function.h + +class Bar { + public: + static auto foo() -> void; +}; + +// --- import_class_public_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_public_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- class_private_static_member_function.h + +class Bar { + private: + static auto foo() -> void; +}; + +// --- todo_fail_import_class_private_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_private_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- class_public_member_function.h + +class Bar { + public: + auto foo() -> void; +}; + +// --- fail_import_class_public_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_public_member_function.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_class_public_member_function.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Non-global function` [SemanticsTodo] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_import_class_public_member_function.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: + bar->foo(); +} + +// --- class_public_static_data_member.h + +class Bar { + public: + static Bar* foo; +}; + +// --- fail_import_class_public_static_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_public_static_data_member.h"; + +fn MyF() { + // CHECK:STDERR: fail_import_class_public_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: fail_import_class_public_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_import_class_public_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + let bar: Cpp.Bar* = Cpp.Bar.foo(); +} + +// --- class_public_data_member.h + +class Bar { + public: + Bar* foo; +}; + +// --- fail_import_class_public_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_public_static_data_member.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_class_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_import_class_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_import_class_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; +} + +// --- class_inheritance_static.h + +class Bar1 { + public: + static auto foo1() -> void; +}; + +class Bar2 : public Bar1 { + public: + static auto foo2() -> void; +}; + +// --- import_class_inheritance_static.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_inheritance_static.h"; + +fn MyF() { + Cpp.Bar1.foo1(); + Cpp.Bar2.foo1(); + Cpp.Bar2.foo2(); +} + +// --- class_inheritance_pointers.h + +class Bar1 {}; +class Bar2 : public Bar1 {}; + +// --- fail_import_class_inheritance_pointers.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_inheritance_pointers.h"; + +fn MyF1(bar : Cpp.Bar1*); +// TODO: Support C++ inheritance. +// CHECK:STDERR: fail_import_class_inheritance_pointers.carbon:[[@LINE+7]]:33: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound] +// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); } +// CHECK:STDERR: ^~~ +// CHECK:STDERR: fail_import_class_inheritance_pointers.carbon:[[@LINE-5]]:9: note: initializing function parameter [InCallToFunctionParam] +// CHECK:STDERR: fn MyF1(bar : Cpp.Bar1*); +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); } + +// --- class_dynamic.h + +class Bar { + public: + virtual ~Bar(); +}; + +// --- fail_import_class_dynamic.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_dynamic.h"; + +// CHECK:STDERR: fail_import_class_dynamic.carbon:[[@LINE+7]]:14: error: semantics TODO: `Unsupported: Dynamic Class` [SemanticsTodo] +// CHECK:STDERR: fn MyF(bar : Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_import_class_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*); + +// --- class_to_inherit_public.h + +class Bar { + public: + static auto foo() -> void; +}; + +// --- import_class_to_inherit_public.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_to_inherit_public.h"; + +class Derived { + extend base: Cpp.Bar; +} + +fn MyF() { + Derived.foo(); +} + +// --- class_to_inherit_private.h + +class Bar { + private: + static auto foo() -> void; +}; + +// --- todo_fail_class_to_inherit_private.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_to_inherit_private.h"; + +class Derived { + extend base: Cpp.Bar; +} + +fn MyF() { + Derived.foo(); +} + +// --- class_template.h + +template +class Bar {}; + +// --- fail_import_class_template.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "class_template.h"; + +// CHECK:STDERR: fail_import_class_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_import_class_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_class_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn MyF(bar: Cpp.Bar*); + +// CHECK:STDOUT: --- fail_import_class_declaration.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_declaration.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc13: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_class_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_class_declaration_and_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_declaration_and_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_class_public_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_public_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_import_class_private_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_private_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_public_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_public_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %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: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc14: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_public_static_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc18_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18_26: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc18_15: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc18_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_public_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr.loc6 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc6: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc6: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc6: type = ptr_type %Bar.ref.loc6 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %foo_bar.patt: %ptr.f68 = binding_pattern foo_bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc18_30: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18_23: type = splice_block %ptr.loc18 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc18: type = ptr_type %Bar.ref.loc18 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_class_inheritance_static.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar1: type = class_type @Bar1 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo1.type.148: type = fn_type @foo1.1 [concrete] +// CHECK:STDOUT: %foo1.8cd: %foo1.type.148 = struct_value () [concrete] +// CHECK:STDOUT: %Bar2: type = class_type @Bar2 [concrete] +// CHECK:STDOUT: %foo1.type.0b8: type = fn_type @foo1.2 [concrete] +// CHECK:STDOUT: %foo1.ba2: %foo1.type.0b8 = struct_value () [concrete] +// CHECK:STDOUT: %foo2.type: type = fn_type @foo2 [concrete] +// CHECK:STDOUT: %foo2: %foo2.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar1 = @MyF.%Bar1.decl +// CHECK:STDOUT: .Bar2 = @MyF.%Bar2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_inheritance_static.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar1 { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar1 +// CHECK:STDOUT: .foo1 = @MyF.%foo1.decl.1 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar2 { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type.2 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar2 +// CHECK:STDOUT: .foo1 = @MyF.%foo1.decl.2 +// CHECK:STDOUT: .foo2 = @MyF.%foo2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc7: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar1.decl: type = class_decl @Bar1 [concrete = constants.%Bar1] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, %Bar1.decl [concrete = constants.%Bar1] +// CHECK:STDOUT: %foo1.decl.1: %foo1.type.148 = fn_decl @foo1.1 [concrete = constants.%foo1.8cd] {} {} +// CHECK:STDOUT: %foo1.ref.loc7: %foo1.type.148 = name_ref foo1, %foo1.decl.1 [concrete = constants.%foo1.8cd] +// CHECK:STDOUT: %foo1.call.loc7: init %empty_tuple.type = call %foo1.ref.loc7() +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.decl: type = class_decl @Bar2 [concrete = constants.%Bar2] {} {} +// CHECK:STDOUT: %complete_type.2: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar2.ref.loc8: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %foo1.decl.2: %foo1.type.0b8 = fn_decl @foo1.2 [concrete = constants.%foo1.ba2] {} {} +// CHECK:STDOUT: %foo1.ref.loc8: %foo1.type.0b8 = name_ref foo1, %foo1.decl.2 [concrete = constants.%foo1.ba2] +// CHECK:STDOUT: %foo1.call.loc8: init %empty_tuple.type = call %foo1.ref.loc8() +// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.ref.loc9: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %foo2.decl: %foo2.type = fn_decl @foo2 [concrete = constants.%foo2] {} {} +// CHECK:STDOUT: %foo2.ref: %foo2.type = name_ref foo2, %foo2.decl [concrete = constants.%foo2] +// CHECK:STDOUT: %foo2.call: init %empty_tuple.type = call %foo2.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo1.1[](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo1.2[](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo2[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_inheritance_pointers.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar1: type = class_type @Bar1 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar1 [concrete] +// CHECK:STDOUT: %MyF1.type: type = fn_type @MyF1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF1: %MyF1.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar2: type = class_type @Bar2 [concrete] +// CHECK:STDOUT: %ptr.eca: type = ptr_type %Bar2 [concrete] +// CHECK:STDOUT: %MyF2.type: type = fn_type @MyF2 [concrete] +// CHECK:STDOUT: %MyF2: %MyF2.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar1 = @MyF1.%Bar1.decl +// CHECK:STDOUT: .Bar2 = @MyF2.%Bar2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF1 = %MyF1.decl +// CHECK:STDOUT: .MyF2 = %MyF2.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_inheritance_pointers.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF1.decl: %MyF1.type = fn_decl @MyF1 [concrete = constants.%MyF1] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar1.decl: type = class_decl @Bar1 [concrete = constants.%Bar1] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, %Bar1.decl [concrete = constants.%Bar1] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar1.ref [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF2.decl: %MyF2.type = fn_decl @MyF2 [concrete = constants.%MyF2] { +// CHECK:STDOUT: %bar.patt: %ptr.eca = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.eca = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.eca = value_param call_param0 +// CHECK:STDOUT: %.loc15_23: type = splice_block %ptr [concrete = constants.%ptr.eca] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.decl: type = class_decl @Bar2 [concrete = constants.%Bar2] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar2.ref: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar2.ref [concrete = constants.%ptr.eca] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.eca = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar1 { +// CHECK:STDOUT: complete_type_witness = @MyF1.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar1 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar2 { +// CHECK:STDOUT: complete_type_witness = @MyF2.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar2 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF1(%bar.param_patt: %ptr.f68); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF2(%bar.param_patt: %ptr.eca) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %MyF1.ref: %MyF1.type = name_ref MyF1, file.%MyF1.decl [concrete = constants.%MyF1] +// CHECK:STDOUT: %bar.ref: %ptr.eca = name_ref bar, %bar +// CHECK:STDOUT: %.loc15_33: %ptr.f68 = converted %bar.ref, [concrete = ] +// CHECK:STDOUT: %MyF1.call: init %empty_tuple.type = call %MyF1.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_dynamic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_dynamic.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc13: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_class_to_inherit_public.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Derived.elem: type = unbound_element_type %Derived, %Bar [concrete] +// CHECK:STDOUT: %struct_type.base.36d: type = struct_type {.base: %Bar} [concrete] +// CHECK:STDOUT: %complete_type.fff: = complete_type_witness %struct_type.base.36d [concrete] +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @Derived.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_to_inherit_public.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {} +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %.loc7: %Derived.elem = base_decl %Bar.ref, element0 [concrete] +// CHECK:STDOUT: %complete_type.loc8: = complete_type_witness %struct_type.base.36d [concrete = constants.%complete_type.fff] +// CHECK:STDOUT: complete_type_witness = %complete_type.loc8 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .Cpp = +// CHECK:STDOUT: .base = %.loc7 +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: extend %Bar.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @Derived.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_class_to_inherit_private.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Derived.elem: type = unbound_element_type %Derived, %Bar [concrete] +// CHECK:STDOUT: %struct_type.base.36d: type = struct_type {.base: %Bar} [concrete] +// CHECK:STDOUT: %complete_type.fff: = complete_type_witness %struct_type.base.36d [concrete] +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @Derived.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_to_inherit_private.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {} +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %.loc7: %Derived.elem = base_decl %Bar.ref, element0 [concrete] +// CHECK:STDOUT: %complete_type.loc8: = complete_type_witness %struct_type.base.36d [concrete = constants.%complete_type.fff] +// CHECK:STDOUT: complete_type_witness = %complete_type.loc8 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .Cpp = +// CHECK:STDOUT: .base = %.loc7 +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: extend %Bar.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @Derived.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_class_template.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "class_template.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc17: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon new file mode 100644 index 000000000000..3fba300e21f4 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon @@ -0,0 +1,1126 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/no_prelude/struct.carbon + +// --- struct_declaration.h + +struct Bar; + +// --- fail_import_struct_declaration.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_declaration.h"; + +// CHECK:STDERR: fail_import_struct_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_import_struct_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*); + +// --- struct_definition.h + +struct Bar {}; + +// --- import_struct_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- struct_declaration_and_definition.h + +struct Bar; +struct Bar {}; + +// --- import_struct_declaration_and_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_declaration_and_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- struct_public_static_member_function.h + +struct Bar { + static auto foo() -> void; +}; + +// --- import_struct_public_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_public_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- struct_private_static_member_function.h + +struct Bar { + private: + static auto foo() -> void; +}; + +// --- todo_fail_import_struct_private_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_private_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- struct_public_member_function.h + +struct Bar { + auto foo() -> void; +}; + +// --- fail_import_struct_public_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_public_member_function.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_struct_public_member_function.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Non-global function` [SemanticsTodo] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_import_struct_public_member_function.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: + bar->foo(); +} + +// --- struct_public_static_data_member.h + +struct Bar { + static Bar* foo; +}; + +// --- fail_import_struct_public_static_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_public_static_data_member.h"; + +fn MyF() { + // CHECK:STDERR: fail_import_struct_public_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: fail_import_struct_public_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_import_struct_public_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + let bar: Cpp.Bar* = Cpp.Bar.foo(); +} + +// --- struct_public_data_member.h + +struct Bar { + Bar* foo; +}; + +// --- fail_import_struct_public_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_public_static_data_member.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_struct_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_import_struct_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_import_struct_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; +} + +// --- struct_inheritance_static.h + +struct Bar1 { + static auto foo1() -> void; +}; + +struct Bar2 : public Bar1 { + static auto foo2() -> void; +}; + +// --- import_struct_inheritance_static.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_inheritance_static.h"; + +fn MyF() { + Cpp.Bar1.foo1(); + Cpp.Bar2.foo1(); + Cpp.Bar2.foo2(); +} + +// --- struct_inheritance_pointers.h + +struct Bar1 {}; +struct Bar2 : public Bar1 {}; + +// --- fail_import_struct_inheritance_pointers.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_inheritance_pointers.h"; + +fn MyF1(bar : Cpp.Bar1*); +// TODO: Support C++ inheritance. +// CHECK:STDERR: fail_import_struct_inheritance_pointers.carbon:[[@LINE+7]]:33: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound] +// CHECK:STDERR: fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); } +// CHECK:STDERR: ^~~ +// CHECK:STDERR: fail_import_struct_inheritance_pointers.carbon:[[@LINE-5]]:9: note: initializing function parameter [InCallToFunctionParam] +// CHECK:STDERR: fn MyF1(bar : Cpp.Bar1*); +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +fn MyF2(bar : Cpp.Bar2*) { MyF1(bar); } + +// --- struct_dynamic.h + +struct Bar { + virtual ~Bar(); +}; + +// --- fail_import_struct_dynamic.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_dynamic.h"; + +// CHECK:STDERR: fail_import_struct_dynamic.carbon:[[@LINE+7]]:14: error: semantics TODO: `Unsupported: Dynamic Class` [SemanticsTodo] +// CHECK:STDERR: fn MyF(bar : Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_import_struct_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*); + +// --- struct_to_inherit_public.h + +struct Bar { static auto foo() -> void; }; + +// --- import_struct_to_inherit_public.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_to_inherit_public.h"; + +class Derived { + extend base: Cpp.Bar; +} + +fn MyF() { + Derived.foo(); +} + +// --- struct_to_inherit_private.h + +struct Bar { + private: + static auto foo() -> void; +}; + +// --- todo_fail_struct_to_inherit_private.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_to_inherit_private.h"; + +class Derived { + extend base: Cpp.Bar; +} + +fn MyF() { + Derived.foo(); +} + +// --- struct_template.h + +template +struct Bar {}; + +// --- fail_import_struct_template.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "struct_template.h"; + +// CHECK:STDERR: fail_import_struct_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_import_struct_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_struct_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn MyF(bar: Cpp.Bar*); + +// CHECK:STDOUT: --- fail_import_struct_declaration.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_declaration.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc13: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_struct_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_struct_declaration_and_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_declaration_and_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_struct_public_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_public_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_import_struct_private_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_private_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_public_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_public_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %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: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc14: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_public_static_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc18_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18_26: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc18_15: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc18_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_public_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr.loc6 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc6: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc6: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc6: type = ptr_type %Bar.ref.loc6 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %foo_bar.patt: %ptr.f68 = binding_pattern foo_bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc18_30: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18_23: type = splice_block %ptr.loc18 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc18: type = ptr_type %Bar.ref.loc18 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_struct_inheritance_static.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar1: type = class_type @Bar1 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo1.type.148: type = fn_type @foo1.1 [concrete] +// CHECK:STDOUT: %foo1.8cd: %foo1.type.148 = struct_value () [concrete] +// CHECK:STDOUT: %Bar2: type = class_type @Bar2 [concrete] +// CHECK:STDOUT: %foo1.type.0b8: type = fn_type @foo1.2 [concrete] +// CHECK:STDOUT: %foo1.ba2: %foo1.type.0b8 = struct_value () [concrete] +// CHECK:STDOUT: %foo2.type: type = fn_type @foo2 [concrete] +// CHECK:STDOUT: %foo2: %foo2.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar1 = @MyF.%Bar1.decl +// CHECK:STDOUT: .Bar2 = @MyF.%Bar2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_inheritance_static.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar1 { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar1 +// CHECK:STDOUT: .foo1 = @MyF.%foo1.decl.1 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar2 { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type.2 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar2 +// CHECK:STDOUT: .foo1 = @MyF.%foo1.decl.2 +// CHECK:STDOUT: .foo2 = @MyF.%foo2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc7: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar1.decl: type = class_decl @Bar1 [concrete = constants.%Bar1] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, %Bar1.decl [concrete = constants.%Bar1] +// CHECK:STDOUT: %foo1.decl.1: %foo1.type.148 = fn_decl @foo1.1 [concrete = constants.%foo1.8cd] {} {} +// CHECK:STDOUT: %foo1.ref.loc7: %foo1.type.148 = name_ref foo1, %foo1.decl.1 [concrete = constants.%foo1.8cd] +// CHECK:STDOUT: %foo1.call.loc7: init %empty_tuple.type = call %foo1.ref.loc7() +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.decl: type = class_decl @Bar2 [concrete = constants.%Bar2] {} {} +// CHECK:STDOUT: %complete_type.2: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar2.ref.loc8: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %foo1.decl.2: %foo1.type.0b8 = fn_decl @foo1.2 [concrete = constants.%foo1.ba2] {} {} +// CHECK:STDOUT: %foo1.ref.loc8: %foo1.type.0b8 = name_ref foo1, %foo1.decl.2 [concrete = constants.%foo1.ba2] +// CHECK:STDOUT: %foo1.call.loc8: init %empty_tuple.type = call %foo1.ref.loc8() +// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.ref.loc9: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %foo2.decl: %foo2.type = fn_decl @foo2 [concrete = constants.%foo2] {} {} +// CHECK:STDOUT: %foo2.ref: %foo2.type = name_ref foo2, %foo2.decl [concrete = constants.%foo2] +// CHECK:STDOUT: %foo2.call: init %empty_tuple.type = call %foo2.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo1.1[](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo1.2[](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo2[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_inheritance_pointers.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar1: type = class_type @Bar1 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar1 [concrete] +// CHECK:STDOUT: %MyF1.type: type = fn_type @MyF1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF1: %MyF1.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar2: type = class_type @Bar2 [concrete] +// CHECK:STDOUT: %ptr.eca: type = ptr_type %Bar2 [concrete] +// CHECK:STDOUT: %MyF2.type: type = fn_type @MyF2 [concrete] +// CHECK:STDOUT: %MyF2: %MyF2.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar1 = @MyF1.%Bar1.decl +// CHECK:STDOUT: .Bar2 = @MyF2.%Bar2.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF1 = %MyF1.decl +// CHECK:STDOUT: .MyF2 = %MyF2.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_inheritance_pointers.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF1.decl: %MyF1.type = fn_decl @MyF1 [concrete = constants.%MyF1] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar1.decl: type = class_decl @Bar1 [concrete = constants.%Bar1] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar1.ref: type = name_ref Bar1, %Bar1.decl [concrete = constants.%Bar1] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar1.ref [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF2.decl: %MyF2.type = fn_decl @MyF2 [concrete = constants.%MyF2] { +// CHECK:STDOUT: %bar.patt: %ptr.eca = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.eca = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.eca = value_param call_param0 +// CHECK:STDOUT: %.loc15_23: type = splice_block %ptr [concrete = constants.%ptr.eca] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar2.decl: type = class_decl @Bar2 [concrete = constants.%Bar2] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar2.ref: type = name_ref Bar2, %Bar2.decl [concrete = constants.%Bar2] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar2.ref [concrete = constants.%ptr.eca] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.eca = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar1 { +// CHECK:STDOUT: complete_type_witness = @MyF1.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar1 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar2 { +// CHECK:STDOUT: complete_type_witness = @MyF2.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar2 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF1(%bar.param_patt: %ptr.f68); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF2(%bar.param_patt: %ptr.eca) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %MyF1.ref: %MyF1.type = name_ref MyF1, file.%MyF1.decl [concrete = constants.%MyF1] +// CHECK:STDOUT: %bar.ref: %ptr.eca = name_ref bar, %bar +// CHECK:STDOUT: %.loc15_33: %ptr.f68 = converted %bar.ref, [concrete = ] +// CHECK:STDOUT: %MyF1.call: init %empty_tuple.type = call %MyF1.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_dynamic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_dynamic.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc13: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_struct_to_inherit_public.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Derived.elem: type = unbound_element_type %Derived, %Bar [concrete] +// CHECK:STDOUT: %struct_type.base.36d: type = struct_type {.base: %Bar} [concrete] +// CHECK:STDOUT: %complete_type.fff: = complete_type_witness %struct_type.base.36d [concrete] +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @Derived.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_to_inherit_public.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {} +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %.loc7: %Derived.elem = base_decl %Bar.ref, element0 [concrete] +// CHECK:STDOUT: %complete_type.loc8: = complete_type_witness %struct_type.base.36d [concrete = constants.%complete_type.fff] +// CHECK:STDOUT: complete_type_witness = %complete_type.loc8 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .Cpp = +// CHECK:STDOUT: .base = %.loc7 +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: extend %Bar.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @Derived.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_struct_to_inherit_private.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Derived.elem: type = unbound_element_type %Derived, %Bar [concrete] +// CHECK:STDOUT: %struct_type.base.36d: type = struct_type {.base: %Bar} [concrete] +// CHECK:STDOUT: %complete_type.fff: = complete_type_witness %struct_type.base.36d [concrete] +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @Derived.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_to_inherit_private.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {} +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %.loc7: %Derived.elem = base_decl %Bar.ref, element0 [concrete] +// CHECK:STDOUT: %complete_type.loc8: = complete_type_witness %struct_type.base.36d [concrete = constants.%complete_type.fff] +// CHECK:STDOUT: complete_type_witness = %complete_type.loc8 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .Cpp = +// CHECK:STDOUT: .base = %.loc7 +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: extend %Bar.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @Derived.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_struct_template.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "struct_template.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc17: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/union.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/union.carbon new file mode 100644 index 000000000000..e9181227901f --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/no_prelude/union.carbon @@ -0,0 +1,759 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/no_prelude/union.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/no_prelude/union.carbon + +// --- union_declaration.h + +union Bar; + +// --- fail_import_union_declaration.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_declaration.h"; + +// CHECK:STDERR: fail_import_union_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_import_union_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*); + +// --- union_definition.h + +union Bar {}; + +// --- import_union_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- union_declaration_and_definition.h + +union Bar; +union Bar {}; + +// --- import_union_declaration_and_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_declaration_and_definition.h"; + +fn MyF(bar: Cpp.Bar*); + +// --- union_public_static_member_function.h + +union Bar { + public: + static auto foo() -> void; +}; + +// --- import_union_public_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_public_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- union_private_static_member_function.h + +union Bar { + private: + static auto foo() -> void; +}; + +// --- todo_fail_import_union_private_static_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_private_static_member_function.h"; + +fn MyF() { + Cpp.Bar.foo(); +} + +// --- union_public_member_function.h + +union Bar { + public: + auto foo() -> void; +}; + +// --- fail_import_union_public_member_function.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_public_member_function.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_union_public_member_function.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: Non-global function` [SemanticsTodo] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_import_union_public_member_function.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: bar->foo(); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: + bar->foo(); +} + +// --- union_public_static_data_member.h + +union Bar { + public: + static Bar* foo; +}; + +// --- fail_import_union_public_static_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_public_static_data_member.h"; + +fn MyF() { + // CHECK:STDERR: fail_import_union_public_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: fail_import_union_public_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_import_union_public_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + let bar: Cpp.Bar* = Cpp.Bar.foo(); +} + +// --- union_public_data_member.h + +union Bar { + public: + Bar* foo; +}; + +// --- fail_import_union_public_data_member.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_public_static_data_member.h"; + +fn MyF(bar : Cpp.Bar*) { + // CHECK:STDERR: fail_import_union_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_import_union_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_import_union_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; +} + +// --- union_to_inherit_public.h + +union Bar { + public: + static auto foo() -> void; +}; + +// --- todo_fail_import_union_to_inherit_public.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_to_inherit_public.h"; + +class Derived { + extend base: Cpp.Bar; +} + +fn MyF() { + Derived.foo(); +} + +// --- union_template.h + +template +union Bar {}; + +// --- fail_import_union_template.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "union_template.h"; + +// CHECK:STDERR: fail_import_union_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_import_union_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_union_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn MyF(bar: Cpp.Bar*); + +// CHECK:STDOUT: --- fail_import_union_declaration.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_declaration.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc13: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_union_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_union_declaration_and_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_declaration_and_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref [concrete = constants.%ptr] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr); +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_union_public_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_public_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_import_union_private_static_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_private_static_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_union_public_member_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_public_member_function.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %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: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc14: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_union_public_static_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc18_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18_26: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc18_15: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc18_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_union_public_data_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %ptr.f68: type = ptr_type %Bar [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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @MyF.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_public_static_data_member.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: %ptr.f68 = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: %ptr.f68 = value_param_pattern %bar.patt, call_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: %ptr.f68 = value_param call_param0 +// CHECK:STDOUT: %.loc6: type = splice_block %ptr.loc6 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc6: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: %Bar.ref.loc6: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc6: type = ptr_type %Bar.ref.loc6 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @MyF.%complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: %ptr.f68) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %foo_bar.patt: %ptr.f68 = binding_pattern foo_bar +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar.ref: %ptr.f68 = name_ref bar, %bar +// CHECK:STDOUT: %.loc18_30: ref %Bar = deref %bar.ref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] +// CHECK:STDOUT: %.loc18_23: type = splice_block %ptr.loc18 [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc18: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr.loc18: type = ptr_type %Bar.ref.loc18 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo_bar: %ptr.f68 = bind_name foo_bar, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_import_union_to_inherit_public.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [concrete] +// CHECK:STDOUT: %Bar: type = class_type @Bar [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Derived.elem: type = unbound_element_type %Derived, %Bar [concrete] +// CHECK:STDOUT: %struct_type.base.36d: type = struct_type {.base: %Bar} [concrete] +// CHECK:STDOUT: %complete_type.fff: = complete_type_witness %struct_type.base.36d [concrete] +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = @Derived.%Bar.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_to_inherit_public.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {} +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.decl: type = class_decl @Bar [concrete = constants.%Bar] {} {} +// CHECK:STDOUT: %complete_type.1: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: %Bar.ref: type = name_ref Bar, %Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %.loc7: %Derived.elem = base_decl %Bar.ref, element0 [concrete] +// CHECK:STDOUT: %complete_type.loc8: = complete_type_witness %struct_type.base.36d [concrete = constants.%complete_type.fff] +// CHECK:STDOUT: complete_type_witness = %complete_type.loc8 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .Cpp = +// CHECK:STDOUT: .base = %.loc7 +// CHECK:STDOUT: .foo = +// CHECK:STDOUT: extend %Bar.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: complete_type_witness = @Derived.%complete_type.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo[](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_union_template.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "union_template.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] { +// CHECK:STDOUT: %bar.patt: = binding_pattern bar +// CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete = ] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %bar.param: = value_param call_param0 +// CHECK:STDOUT: %.loc17: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] +// CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] +// CHECK:STDOUT: } +// CHECK:STDOUT: %bar: = bind_name bar, %bar.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF(%bar.param_patt: ); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon index 0195eafeebaf..473cd553e99c 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon @@ -10,7 +10,7 @@ // --- unsupported_decl.h -class foo; +typedef int foo; // --- fail_import_unsupported_decl.carbon @@ -19,7 +19,7 @@ library "[[@TEST_NAME]]"; import Cpp library "unsupported_decl.h"; fn F() { - // CHECK:STDERR: fail_import_unsupported_decl.carbon:[[@LINE+11]]:3: error: semantics TODO: `Unsupported: Declaration type CXXRecord` [SemanticsTodo] + // CHECK:STDERR: fail_import_unsupported_decl.carbon:[[@LINE+11]]:3: error: semantics TODO: `Unsupported: Declaration type Typedef` [SemanticsTodo] // CHECK:STDERR: Cpp.foo(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_import_unsupported_decl.carbon:[[@LINE+8]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]