Initial 'export name' handling. (#3949)

This adds a `BindExport` instruction in order to better track the
location of the `export` itself, but a `bind_name_id` is also added to
`ImportRef` so that we know quickly where to put it in name lookup.

Merging identical names is a TODO. I haven't quite decided how best to
achieve that, because I do think the BindExport should be what's
actually added to name lookup.

Also, I will probably add a mode to DeclNameStack that blocks
non-namespace scopes. This seems to already be an error, but the wrong
one (maybe due to lack of support for cross-file decl/def support).
This commit is contained in:
Jon Ross-Perkins
2024-05-17 18:05:52 +00:00
committed by GitHub
parent 122a361317
commit 40b2217421
22 changed files with 2135 additions and 234 deletions
+8 -2
View File
@@ -87,6 +87,13 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLoc> {
while (true) {
if (cursor_inst_id.is_valid()) {
auto cursor_inst = cursor_ir->insts().Get(cursor_inst_id);
if (auto bind_ref = cursor_inst.TryAs<SemIR::BindExport>();
bind_ref && bind_ref->value_id.is_valid()) {
cursor_inst_id = bind_ref->value_id;
continue;
}
// If the parse node is valid, use it for the location.
if (auto loc_id = cursor_ir->insts().GetLocId(cursor_inst_id);
loc_id.is_valid()) {
@@ -98,8 +105,7 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLoc> {
// If a namespace has an instruction for an import, switch to looking at
// it.
if (auto ns =
cursor_ir->insts().TryGetAs<SemIR::Namespace>(cursor_inst_id)) {
if (auto ns = cursor_inst.TryAs<SemIR::Namespace>()) {
if (ns->import_id.is_valid()) {
cursor_inst_id = ns->import_id;
continue;
+22 -9
View File
@@ -247,7 +247,8 @@ auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
//
// // Error, no `F` in `B`.
// fn B.F() {}
return LookupNameInExactScope(loc_id, name_id, name_scopes().Get(scope_id));
return LookupNameInExactScope(loc_id, name_id, scope_id,
name_scopes().Get(scope_id));
}
}
@@ -282,6 +283,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
// Handles lookup through the import_ir_scopes for LookupNameInExactScope.
static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
SemIR::NameId name_id,
SemIR::NameScopeId scope_id,
const SemIR::NameScope& scope)
-> SemIR::InstId {
auto identifier_id = name_id.AsIdentifierId();
@@ -298,6 +300,7 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
});
auto result_id = SemIR::InstId::Invalid;
auto bind_name_id = SemIR::BindNameId::Invalid;
for (auto [import_ir_id, import_scope_id] : scope.import_ir_scopes) {
auto& import_ir = context.import_irs().Get(import_ir_id);
@@ -321,8 +324,15 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
// Name doesn't exist in the import scope.
continue;
}
auto import_inst_id =
AddImportRef(context, {.ir_id = import_ir_id, .inst_id = it->second});
if (!bind_name_id.is_valid()) {
bind_name_id = context.bind_names().Add(
{.name_id = name_id,
.enclosing_scope_id = scope_id,
.bind_index = SemIR::CompileTimeBindIndex::Invalid});
}
auto import_inst_id = AddImportRef(
context, {.ir_id = import_ir_id, .inst_id = it->second}, bind_name_id);
if (result_id.is_valid()) {
context.DiagnoseDuplicateName(import_inst_id, result_id);
} else {
@@ -335,6 +345,7 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
}
auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
SemIR::NameScopeId scope_id,
const SemIR::NameScope& scope)
-> SemIR::InstId {
if (auto it = scope.names.find(name_id); it != scope.names.end()) {
@@ -342,7 +353,7 @@ auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
return it->second;
}
if (!scope.import_ir_scopes.empty()) {
return LookupInImportIRScopes(*this, loc, name_id, scope);
return LookupInImportIRScopes(*this, loc, name_id, scope_id, scope);
}
return SemIR::InstId::Invalid;
}
@@ -356,10 +367,12 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
// Walk this scope and, if nothing is found here, the scopes it extends.
while (!scope_ids.empty()) {
const auto& scope = name_scopes().Get(scope_ids.pop_back_val());
auto scope_id = scope_ids.pop_back_val();
const auto& scope = name_scopes().Get(scope_id);
has_error |= scope.has_error;
auto scope_result_id = LookupNameInExactScope(node_id, name_id, scope);
auto scope_result_id =
LookupNameInExactScope(node_id, name_id, scope_id, scope);
if (!scope_result_id.is_valid()) {
// Nothing found in this scope: also look in its extended scopes.
auto extended = llvm::reverse(scope.extended_scopes);
@@ -409,7 +422,7 @@ static auto GetCorePackage(Context& context, SemIRLoc loc)
// Look up `package.Core`.
auto core_inst_id = context.LookupNameInExactScope(
loc, core_name_id,
loc, core_name_id, SemIR::NameScopeId::Package,
context.name_scopes().Get(SemIR::NameScopeId::Package));
if (!core_inst_id.is_valid()) {
context.DiagnoseNameNotFound(loc, core_name_id);
@@ -434,8 +447,8 @@ auto Context::LookupNameInCore(SemIRLoc loc, llvm::StringRef name)
}
auto name_id = SemIR::NameId::ForIdentifier(identifiers().Add(name));
auto inst_id =
LookupNameInExactScope(loc, name_id, name_scopes().Get(core_package_id));
auto inst_id = LookupNameInExactScope(loc, name_id, core_package_id,
name_scopes().Get(core_package_id));
if (!inst_id.is_valid()) {
DiagnoseNameNotFound(loc, name_id);
return SemIR::InstId::BuiltinError;
+1
View File
@@ -109,6 +109,7 @@ class Context {
// instruction. Does not look into extended scopes. Returns an invalid
// instruction if the name is not found.
auto LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
SemIR::NameScopeId scope_id,
const SemIR::NameScope& scope) -> SemIR::InstId;
// Performs a qualified name lookup in a specified scope and in scopes that
+3
View File
@@ -1065,6 +1065,9 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
case CARBON_KIND(SemIR::BindAlias typed_inst): {
return context.constant_values().Get(typed_inst.value_id);
}
case CARBON_KIND(SemIR::BindExport typed_inst): {
return context.constant_values().Get(typed_inst.value_id);
}
case CARBON_KIND(SemIR::NameRef typed_inst): {
return context.constant_values().Get(typed_inst.value_id);
}
+40 -2
View File
@@ -3,18 +3,56 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/context.h"
#include "toolchain/check/decl_name_stack.h"
#include "toolchain/parse/typed_nodes.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/typed_insts.h"
namespace Carbon::Check {
auto HandleExportIntroducer(Context& /*context*/,
auto HandleExportIntroducer(Context& context,
Parse::ExportIntroducerId /*node_id*/) -> bool {
// TODO: Probably need to update DeclNameStack to restrict to only namespaces.
context.decl_name_stack().PushScopeAndStartName();
return true;
}
auto HandleExportDirective(Context& context, Parse::ExportDirectiveId node_id)
-> bool {
return context.TODO(node_id, "ExportDirective");
auto name_context = context.decl_name_stack().FinishName();
context.decl_name_stack().PopScope();
if (name_context.state == DeclNameStack::NameContext::State::Error) {
// Should already be diagnosed.
return true;
}
auto inst_id = name_context.prev_inst_id();
if (!inst_id.is_valid()) {
context.DiagnoseNameNotFound(node_id, name_context.name_id_for_new_inst());
return true;
}
auto import_ref = context.insts().TryGetAs<SemIR::ImportRefLoaded>(inst_id);
if (!import_ref) {
CARBON_DIAGNOSTIC(ExportNotImportedEntity, Error,
"Only imported entities are valid for `export`.");
CARBON_DIAGNOSTIC(ExportNotImportedEntitySource, Note,
"Name is declared here.");
context.emitter()
.Build(node_id, ExportNotImportedEntity)
.Note(inst_id, ExportNotImportedEntitySource)
.Emit();
return true;
}
auto export_id = context.AddInst(
{node_id, SemIR::BindExport{.type_id = import_ref->type_id,
.bind_name_id = import_ref->bind_name_id,
.value_id = inst_id}});
context.AddExport(export_id);
return true;
}
} // namespace Carbon::Check
+2 -2
View File
@@ -106,8 +106,8 @@ static auto BuildInterfaceWitness(
CARBON_FATAL() << "Unexpected type: " << type_inst;
}
auto& fn = context.functions().Get(fn_type->function_id);
auto impl_decl_id =
context.LookupNameInExactScope(decl_id, fn.name_id, impl_scope);
auto impl_decl_id = context.LookupNameInExactScope(
decl_id, fn.name_id, impl.scope_id, impl_scope);
if (impl_decl_id.is_valid()) {
used_decl_ids.push_back(impl_decl_id);
table.push_back(CheckAssociatedFunctionImplementation(
+16 -9
View File
@@ -18,12 +18,13 @@
namespace Carbon::Check {
// Returns name information for the entity, corresponding to IDs in the import
// IR rather than the current IR. May return Invalid for a TODO.
// IR rather than the current IR.
static auto GetImportName(const SemIR::File& import_sem_ir,
SemIR::Inst import_inst)
-> std::pair<SemIR::NameId, SemIR::NameScopeId> {
CARBON_KIND_SWITCH(import_inst) {
case SemIR::BindAlias::Kind:
case SemIR::BindExport::Kind:
case SemIR::BindName::Kind:
case SemIR::BindSymbolicName::Kind: {
auto bind_inst = import_inst.As<SemIR::AnyBindName>();
@@ -139,12 +140,17 @@ static auto CopySingleNameScopeFromImportIR(
SemIR::NameId name_id) -> SemIR::NameScopeId {
// Produce the namespace for the entry.
auto make_import_id = [&]() {
auto bind_name_id = context.bind_names().Add(
{.name_id = name_id,
.enclosing_scope_id = enclosing_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::Invalid});
auto import_ir_inst_id = context.import_ir_insts().Add(
{.ir_id = ir_id, .inst_id = import_inst_id});
return context.AddInst(
{import_ir_inst_id,
SemIR::ImportRefLoaded{.type_id = namespace_type_id,
.import_ir_inst_id = import_ir_inst_id}});
.import_ir_inst_id = import_ir_inst_id,
.bind_name_id = bind_name_id}});
};
auto [namespace_scope_id, namespace_const_id, _] =
AddNamespace(context, namespace_type_id, Parse::NodeId::Invalid, name_id,
@@ -228,11 +234,6 @@ auto ImportLibraryFromCurrentPackage(Context& context,
auto import_inst = import_sem_ir.insts().Get(import_inst_id);
auto [import_name_id, import_enclosing_scope_id] =
GetImportName(import_sem_ir, import_inst);
// TODO: This should only be invalid when GetImportName for an inst
// isn't yet implemented. Long-term this should be removed.
if (!import_name_id.is_valid()) {
continue;
}
llvm::DenseMap<SemIR::NameScopeId, SemIR::NameScopeId> copied_namespaces;
@@ -249,12 +250,18 @@ auto ImportLibraryFromCurrentPackage(Context& context,
import_namespace_inst->name_scope_id, enclosing_scope_id, name_id);
} else {
// Leave a placeholder that the inst comes from the other IR.
auto target_id =
AddImportRef(context, {.ir_id = ir_id, .inst_id = import_inst_id});
auto bind_name_id = context.bind_names().Add(
{.name_id = name_id,
.enclosing_scope_id = enclosing_scope_id,
.bind_index = SemIR::CompileTimeBindIndex::Invalid});
auto target_id = AddImportRef(
context, {.ir_id = ir_id, .inst_id = import_inst_id}, bind_name_id);
auto [it, success] = context.name_scopes()
.Get(enclosing_scope_id)
.names.insert({name_id, target_id});
if (!success) {
// TODO: Figure out how best to handle when an export is added that's a
// conflict. Right now it diagnoses as a conflict around here.
context.DiagnoseDuplicateName(target_id, it->second);
}
}
+29 -8
View File
@@ -52,11 +52,13 @@ auto AddImportIR(Context& context, SemIR::ImportIR import_ir)
return ir_id;
}
auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst)
-> SemIR::InstId {
auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst,
SemIR::BindNameId bind_name_id) -> SemIR::InstId {
auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst);
auto import_ref_id = context.AddPlaceholderInstInNoBlock(
{import_ir_inst_id, SemIR::ImportRefUnloaded{import_ir_inst_id}});
{import_ir_inst_id,
SemIR::ImportRefUnloaded{.import_ir_inst_id = import_ir_inst_id,
.bind_name_id = bind_name_id}});
// We can't insert this instruction into whatever block we happen to be in,
// because this function is typically called by name lookup in the middle of
@@ -483,7 +485,8 @@ class ImportRefResolver {
SemIR::NameScope& new_scope) -> void {
for (auto [entry_name_id, entry_inst_id] : import_scope.names) {
auto ref_id = AddImportRef(
context_, {.ir_id = import_ir_id_, .inst_id = entry_inst_id});
context_, {.ir_id = import_ir_id_, .inst_id = entry_inst_id},
SemIR::BindNameId::Invalid);
CARBON_CHECK(
new_scope.names.insert({GetLocalNameId(entry_name_id), ref_id})
.second);
@@ -503,7 +506,8 @@ class ImportRefResolver {
new_associated_entities.reserve(associated_entities.size());
for (auto inst_id : associated_entities) {
new_associated_entities.push_back(
AddImportRef(context_, {.ir_id = import_ir_id_, .inst_id = inst_id}));
AddImportRef(context_, {.ir_id = import_ir_id_, .inst_id = inst_id},
SemIR::BindNameId::Invalid));
}
return context_.inst_blocks().Add(new_associated_entities);
}
@@ -538,6 +542,9 @@ class ImportRefResolver {
case CARBON_KIND(SemIR::BindAlias inst): {
return TryResolveTypedInst(inst);
}
case CARBON_KIND(SemIR::BindExport inst): {
return TryResolveTypedInst(inst);
}
case CARBON_KIND(SemIR::BindName inst): {
// TODO: This always returns `ConstantId::NotConstant`.
return {TryEvalInst(context_, inst_id, inst)};
@@ -607,7 +614,8 @@ class ImportRefResolver {
// Add a lazy reference to the target declaration.
auto decl_id = AddImportRef(
context_, {.ir_id = import_ir_id_, .inst_id = inst.decl_id});
context_, {.ir_id = import_ir_id_, .inst_id = inst.decl_id},
SemIR::BindNameId::Invalid);
auto inst_id = context_.AddInstInNoBlock(
{AddImportIRInst(inst.decl_id),
@@ -666,6 +674,15 @@ class ImportRefResolver {
return {value_id};
}
auto TryResolveTypedInst(SemIR::BindExport inst) -> ResolveResult {
auto initial_work = work_stack_.size();
auto value_id = GetLocalConstantId(inst.value_id);
if (HasNewWork(initial_work)) {
return ResolveResult::Retry();
}
return {value_id};
}
auto TryResolveTypedInst(SemIR::BindSymbolicName inst,
SemIR::InstId import_inst_id) -> ResolveResult {
auto initial_work = work_stack_.size();
@@ -1217,7 +1234,10 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
// doesn't use ReplaceInstBeforeConstantUse because it would trigger
// TryEvalInst, which we want to avoid with ImportRefs.
context.sem_ir().insts().Set(
inst_id, SemIR::ImportRefLoaded{type_id, inst->import_ir_inst_id});
inst_id,
SemIR::ImportRefLoaded{.type_id = type_id,
.import_ir_inst_id = inst->import_ir_inst_id,
.bind_name_id = inst->bind_name_id});
// Store the constant for both the ImportRefLoaded and imported instruction.
context.constant_values().Set(inst_id, constant_id);
@@ -1242,7 +1262,8 @@ static auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id,
auto& impl = context.impls().Get(impl_id);
impl.witness_id = AddImportRef(
context, {.ir_id = import_ir_id, .inst_id = import_impl.witness_id});
context, {.ir_id = import_ir_id, .inst_id = import_impl.witness_id},
SemIR::BindNameId::Invalid);
}
}
+2 -2
View File
@@ -21,8 +21,8 @@ auto AddImportIR(Context& context, SemIR::ImportIR import_ir)
// Adds an import_ref instruction for the specified instruction in the
// specified IR. The import_ref is initially marked as unused.
auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst)
-> SemIR::InstId;
auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst,
SemIR::BindNameId bind_name_id) -> SemIR::InstId;
// If the passed in instruction ID is an ImportRefUnloaded, turns it into an
// ImportRefLoaded for use.
@@ -0,0 +1,241 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
class C {}
alias D = C;
// --- export.carbon
library "export" api;
import library "base";
export D;
// --- export_orig.carbon
library "export_orig" api;
import library "base";
export C;
// ============================================================================
// Test files
// ============================================================================
// --- use_export.carbon
library "use_export" api;
import library "export";
var d: D = {};
// --- fail_orig_name_not_in_export.carbon
library "fail_orig_name_not_in_export" api;
import library "export";
// CHECK:STDERR: fail_orig_name_not_in_export.carbon:[[@LINE+3]]:8: ERROR: Name `C` not found.
// CHECK:STDERR: var c: C = {};
// CHECK:STDERR: ^
var c: C = {};
// --- indirect_compat.carbon
library "indirect_compat" api;
import library "export";
import library "export_orig";
var c: C = {};
var d: D* = &c;
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: .D = %D
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C]
// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+1, unloaded
// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+5, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+2, unloaded
// CHECK:STDOUT: %D: type = bind_export D, %import_ref.2 [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export_orig.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+5, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+2, unloaded
// CHECK:STDOUT: %C: type = bind_export C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %struct: C = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .D = %import_ref.1
// CHECK:STDOUT: .d = %d
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+7, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+6, unloaded
// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %d.var: ref C = var d
// CHECK:STDOUT: %d: ref C = bind_name d, %d.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc6_13.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc6_13.2: init C = class_init (), file.%d.var [template = constants.%struct]
// CHECK:STDOUT: %.loc6_14: init C = converted %.loc6_13.1, %.loc6_13.2 [template = constants.%struct]
// CHECK:STDOUT: assign file.%d.var, %.loc6_14
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_orig_name_not_in_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .D = %import_ref
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref = import_ref ir1, inst+7, unloaded
// CHECK:STDOUT: %C.ref: <error> = name_ref C, <error> [template = <error>]
// CHECK:STDOUT: %c.var: ref <error> = var c
// CHECK:STDOUT: %c: ref <error> = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc9: {} = struct_literal ()
// CHECK:STDOUT: assign file.%c.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- indirect_compat.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %struct: C = struct_value () [template]
// CHECK:STDOUT: %.4: type = ptr_type C [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .D = %import_ref.1
// CHECK:STDOUT: .C = %import_ref.2
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: .d = %d
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+7, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+7, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+6, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.2 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %.loc8: type = ptr_type C [template = constants.%.4]
// CHECK:STDOUT: %d.var: ref C* = var d
// CHECK:STDOUT: %d: ref C* = bind_name d, %d.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc7_13.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc7_13.2: init C = class_init (), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc7_14: init C = converted %.loc7_13.1, %.loc7_13.2 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc7_14
// CHECK:STDOUT: %c.ref: ref C = name_ref c, file.%c
// CHECK:STDOUT: %.loc8: C* = addr_of %c.ref
// CHECK:STDOUT: assign file.%d.var, %.loc8
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,112 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
class C {}
// --- export.carbon
library "export" api;
import library "base";
export C;
// ============================================================================
// Test files
// ============================================================================
// --- use_export.carbon
library "use_export" api;
import library "export";
var c: C = {};
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded
// CHECK:STDOUT: %C: type = bind_export C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %struct: C = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+6, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+5, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc6_13.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc6_13.2: init C = class_init (), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc6_14: init C = converted %.loc6_13.1, %.loc6_13.2 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc6_14
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,101 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
fn F();
// --- export.carbon
library "export" api;
import library "base";
export F;
// ============================================================================
// Test files
// ============================================================================
// --- use_export.carbon
library "use_export" api;
import library "export";
var f: () = F();
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %import_ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: F = import_ref ir1, inst+1, loaded [template = constants.%struct]
// CHECK:STDOUT: %F: F = bind_export F, %import_ref [template = constants.%struct]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %import_ref
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: F = import_ref ir1, inst+6, loaded [template = constants.%struct]
// CHECK:STDOUT: %.loc6_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: F = name_ref F, file.%import_ref [template = constants.%struct]
// CHECK:STDOUT: %F.call: init () = call %F.ref()
// CHECK:STDOUT: assign file.%f.var, %F.call
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,115 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
interface I {}
// --- export.carbon
library "export" api;
import library "base";
export I;
// ============================================================================
// Test files
// ============================================================================
// --- use_export.carbon
library "use_export" api;
import library "export";
fn UseEmpty(i: I) {}
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = interface_type @I [template]
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .I = %I.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self 0 [symbolic = constants.%Self]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = interface_type @I [template]
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .I = %import_ref.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%.1]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded
// CHECK:STDOUT: %I: type = bind_export I, %import_ref.1 [template = constants.%.1]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = interface_type @I [template]
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %UseEmpty: type = fn_type @UseEmpty [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %struct: UseEmpty = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .I = %import_ref.1
// CHECK:STDOUT: .UseEmpty = %UseEmpty.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+7, loaded [template = constants.%.1]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+6, unloaded
// CHECK:STDOUT: %UseEmpty.decl: UseEmpty = fn_decl @UseEmpty [template = constants.%struct] {
// CHECK:STDOUT: %I.ref: type = name_ref I, %import_ref.1 [template = constants.%.1]
// CHECK:STDOUT: %i.loc6_13.1: I = param i
// CHECK:STDOUT: @UseEmpty.%i: I = bind_name i, %i.loc6_13.1
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @UseEmpty(%i: I) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,588 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
class C {
var x: ();
};
class D {
var y: ();
};
// --- export_import.carbon
library "export_import" api;
export import library "base";
// --- export_import_then_name.carbon
library "export_import_then_name" api;
import library "export_import";
export C;
// --- export_name.carbon
library "export_name" api;
import library "base";
export C;
// --- export_name_then_import.carbon
library "export_name_then_import" api;
export import library "export_name";
// ============================================================================
// Test files
// ============================================================================
// --- use_export_import_then_name.carbon
library "use_export_import_then_name" api;
import library "export_import_then_name";
var c: C = {.x = ()};
// --- use_export_name_then_import.carbon
library "use_export_name_then_import" api;
import library "export_name_then_import";
var c: C = {.x = ()};
// --- fail_todo_use_both.carbon
library "use_both" api;
import library "export_import_then_name";
// CHECK:STDERR: fail_todo_use_both.carbon:[[@LINE+19]]:1: In import.
// CHECK:STDERR: import library "export_name_then_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_name.carbon:4:1: In import.
// CHECK:STDERR: import library "base";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_use_both.carbon:[[@LINE-10]]:1: In import.
// CHECK:STDERR: import library "export_import_then_name";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_import_then_name.carbon:4:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: Name is previously declared here.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
import library "export_name_then_import";
var c: C = {.x = ()};
// --- fail_nonexport_use_both.carbon
library "fail_nonexport_use_both" api;
import library "export_import_then_name";
// CHECK:STDERR: fail_nonexport_use_both.carbon:[[@LINE+19]]:1: In import.
// CHECK:STDERR: import library "export_name_then_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_name.carbon:4:1: In import.
// CHECK:STDERR: import library "base";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_nonexport_use_both.carbon:[[@LINE-10]]:1: In import.
// CHECK:STDERR: import library "export_import_then_name";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_import_then_name.carbon:4:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: Name is previously declared here.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
import library "export_name_then_import";
// CHECK:STDERR: fail_nonexport_use_both.carbon:[[@LINE+4]]:8: ERROR: Name `D` not found.
// CHECK:STDERR: var d: D = {.y = ()};
// CHECK:STDERR: ^
// CHECK:STDERR:
var d: D = {.y = ()};
// --- fail_todo_use_both_reversed.carbon
library "use_both_reversed" api;
import library "export_import_then_name";
// CHECK:STDERR: fail_todo_use_both_reversed.carbon:[[@LINE+19]]:1: In import.
// CHECK:STDERR: import library "export_name_then_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_name.carbon:4:1: In import.
// CHECK:STDERR: import library "base";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_use_both_reversed.carbon:[[@LINE-10]]:1: In import.
// CHECK:STDERR: import library "export_import_then_name";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_import_then_name.carbon:4:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: Name is previously declared here.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
import library "export_name_then_import";
var c: C = {.x = ()};
// --- fail_todo_use_both_and_export_import.carbon
library "use_both_and_export_import" api;
import library "export_import_then_name";
// CHECK:STDERR: fail_todo_use_both_and_export_import.carbon:[[@LINE+19]]:1: In import.
// CHECK:STDERR: import library "export_name_then_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_name.carbon:4:1: In import.
// CHECK:STDERR: import library "base";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_use_both_and_export_import.carbon:[[@LINE-10]]:1: In import.
// CHECK:STDERR: import library "export_import_then_name";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_import_then_name.carbon:4:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: Name is previously declared here.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
import library "export_name_then_import";
// CHECK:STDERR: fail_todo_use_both_and_export_import.carbon:[[@LINE+15]]:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_use_both_and_export_import.carbon:[[@LINE-27]]:1: In import.
// CHECK:STDERR: import library "export_import_then_name";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export_import_then_name.carbon:4:1: In import.
// CHECK:STDERR: import library "export_import";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:1: Name is previously declared here.
// CHECK:STDERR: class C {
// CHECK:STDERR: ^~~~~~~~~
import library "export_import";
var c: C = {.x = ()};
var d: D = {.y = ()};
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = unbound_element_type C, () [template]
// CHECK:STDOUT: %.3: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %D: type = class_type @D [template]
// CHECK:STDOUT: %.4: type = unbound_element_type D, () [template]
// CHECK:STDOUT: %.5: type = struct_type {.y: ()} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: .D = %D.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: %.loc5_11.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc5_11.2: type = converted %.loc5_11.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_8: <unbound element of class C> = field_decl x, element0 [template]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: .x = %.loc5_8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @D {
// CHECK:STDOUT: %.loc9_11.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_11.2: type = converted %.loc9_11.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %.loc9_8: <unbound element of class D> = field_decl y, element0 [template]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%D
// CHECK:STDOUT: .y = %.loc9_8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export_import.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+1, unloaded
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+11, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export_import_then_name.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+1, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+11, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+7, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+2, unloaded
// CHECK:STDOUT: %C: type = bind_export C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .x = file.%import_ref.3
// CHECK:STDOUT: .Self = file.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export_name.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+11, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+7, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+2, unloaded
// CHECK:STDOUT: %C: type = bind_export C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .x = file.%import_ref.3
// CHECK:STDOUT: .Self = file.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export_name_then_import.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref = import_ref ir1, inst+11, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export_import_then_name.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+11, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+10, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: .x = file.%import_ref.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc6_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_20.1: {.x: ()} = struct_literal (%.loc6_19.1)
// CHECK:STDOUT: %.loc6_20.2: ref () = class_element_access file.%c.var, element0
// CHECK:STDOUT: %.loc6_19.2: init () = tuple_init () to %.loc6_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc6_20.3: init () = converted %.loc6_19.1, %.loc6_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc6_20.4: init C = class_init (%.loc6_20.3), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc6_21: init C = converted %.loc6_20.1, %.loc6_20.4 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc6_21
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- use_export_name_then_import.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+11, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+10, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+9, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.2
// CHECK:STDOUT: .x = file.%import_ref.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc6_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc6_20.1: {.x: ()} = struct_literal (%.loc6_19.1)
// CHECK:STDOUT: %.loc6_20.2: ref () = class_element_access file.%c.var, element0
// CHECK:STDOUT: %.loc6_19.2: init () = tuple_init () to %.loc6_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc6_20.3: init () = converted %.loc6_19.1, %.loc6_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc6_20.4: init C = class_init (%.loc6_20.3), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc6_21: init C = converted %.loc6_20.1, %.loc6_20.4 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc6_21
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_both.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+11, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+11, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+10, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+9, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.3
// CHECK:STDOUT: .x = file.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc26_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc26_20.1: {.x: ()} = struct_literal (%.loc26_19.1)
// CHECK:STDOUT: %.loc26_20.2: ref () = class_element_access file.%c.var, element0
// CHECK:STDOUT: %.loc26_19.2: init () = tuple_init () to %.loc26_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc26_20.3: init () = converted %.loc26_19.1, %.loc26_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc26_20.4: init C = class_init (%.loc26_20.3), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc26_21: init C = converted %.loc26_20.1, %.loc26_20.4 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc26_21
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_nonexport_use_both.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.y: ()} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .d = %d
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+11, unloaded
// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+11, unloaded
// CHECK:STDOUT: %D.ref: <error> = name_ref D, <error> [template = <error>]
// CHECK:STDOUT: %d.var: ref <error> = var d
// CHECK:STDOUT: %d: ref <error> = bind_name d, %d.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc30_19: () = tuple_literal ()
// CHECK:STDOUT: %.loc30_20: {.y: ()} = struct_literal (%.loc30_19)
// CHECK:STDOUT: assign file.%d.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_both_reversed.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+11, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+11, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+10, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+9, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.3
// CHECK:STDOUT: .x = file.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc26_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc26_20.1: {.x: ()} = struct_literal (%.loc26_19.1)
// CHECK:STDOUT: %.loc26_20.2: ref () = class_element_access file.%c.var, element0
// CHECK:STDOUT: %.loc26_19.2: init () = tuple_init () to %.loc26_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc26_20.3: init () = converted %.loc26_19.1, %.loc26_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc26_20.4: init C = class_init (%.loc26_20.3), file.%c.var [template = constants.%struct]
// CHECK:STDOUT: %.loc26_21: init C = converted %.loc26_20.1, %.loc26_20.4 [template = constants.%struct]
// CHECK:STDOUT: assign file.%c.var, %.loc26_21
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_both_and_export_import.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template]
// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: %struct.1: C = struct_value (%tuple) [template]
// CHECK:STDOUT: %D: type = class_type @D [template]
// CHECK:STDOUT: %.4: type = struct_type {.y: ()} [template]
// CHECK:STDOUT: %.5: type = ptr_type {.y: ()} [template]
// CHECK:STDOUT: %struct.2: D = struct_value (%tuple) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .C = %import_ref.1
// CHECK:STDOUT: .D = %import_ref.4
// CHECK:STDOUT: .c = %c
// CHECK:STDOUT: .d = %d
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+11, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+11, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref ir5, inst+1, unloaded
// CHECK:STDOUT: %import_ref.4: type = import_ref ir5, inst+11, loaded [template = constants.%D]
// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+10, unloaded
// CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+9, unloaded
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
// CHECK:STDOUT: %c.var: ref C = var c
// CHECK:STDOUT: %c: ref C = bind_name c, %c.var
// CHECK:STDOUT: %import_ref.7 = import_ref ir5, inst+12, unloaded
// CHECK:STDOUT: %import_ref.8 = import_ref ir5, inst+16, unloaded
// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.4 [template = constants.%D]
// CHECK:STDOUT: %d.var: ref D = var d
// CHECK:STDOUT: %d: ref D = bind_name d, %d.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.5
// CHECK:STDOUT: .x = file.%import_ref.6
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @D {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = file.%import_ref.7
// CHECK:STDOUT: .y = file.%import_ref.8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc42_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc42_20.1: {.x: ()} = struct_literal (%.loc42_19.1)
// CHECK:STDOUT: %.loc42_20.2: ref () = class_element_access file.%c.var, element0
// CHECK:STDOUT: %.loc42_19.2: init () = tuple_init () to %.loc42_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc42_20.3: init () = converted %.loc42_19.1, %.loc42_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc42_20.4: init C = class_init (%.loc42_20.3), file.%c.var [template = constants.%struct.1]
// CHECK:STDOUT: %.loc42_21: init C = converted %.loc42_20.1, %.loc42_20.4 [template = constants.%struct.1]
// CHECK:STDOUT: assign file.%c.var, %.loc42_21
// CHECK:STDOUT: %.loc43_19.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc43_20.1: {.y: ()} = struct_literal (%.loc43_19.1)
// CHECK:STDOUT: %.loc43_20.2: ref () = class_element_access file.%d.var, element0
// CHECK:STDOUT: %.loc43_19.2: init () = tuple_init () to %.loc43_20.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc43_20.3: init () = converted %.loc43_19.1, %.loc43_19.2 [template = constants.%tuple]
// CHECK:STDOUT: %.loc43_20.4: init D = class_init (%.loc43_20.3), file.%d.var [template = constants.%struct.2]
// CHECK:STDOUT: %.loc43_21: init D = converted %.loc43_20.1, %.loc43_20.4 [template = constants.%struct.2]
// CHECK:STDOUT: assign file.%d.var, %.loc43_21
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,103 @@
// 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
// ============================================================================
// Setup files
// ============================================================================
// --- base.carbon
library "base" api;
var v: ();
// --- export.carbon
library "export" api;
import library "base";
export v;
// ============================================================================
// Test files
// ============================================================================
// --- fail_todo_use_export.carbon
library "use_export" api;
// CHECK:STDERR: fail_todo_use_export.carbon:[[@LINE+9]]:1: In import.
// CHECK:STDERR: import library "export";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: export.carbon:4:1: In import.
// CHECK:STDERR: import library "base";
// CHECK:STDERR: ^~~~~~
// CHECK:STDERR: base.carbon:4:5: ERROR: Semantics TODO: `Non-constant ImportRefLoaded (comes up with var)`.
// CHECK:STDERR: var v: ();
// CHECK:STDERR: ^
import library "export";
var w: () = v;
// CHECK:STDOUT: --- base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .v = %v
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc4_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %v.var: ref () = var v
// CHECK:STDOUT: %v: ref () = bind_name v, %v.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .v = %import_ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: ref () = import_ref ir1, inst+5, loaded
// CHECK:STDOUT: %v: ref () = bind_export v, %import_ref
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_export.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %tuple: () = tuple_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .v = %import_ref
// CHECK:STDOUT: .w = %w
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref: ref () = import_ref ir1, inst+3, loaded [template = <error>]
// CHECK:STDOUT: %.loc15_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc15_9.2: type = converted %.loc15_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %w.var: ref () = var w
// CHECK:STDOUT: %w: ref () = bind_name w, %w.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %v.ref: ref () = name_ref v, file.%import_ref [template = <error>]
// CHECK:STDOUT: %.loc15_13: init () = tuple_init () to file.%w.var [template = constants.%tuple]
// CHECK:STDOUT: %.loc15_14: init () = converted %v.ref, %.loc15_13 [template = constants.%tuple]
// CHECK:STDOUT: assign file.%w.var, %.loc15_14
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -201,6 +201,10 @@ CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclRepeated)
CARBON_DIAGNOSTIC_KIND(ClassIncompleteWithinDefinition)
CARBON_DIAGNOSTIC_KIND(ConstructionOfAbstractClass)
// Export checking.
CARBON_DIAGNOSTIC_KIND(ExportNotImportedEntity)
CARBON_DIAGNOSTIC_KIND(ExportNotImportedEntitySource)
// Interface checking.
CARBON_DIAGNOSTIC_KIND(InterfacePreviousDefinition)
CARBON_DIAGNOSTIC_KIND(InterfaceRedefinition)
+10
View File
@@ -88,6 +88,16 @@ auto HandleBindAlias(FunctionContext& context, SemIR::InstId inst_id,
context.SetLocal(inst_id, context.GetValue(inst.value_id));
}
auto HandleBindExport(FunctionContext& context, SemIR::InstId inst_id,
SemIR::BindExport inst) -> void {
auto type_inst_id = context.sem_ir().types().GetInstId(inst.type_id);
if (type_inst_id == SemIR::InstId::BuiltinNamespaceType) {
return;
}
context.SetLocal(inst_id, context.GetValue(inst.value_id));
}
auto HandleBindName(FunctionContext& context, SemIR::InstId inst_id,
SemIR::BindName inst) -> void {
context.SetLocal(inst_id, context.GetValue(inst.value_id));
+5
View File
@@ -266,6 +266,7 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
break;
}
case BindAlias::Kind:
case BindExport::Kind:
case BindSymbolicName::Kind: {
auto name_id = untyped_inst.As<AnyBindName>().bind_name_id;
out << sem_ir.names().GetFormatted(
@@ -534,6 +535,10 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
inst_id = inst.value_id;
continue;
}
case CARBON_KIND(BindExport inst): {
inst_id = inst.value_id;
continue;
}
case CARBON_KIND(NameRef inst): {
inst_id = inst.value_id;
continue;
+1
View File
@@ -85,6 +85,7 @@ CARBON_SEM_IR_INST_KIND_IMPL(AssociatedEntityType, TYPE_ALWAYS,
CONSTANT_CONDITIONAL)
CARBON_SEM_IR_INST_KIND_IMPL(BaseDecl, TYPE_NEVER, CONSTANT_ALWAYS)
CARBON_SEM_IR_INST_KIND_IMPL(BindAlias, TYPE_NEVER, CONSTANT_NEVER)
CARBON_SEM_IR_INST_KIND_IMPL(BindExport, TYPE_NEVER, CONSTANT_NEVER)
CARBON_SEM_IR_INST_KIND_IMPL(BindName, TYPE_NEVER, CONSTANT_NEVER)
CARBON_SEM_IR_INST_KIND_IMPL(BindSymbolicName, TYPE_MAYBE,
CONSTANT_SYMBOLIC_ONLY)
+1
View File
@@ -391,6 +391,7 @@ auto InstNamer::CollectNamesInBlock(ScopeId scope_id,
continue;
}
case BindAlias::Kind:
case BindExport::Kind:
case BindName::Kind:
case BindSymbolicName::Kind: {
auto inst = untyped_inst.As<AnyBindName>();
+16 -1
View File
@@ -222,7 +222,8 @@ struct BaseDecl {
// Common representation for both kinds of `bind*name` node.
struct AnyBindName {
// TODO: Also handle BindTemplateName once it exists.
static constexpr InstKind Kinds[] = {InstKind::BindAlias, InstKind::BindName,
static constexpr InstKind Kinds[] = {InstKind::BindAlias,
InstKind::BindExport, InstKind::BindName,
InstKind::BindSymbolicName};
InstKind kind;
@@ -240,6 +241,15 @@ struct BindAlias {
InstId value_id;
};
struct BindExport {
static constexpr auto Kind =
InstKind::BindExport.Define<Parse::NodeId>("bind_export");
TypeId type_id;
BindNameId bind_name_id;
InstId value_id;
};
struct BindName {
// TODO: Make Parse::NodeId more specific.
static constexpr auto Kind =
@@ -522,6 +532,9 @@ struct AnyImportRef {
InstKind kind;
ImportIRInstId import_ir_inst_id;
// A BindName is currently only set on directly imported names. It is not
// generically available.
BindNameId bind_name_id;
};
// An imported entity that is not yet been loaded.
@@ -531,6 +544,7 @@ struct ImportRefUnloaded {
InstKind::ImportRefUnloaded.Define<Parse::InvalidNodeId>("import_ref");
ImportIRInstId import_ir_inst_id;
BindNameId bind_name_id;
};
// A imported entity that is loaded, and may be used.
@@ -541,6 +555,7 @@ struct ImportRefLoaded {
TypeId type_id;
ImportIRInstId import_ir_inst_id;
BindNameId bind_name_id;
};
// Finalizes the initialization of `dest_id` from the initializer expression