mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 20:11:12 +01:00
Add ExternDecl and ExternType for extern classes. (#3893)
This expands `extern` handling for most cases.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
namespace Carbon::Check {
|
||||
|
||||
auto MergeClassRedecl(Context& context, SemIRLoc new_loc,
|
||||
SemIR::Class& new_class, bool /*new_is_import*/,
|
||||
SemIR::Class& new_class, bool new_is_import,
|
||||
bool new_is_definition, bool new_is_extern,
|
||||
SemIR::ClassId prev_class_id, bool prev_is_extern,
|
||||
SemIR::ImportIRInstId prev_import_ir_inst_id) -> bool {
|
||||
@@ -51,6 +51,13 @@ auto MergeClassRedecl(Context& context, SemIRLoc new_loc,
|
||||
prev_class.object_repr_id = new_class.object_repr_id;
|
||||
}
|
||||
|
||||
if ((prev_import_ir_inst_id.is_valid() && !new_is_import) ||
|
||||
(prev_is_extern && !new_is_extern)) {
|
||||
prev_class.decl_id = new_class.decl_id;
|
||||
ReplacePrevInstForMerge(
|
||||
context, prev_class.enclosing_scope_id, prev_class.name_id,
|
||||
new_is_import ? new_loc.inst_id : new_class.decl_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -977,6 +977,7 @@ class TypeCompleter {
|
||||
case SemIR::ClassInit::Kind:
|
||||
case SemIR::Converted::Kind:
|
||||
case SemIR::Deref::Kind:
|
||||
case SemIR::ExternDecl::Kind:
|
||||
case SemIR::FacetTypeAccess::Kind:
|
||||
case SemIR::FloatLiteral::Kind:
|
||||
case SemIR::FieldDecl::Kind:
|
||||
@@ -1056,6 +1057,7 @@ class TypeCompleter {
|
||||
|
||||
case SemIR::AssociatedEntityType::Kind:
|
||||
case SemIR::BindSymbolicName::Kind:
|
||||
case SemIR::ExternType::Kind:
|
||||
case SemIR::FloatType::Kind:
|
||||
case SemIR::IntType::Kind:
|
||||
case SemIR::PointerType::Kind:
|
||||
|
||||
@@ -897,6 +897,15 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
return RebuildIfFieldsAreConstant(context, inst,
|
||||
&SemIR::BoundMethod::object_id,
|
||||
&SemIR::BoundMethod::function_id);
|
||||
case CARBON_KIND(SemIR::ExternDecl extern_decl): {
|
||||
// Return an extern form of the declaration's constant value.
|
||||
auto non_extern_type_id = context.GetTypeIdForTypeConstant(
|
||||
context.constant_values().Get(extern_decl.decl_id));
|
||||
return MakeConstantResult(
|
||||
context,
|
||||
SemIR::ExternType{SemIR::TypeId::TypeType, non_extern_type_id},
|
||||
Phase::Template);
|
||||
}
|
||||
case SemIR::InterfaceWitness::Kind:
|
||||
return RebuildIfFieldsAreConstant(context, inst,
|
||||
&SemIR::InterfaceWitness::elements_id);
|
||||
@@ -975,6 +984,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
}
|
||||
|
||||
case SemIR::ClassType::Kind:
|
||||
case SemIR::ExternType::Kind:
|
||||
case SemIR::InterfaceType::Kind:
|
||||
CARBON_FATAL() << inst.kind()
|
||||
<< " is only created during corresponding Decl handling.";
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// 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"
|
||||
#include "toolchain/check/merge.h"
|
||||
#include "toolchain/check/modifiers.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/typed_insts.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
@@ -35,6 +38,51 @@ auto HandleClassIntroducer(Context& context, Parse::ClassIntroducerId node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adds the name to name lookup. If there's a conflict, tries to merge. May
|
||||
// update class_decl and class_info when merging.
|
||||
static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
|
||||
const DeclNameStack::NameContext& name_context,
|
||||
SemIR::InstId class_decl_id,
|
||||
SemIR::ClassDecl& class_decl,
|
||||
SemIR::Class& class_info, bool is_definition,
|
||||
bool is_extern) -> void {
|
||||
auto prev_id =
|
||||
context.decl_name_stack().LookupOrAddName(name_context, class_decl_id);
|
||||
if (prev_id.is_valid()) {
|
||||
auto prev_inst_for_merge =
|
||||
ResolvePrevInstForMerge(context, node_id, prev_id);
|
||||
|
||||
auto prev_class_id = SemIR::ClassId::Invalid;
|
||||
CARBON_KIND_SWITCH(prev_inst_for_merge.inst) {
|
||||
case CARBON_KIND(SemIR::ClassDecl class_decl): {
|
||||
prev_class_id = class_decl.class_id;
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::ClassType class_type): {
|
||||
prev_class_id = class_type.class_id;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// This is a redeclaration of something other than a class.
|
||||
context.DiagnoseDuplicateName(class_decl_id, prev_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (prev_class_id.is_valid()) {
|
||||
if (MergeClassRedecl(context, node_id, class_info,
|
||||
/*new_is_import=*/false, is_definition, is_extern,
|
||||
prev_class_id, prev_inst_for_merge.is_extern,
|
||||
prev_inst_for_merge.import_ir_inst_id)) {
|
||||
// When merging, use the existing entity rather than adding a new one.
|
||||
class_decl.class_id = prev_class_id;
|
||||
}
|
||||
} else {
|
||||
// This is a redeclaration of something other than a class.
|
||||
context.DiagnoseDuplicateName(class_decl_id, prev_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
|
||||
bool is_definition)
|
||||
-> std::tuple<SemIR::ClassId, SemIR::InstId> {
|
||||
@@ -88,30 +136,16 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
|
||||
.decl_id = class_decl_id,
|
||||
.inheritance_kind = inheritance_kind};
|
||||
|
||||
// Check whether this is a redeclaration.
|
||||
auto prev_id =
|
||||
context.decl_name_stack().LookupOrAddName(name_context, class_decl_id);
|
||||
if (prev_id.is_valid()) {
|
||||
auto prev_inst_for_merge =
|
||||
ResolvePrevInstForMerge(context, node_id, prev_id);
|
||||
|
||||
if (auto prev_class_decl =
|
||||
prev_inst_for_merge.inst.TryAs<SemIR::ClassDecl>()) {
|
||||
// TODO: Fix prev_is_extern.
|
||||
if (MergeClassRedecl(context, node_id, class_info,
|
||||
/*new_is_import=*/false, is_definition, is_extern,
|
||||
prev_class_decl->class_id,
|
||||
/*prev_is_extern=*/false,
|
||||
prev_inst_for_merge.import_ir_inst_id)) {
|
||||
// When merging, use the existing entity rather than adding a new one.
|
||||
class_decl.class_id = prev_class_decl->class_id;
|
||||
}
|
||||
} else {
|
||||
// This is a redeclaration of something other than a class.
|
||||
context.DiagnoseDuplicateName(class_decl_id, prev_id);
|
||||
}
|
||||
auto extern_decl_id = SemIR::InstId::Invalid;
|
||||
if (is_extern) {
|
||||
extern_decl_id = context.AddPlaceholderInst(
|
||||
{node_id, SemIR::ExternDecl{SemIR::TypeId::TypeType, class_decl_id}});
|
||||
}
|
||||
|
||||
MergeOrAddName(context, node_id, name_context,
|
||||
extern_decl_id.is_valid() ? extern_decl_id : class_decl_id,
|
||||
class_decl, class_info, is_definition, is_extern);
|
||||
|
||||
// Create a new class if this isn't a valid redeclaration.
|
||||
bool is_new_class = !class_decl.class_id.is_valid();
|
||||
if (is_new_class) {
|
||||
@@ -130,6 +164,12 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
|
||||
class_info.self_type_id = context.GetTypeIdForTypeInst(class_decl_id);
|
||||
}
|
||||
|
||||
if (is_extern) {
|
||||
context.ReplaceInstBeforeConstantUse(
|
||||
extern_decl_id,
|
||||
SemIR::ExternDecl{SemIR::TypeId::TypeType, class_decl_id});
|
||||
}
|
||||
|
||||
return {class_decl.class_id, class_decl_id};
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,8 @@ static auto BuildFunctionDecl(Context& context,
|
||||
auto function_decl = SemIR::FunctionDecl{
|
||||
context.GetBuiltinType(SemIR::BuiltinKind::FunctionType),
|
||||
SemIR::FunctionId::Invalid, decl_block_id};
|
||||
// TODO: Should Function replace is_extern with ExternDecl, similar to
|
||||
// ClassDecl?
|
||||
auto function_info = SemIR::Function{
|
||||
.name_id = name_context.name_id_for_new_inst(),
|
||||
.enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(),
|
||||
|
||||
@@ -36,6 +36,11 @@ static auto GetImportName(const SemIR::File& import_sem_ir,
|
||||
return {class_info.name_id, class_info.enclosing_scope_id};
|
||||
}
|
||||
|
||||
case CARBON_KIND(SemIR::ExternDecl extern_decl): {
|
||||
return GetImportName(import_sem_ir,
|
||||
import_sem_ir.insts().Get(extern_decl.decl_id));
|
||||
}
|
||||
|
||||
case CARBON_KIND(SemIR::FunctionDecl function_decl): {
|
||||
const auto& function =
|
||||
import_sem_ir.functions().Get(function_decl.function_id);
|
||||
|
||||
@@ -409,6 +409,9 @@ class ImportRefResolver {
|
||||
case CARBON_KIND(SemIR::ConstType inst): {
|
||||
return TryResolveTypedInst(inst);
|
||||
}
|
||||
case CARBON_KIND(SemIR::ExternDecl inst): {
|
||||
return TryResolveTypedInst(inst);
|
||||
}
|
||||
case CARBON_KIND(SemIR::FieldDecl inst): {
|
||||
return TryResolveTypedInst(inst, inst_id);
|
||||
}
|
||||
@@ -669,6 +672,19 @@ class ImportRefResolver {
|
||||
SemIR::ConstType{SemIR::TypeId::TypeType, inner_type_id})};
|
||||
}
|
||||
|
||||
auto TryResolveTypedInst(SemIR::ExternDecl inst) -> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
|
||||
auto decl_const_id = GetLocalConstantId(inst.decl_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto extern_id = context_.AddInstInNoBlock(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(inst.decl_id),
|
||||
SemIR::ExternDecl{SemIR::TypeId::TypeType, decl_const_id.inst_id()}));
|
||||
return {context_.constant_values().Get(extern_id)};
|
||||
}
|
||||
|
||||
auto TryResolveTypedInst(SemIR::FieldDecl inst, SemIR::InstId import_inst_id)
|
||||
-> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
|
||||
+50
-28
@@ -127,30 +127,44 @@ auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind,
|
||||
|
||||
auto ResolvePrevInstForMerge(Context& context, Parse::NodeId node_id,
|
||||
SemIR::InstId prev_inst_id) -> InstForMerge {
|
||||
auto prev_inst = context.insts().Get(prev_inst_id);
|
||||
auto import_ref = prev_inst.TryAs<SemIR::AnyImportRef>();
|
||||
// If not imported, use the instruction directly.
|
||||
if (!import_ref) {
|
||||
return {.inst = prev_inst,
|
||||
.import_ir_inst_id = SemIR::ImportIRInstId::Invalid};
|
||||
InstForMerge result = {.inst = context.insts().Get(prev_inst_id),
|
||||
.import_ir_inst_id = SemIR::ImportIRInstId::Invalid,
|
||||
.is_extern = false};
|
||||
|
||||
CARBON_KIND_SWITCH(result.inst) {
|
||||
case CARBON_KIND(SemIR::ExternDecl extern_decl): {
|
||||
result.is_extern = true;
|
||||
result.inst = context.insts().Get(extern_decl.decl_id);
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::ImportRefUsed import_ref): {
|
||||
CARBON_DIAGNOSTIC(
|
||||
RedeclOfUsedImport, Error,
|
||||
"Redeclaration of imported entity that was previously used.");
|
||||
CARBON_DIAGNOSTIC(UsedImportLoc, Note, "Import used here.");
|
||||
context.emitter()
|
||||
.Build(node_id, RedeclOfUsedImport)
|
||||
.Note(import_ref.used_id, UsedImportLoc)
|
||||
.Emit();
|
||||
[[fallthrough]];
|
||||
}
|
||||
case SemIR::ImportRefLoaded::Kind: {
|
||||
// Follow the import ref.
|
||||
auto import_ref = result.inst.As<SemIR::AnyImportRef>();
|
||||
result.import_ir_inst_id = import_ref.import_ir_inst_id;
|
||||
result.inst = context.insts().Get(
|
||||
context.constant_values().Get(prev_inst_id).inst_id());
|
||||
if (auto extern_type = result.inst.TryAs<SemIR::ExternType>()) {
|
||||
result.inst =
|
||||
context.types().GetAsInst(extern_type->non_extern_type_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If the import ref was previously used, print a diagnostic.
|
||||
if (auto import_ref_used = prev_inst.TryAs<SemIR::ImportRefUsed>()) {
|
||||
CARBON_DIAGNOSTIC(
|
||||
RedeclOfUsedImport, Error,
|
||||
"Redeclaration of imported entity that was previously used.");
|
||||
CARBON_DIAGNOSTIC(UsedImportLoc, Note, "Import used here.");
|
||||
context.emitter()
|
||||
.Build(node_id, RedeclOfUsedImport)
|
||||
.Note(import_ref_used->used_id, UsedImportLoc)
|
||||
.Emit();
|
||||
}
|
||||
|
||||
// Follow the import ref.
|
||||
return {.inst = context.insts().Get(
|
||||
context.constant_values().Get(prev_inst_id).inst_id()),
|
||||
.import_ir_inst_id = import_ref->import_ir_inst_id};
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the instruction to consider when merging the given inst_id. Returns
|
||||
@@ -185,9 +199,18 @@ static auto ResolveMergeableInst(Context& context, SemIR::InstId inst_id)
|
||||
if (!const_id.is_constant()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return {
|
||||
{.inst = context.insts().Get(const_id.inst_id()),
|
||||
.import_ir_inst_id = inst.As<SemIR::AnyImportRef>().import_ir_inst_id}};
|
||||
|
||||
InstForMerge result = {
|
||||
.inst = context.insts().Get(const_id.inst_id()),
|
||||
.import_ir_inst_id = inst.As<SemIR::AnyImportRef>().import_ir_inst_id,
|
||||
.is_extern = false};
|
||||
|
||||
if (auto extern_type = result.inst.TryAs<SemIR::ExternType>()) {
|
||||
result.is_extern = true;
|
||||
result.inst = context.types().GetAsInst(extern_type->non_extern_type_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,
|
||||
@@ -240,11 +263,10 @@ auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
|
||||
}
|
||||
|
||||
auto new_class = context.classes().Get(new_type.class_id);
|
||||
// TODO: Fix new_is_extern and prev_is_extern.
|
||||
MergeClassRedecl(context, new_inst_id, new_class,
|
||||
/*new_is_import=*/true, new_class.is_defined(),
|
||||
/*new_is_extern=*/false, prev_type->class_id,
|
||||
/*prev_is_extern=*/false, prev_inst->import_ir_inst_id);
|
||||
new_inst->is_extern, prev_type->class_id,
|
||||
prev_inst->is_extern, prev_inst->import_ir_inst_id);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -40,6 +40,8 @@ struct InstForMerge {
|
||||
// The imported instruction, or invalid if not an import. This should
|
||||
// typically only be used for the ImportIRId, but we only load it if needed.
|
||||
SemIR::ImportIRInstId import_ir_inst_id;
|
||||
// True if an `extern` declaration.
|
||||
bool is_extern;
|
||||
};
|
||||
|
||||
// Resolves prev_inst_id for merging (or name conflicts). This handles imports
|
||||
|
||||
+23
-41
@@ -44,41 +44,19 @@ library "extern" api;
|
||||
|
||||
import Other library "extern";
|
||||
|
||||
// CHECK:STDERR: fail_extern.carbon:[[@LINE+10]]:8: ERROR: Variable has incomplete type `C`.
|
||||
// CHECK:STDERR: fail_extern.carbon:[[@LINE+4]]:1: ERROR: Cannot implicitly convert from `{}` to `extern C`.
|
||||
// CHECK:STDERR: var c: Other.C = {};
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_extern.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import Other library "extern";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: other_extern.carbon:4:1: Class was forward declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var c: Other.C = {};
|
||||
|
||||
// --- fail_todo_merge_define_extern.carbon
|
||||
// --- merge_define_extern.carbon
|
||||
|
||||
library "merge_define_extern" api;
|
||||
|
||||
import Other library "define";
|
||||
// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+12]]:1: In import.
|
||||
// CHECK:STDERR: import Other library "extern";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: other_extern.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import Other library "define";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: other_define.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
import Other library "extern";
|
||||
|
||||
// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+4]]:8: In name lookup for `C`.
|
||||
// CHECK:STDERR: var c: Other.C = {};
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var c: Other.C = {};
|
||||
|
||||
// --- fail_conflict.carbon
|
||||
@@ -130,15 +108,17 @@ var c: Other.C = {};
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .C = %.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
@@ -204,7 +184,8 @@ var c: Other.C = {};
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -216,31 +197,32 @@ var c: Other.C = {};
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Other: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Other.ref: <namespace> = name_ref Other, %Other [template = %Other]
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir3, inst+2, loc_14 [template = constants.%C]
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir3, inst+3, loc_14 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref [template = constants.%C]
|
||||
// CHECK:STDOUT: %c.var: ref <error> = var c
|
||||
// CHECK:STDOUT: %c: ref <error> = bind_name c, %c.var
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref [template = constants.%.1]
|
||||
// CHECK:STDOUT: %c.var: ref extern C = var c
|
||||
// CHECK:STDOUT: %c: ref extern C = bind_name c, %c.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc16: {} = struct_literal ()
|
||||
// CHECK:STDOUT: %.loc10: {} = struct_literal ()
|
||||
// CHECK:STDOUT: assign file.%c.var, <error>
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_merge_define_extern.carbon
|
||||
// CHECK:STDOUT: --- merge_define_extern.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.4: C = struct_value () [template]
|
||||
// CHECK:STDOUT: %.2: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %.3: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.5: C = struct_value () [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -255,7 +237,7 @@ var c: Other.C = {};
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir3, inst+2, loc_19 [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+3, unloaded
|
||||
// CHECK:STDOUT: %import_ref.3: type = import_ref ir4, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.3: type = import_ref ir4, inst+3, loaded [template = constants.%.2]
|
||||
// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {}
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %c.var: ref C = var c
|
||||
@@ -271,10 +253,10 @@ var c: Other.C = {};
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc23_19.1: {} = struct_literal ()
|
||||
// CHECK:STDOUT: %.loc23_19.2: init C = class_init (), file.%c.var [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc23_20: init C = converted %.loc23_19.1, %.loc23_19.2 [template = constants.%.4]
|
||||
// CHECK:STDOUT: assign file.%c.var, %.loc23_20
|
||||
// CHECK:STDOUT: %.loc7_19.1: {} = struct_literal ()
|
||||
// CHECK:STDOUT: %.loc7_19.2: init C = class_init (), file.%c.var [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc7_20: init C = converted %.loc7_19.1, %.loc7_19.2 [template = constants.%.5]
|
||||
// CHECK:STDOUT: assign file.%c.var, %.loc7_20
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+98
-179
@@ -41,12 +41,12 @@ class C {}
|
||||
library "fail_decl_fn_in_extern" api;
|
||||
|
||||
extern class C;
|
||||
// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+7]]:4: ERROR: Cannot declare a member of incomplete class `C`.
|
||||
// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+7]]:6: ERROR: Name qualifiers are only allowed for entities that provide a scope.
|
||||
// CHECK:STDERR: fn C.F();
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+4]]:4: Non-scope entity referenced here.
|
||||
// CHECK:STDERR: fn C.F();
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE-4]]:1: Class was forward declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn C.F();
|
||||
|
||||
@@ -100,11 +100,18 @@ class C {
|
||||
extern class D;
|
||||
}
|
||||
|
||||
// --- todo_fail_def_after_extern_decl.carbon
|
||||
// --- fail_def_after_extern_decl.carbon
|
||||
|
||||
library "fail_def_after_extern_decl" api;
|
||||
|
||||
extern class C;
|
||||
// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `class C` in the same library must match use of `extern`.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
class C {}
|
||||
|
||||
// --- fail_extern_decl_after_decl.carbon
|
||||
@@ -121,64 +128,25 @@ class C;
|
||||
// CHECK:STDERR:
|
||||
extern class C;
|
||||
|
||||
// --- fail_todo_import_extern_decl_then_decl.carbon
|
||||
// --- import_extern_decl_then_decl.carbon
|
||||
|
||||
library "import_extern_decl_then_decl" api;
|
||||
|
||||
import library "extern_decl";
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: import library "decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: class C;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
import library "decl";
|
||||
|
||||
// --- fail_todo_import_decl_then_extern_decl.carbon
|
||||
// --- import_decl_then_extern_decl.carbon
|
||||
|
||||
library "import_decl_then_extern_decl" api;
|
||||
|
||||
import library "decl";
|
||||
// CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: class C;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
import library "extern_decl";
|
||||
|
||||
// --- fail_todo_import_extern_decl_then_def.carbon
|
||||
// --- import_extern_decl_then_def.carbon
|
||||
|
||||
library "import_extern_decl_then_def" api;
|
||||
|
||||
import library "extern_decl";
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: import library "def";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
import library "def";
|
||||
|
||||
// --- fail_import_ownership_conflict.carbon
|
||||
@@ -186,124 +154,58 @@ import library "def";
|
||||
library "fail_import_ownership_conflict" api;
|
||||
|
||||
import library "extern_decl";
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: import library "decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: class C;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
import library "decl";
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+12]]:1: In import.
|
||||
// CHECK:STDERR: import library "def";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-21]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: class C;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
import library "def";
|
||||
|
||||
// --- fail_todo_import_extern_decl_copy.carbon
|
||||
// --- import_extern_decl_copy.carbon
|
||||
|
||||
library "import_extern_decl_copy" api;
|
||||
|
||||
import library "extern_decl";
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+13]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl_copy";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl_copy.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE-7]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
import library "extern_decl_copy";
|
||||
|
||||
// --- fail_todo_extern_decl_after_import_extern_decl.carbon
|
||||
// --- extern_decl_after_import_extern_decl.carbon
|
||||
|
||||
library "extern_decl_after_import_extern_decl" api;
|
||||
|
||||
import library "extern_decl";
|
||||
|
||||
// CHECK:STDERR: fail_todo_extern_decl_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_extern_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import library "extern_decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
extern class C;
|
||||
|
||||
// --- fail_todo_decl_after_import_extern_decl.carbon
|
||||
// --- decl_after_import_extern_decl.carbon
|
||||
|
||||
library "decl_after_import_extern_decl" api;
|
||||
|
||||
import library "decl";
|
||||
|
||||
// CHECK:STDERR: fail_todo_decl_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import library "decl";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: decl.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: class C;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
extern class C;
|
||||
|
||||
// --- fail_todo_def_after_import_extern_decl.carbon
|
||||
// --- def_after_import_extern_decl.carbon
|
||||
|
||||
library "def_after_import_extern_decl" api;
|
||||
|
||||
import library "def";
|
||||
|
||||
// CHECK:STDERR: fail_todo_def_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_def_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import library "def";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: def.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
extern class C;
|
||||
|
||||
// --- fail_todo_extern_decl_after_import_def.carbon
|
||||
// --- extern_decl_after_import_def.carbon
|
||||
|
||||
library "extern_decl_after_import_def" api;
|
||||
|
||||
import library "def";
|
||||
|
||||
// CHECK:STDERR: fail_todo_extern_decl_after_import_def.carbon:[[@LINE+9]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: extern class C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_extern_decl_after_import_def.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import library "def";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: def.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: class C {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
extern class C;
|
||||
|
||||
// CHECK:STDOUT: --- decl.carbon
|
||||
@@ -327,15 +229,17 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .C = %.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
@@ -344,15 +248,17 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .C = %.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
@@ -382,15 +288,17 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .C = %.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl [template = constants.%.1]
|
||||
// CHECK:STDOUT: %.loc12: <function> = fn_decl @.1 [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -423,16 +331,19 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc4
|
||||
// CHECK:STDOUT: .C = %.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc12: type = extern_decl %C.decl.loc12 [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
@@ -441,15 +352,17 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc4
|
||||
// CHECK:STDOUT: .C = %C.decl.loc12
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -482,21 +395,23 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @D;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- todo_fail_def_after_extern_decl.carbon
|
||||
// CHECK:STDOUT: --- fail_def_after_extern_decl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc4
|
||||
// CHECK:STDOUT: .C = %C.decl.loc12
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc5: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
@@ -508,6 +423,7 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -518,23 +434,25 @@ extern class C;
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %.loc12: type = extern_decl %C.decl.loc12 [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_extern_decl_then_decl.carbon
|
||||
// CHECK:STDOUT: --- import_extern_decl_then_decl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref.1
|
||||
// CHECK:STDOUT: .C = %import_ref.2
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+3, loaded [template = constants.%.1]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+2, loaded [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {}
|
||||
@@ -545,10 +463,11 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.2;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_decl_then_extern_decl.carbon
|
||||
// CHECK:STDOUT: --- import_decl_then_extern_decl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -558,7 +477,7 @@ extern class C;
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+2, loaded [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+3, loaded [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {}
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
@@ -568,20 +487,21 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.2;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_extern_decl_then_def.carbon
|
||||
// CHECK:STDOUT: --- import_extern_decl_then_def.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: %.2: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref.1
|
||||
// CHECK:STDOUT: .C = %import_ref.2
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+3, loaded [template = constants.%.2]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+2, loaded [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %import_ref.3 = import_ref ir3, inst+3, unloaded
|
||||
@@ -604,16 +524,17 @@ extern class C;
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %C.3: type = class_type @C.3 [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.2: 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: .C = %import_ref.2
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+3, loaded [template = constants.%.1]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+2, loaded [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {}
|
||||
@@ -623,23 +544,25 @@ extern class C;
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.1;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.2 {
|
||||
// CHECK:STDOUT: class @C.1 {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.2;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.3 {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_extern_decl_copy.carbon
|
||||
// CHECK:STDOUT: --- import_extern_decl_copy.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C.1: type = class_type @C.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: %C.2: type = class_type @C.2 [template]
|
||||
// CHECK:STDOUT: %.2: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -647,8 +570,8 @@ extern class C;
|
||||
// CHECK:STDOUT: .C = %import_ref.1
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C.2]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+2, loaded [template = constants.%C.1]
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+3, loaded [template = constants.%.2]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir3, inst+3, loaded [template = constants.%.1]
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {}
|
||||
// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {}
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
@@ -658,71 +581,70 @@ extern class C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C.2;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_extern_decl_after_import_extern_decl.carbon
|
||||
// CHECK:STDOUT: --- extern_decl_after_import_extern_decl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+2, loaded [template = constants.%C]
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+3, loaded [template = constants.%.1]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.1] {
|
||||
// CHECK:STDOUT: %C.decl: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc6: type = class_decl @C [template = constants.%C] {
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_decl_after_import_extern_decl.carbon
|
||||
// CHECK:STDOUT: --- decl_after_import_extern_decl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %.1: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+2, loaded [template = constants.%C]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.1] {
|
||||
// CHECK:STDOUT: %C.decl: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc6: type = class_decl @C [template = constants.%C] {
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.1]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_def_after_import_extern_decl.carbon
|
||||
// CHECK:STDOUT: --- def_after_import_extern_decl.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 = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %.2: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref.1
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+3, unloaded
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.2] {
|
||||
// CHECK:STDOUT: %C.decl: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc6: type = class_decl @C [template = constants.%C] {
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.2]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
@@ -730,27 +652,26 @@ extern class C;
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_extern_decl_after_import_def.carbon
|
||||
// CHECK:STDOUT: --- extern_decl_after_import_def.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 = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %.2: type = extern_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .C = %import_ref.1
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%C]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+3, unloaded
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.2] {
|
||||
// CHECK:STDOUT: %C.decl: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %C.decl.loc6: type = class_decl @C [template = constants.%C] {
|
||||
// CHECK:STDOUT: %C.decl.1: invalid = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.2]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
@@ -758,5 +679,3 @@ extern class C;
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1;
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+6
-12
@@ -19,13 +19,13 @@ library "b" api;
|
||||
|
||||
import library "a";
|
||||
|
||||
// CHECK:STDERR: fail_b.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: fail_b.carbon:[[@LINE+10]]:1: ERROR: Only one library can declare `class Empty` without `extern`.
|
||||
// CHECK:STDERR: class Empty {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_b.carbon:[[@LINE-5]]:1: In import.
|
||||
// CHECK:STDERR: import library "a";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: a.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: a.carbon:4:1: Previously declared here.
|
||||
// CHECK:STDERR: class Empty {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
@@ -74,23 +74,22 @@ var a: Incomplete;
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Empty: type = class_type @Empty [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.2: type = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %Incomplete: type = class_type @Incomplete [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Empty = %import_ref.1
|
||||
// CHECK:STDOUT: .Incomplete = %import_ref.2
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Empty = %Empty.decl.loc16
|
||||
// CHECK:STDOUT: .a = %a
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loaded [template = constants.%Empty]
|
||||
// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+5, loc_15 [template = constants.%Incomplete]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+3, unloaded
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.2] {
|
||||
// CHECK:STDOUT: %Empty.decl: invalid = class_decl @Empty [template = constants.%Empty] {}
|
||||
// CHECK:STDOUT: %Empty.decl.loc16: type = class_decl @Empty [template = constants.%Empty] {
|
||||
// CHECK:STDOUT: %Empty.decl.1: invalid = class_decl @Empty [template = constants.%Empty] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Incomplete.decl: invalid = class_decl @Incomplete [template = constants.%Incomplete] {}
|
||||
// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, %import_ref.2 [template = constants.%Incomplete]
|
||||
@@ -100,12 +99,7 @@ var a: Incomplete;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Empty {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = file.%import_ref.3
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1 {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%.2
|
||||
// CHECK:STDOUT: .Self = constants.%Empty
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Incomplete;
|
||||
|
||||
+10
-25
@@ -10,22 +10,10 @@ library "a" api;
|
||||
|
||||
class ForwardDecl;
|
||||
|
||||
// --- fail_b.carbon
|
||||
// --- a.impl.carbon
|
||||
|
||||
library "b" api;
|
||||
library "a" impl;
|
||||
|
||||
import library "a";
|
||||
|
||||
// TODO: This should probably have a valid form.
|
||||
// CHECK:STDERR: fail_b.carbon:[[@LINE+9]]:1: ERROR: Duplicate name being declared in the same scope.
|
||||
// CHECK:STDERR: class ForwardDecl {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_b.carbon:[[@LINE-6]]:1: In import.
|
||||
// CHECK:STDERR: import library "a";
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: a.carbon:4:1: Name is previously declared here.
|
||||
// CHECK:STDERR: class ForwardDecl;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
class ForwardDecl {
|
||||
}
|
||||
|
||||
@@ -46,30 +34,27 @@ class ForwardDecl {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @ForwardDecl;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_b.carbon
|
||||
// CHECK:STDOUT: --- a.impl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %ForwardDecl: type = class_type @ForwardDecl [template]
|
||||
// CHECK:STDOUT: %.1: type = class_type @.1 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .ForwardDecl = %import_ref
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .ForwardDecl = %ForwardDecl.decl.loc4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+2, loaded [template = constants.%ForwardDecl]
|
||||
// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+2, loaded [template = constants.%ForwardDecl]
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %.decl: type = class_decl @.1 [template = constants.%.1] {
|
||||
// CHECK:STDOUT: %ForwardDecl.decl: invalid = class_decl @ForwardDecl [template = constants.%ForwardDecl] {}
|
||||
// CHECK:STDOUT: %ForwardDecl.decl.loc4: type = class_decl @ForwardDecl [template = constants.%ForwardDecl] {
|
||||
// CHECK:STDOUT: %ForwardDecl.decl.1: invalid = class_decl @ForwardDecl [template = constants.%ForwardDecl] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @ForwardDecl;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @.1 {
|
||||
// CHECK:STDOUT: class @ForwardDecl {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%.1
|
||||
// CHECK:STDOUT: .Self = constants.%ForwardDecl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -12,6 +12,11 @@
|
||||
|
||||
namespace Carbon::Lower {
|
||||
|
||||
auto HandleExternDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
|
||||
SemIR::ExternDecl /*inst*/) -> void {
|
||||
// No action to perform.
|
||||
}
|
||||
|
||||
auto HandleClassDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
|
||||
SemIR::ClassDecl /*inst*/) -> void {
|
||||
// No action to perform.
|
||||
|
||||
@@ -27,6 +27,11 @@ auto HandleConstType(FunctionContext& context, SemIR::InstId inst_id,
|
||||
context.SetLocal(inst_id, context.GetTypeAsValue());
|
||||
}
|
||||
|
||||
auto HandleExternType(FunctionContext& context, SemIR::InstId inst_id,
|
||||
SemIR::ExternType /*inst*/) -> void {
|
||||
context.SetLocal(inst_id, context.GetTypeAsValue());
|
||||
}
|
||||
|
||||
auto HandleFacetTypeAccess(FunctionContext& context, SemIR::InstId inst_id,
|
||||
SemIR::FacetTypeAccess /*inst*/) -> void {
|
||||
context.SetLocal(inst_id, context.GetTypeAsValue());
|
||||
|
||||
@@ -206,6 +206,7 @@ static auto GetTypePrecedence(InstKind kind) -> int {
|
||||
case BindSymbolicName::Kind:
|
||||
case Builtin::Kind:
|
||||
case ClassType::Kind:
|
||||
case ExternType::Kind:
|
||||
case FacetTypeAccess::Kind:
|
||||
case FloatType::Kind:
|
||||
case ImportRefLoaded::Kind:
|
||||
@@ -246,6 +247,7 @@ static auto GetTypePrecedence(InstKind kind) -> int {
|
||||
case ClassInit::Kind:
|
||||
case Converted::Kind:
|
||||
case Deref::Kind:
|
||||
case ExternDecl::Kind:
|
||||
case FieldDecl::Kind:
|
||||
case FloatLiteral::Kind:
|
||||
case FunctionDecl::Kind:
|
||||
@@ -379,6 +381,11 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(ExternType inst): {
|
||||
out << "extern ";
|
||||
push_inst_id(sem_ir.types().GetInstId(inst.non_extern_type_id));
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(FacetTypeAccess inst): {
|
||||
// Print `T as type` as simply `T`.
|
||||
push_inst_id(inst.facet_id);
|
||||
@@ -521,6 +528,7 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
|
||||
case ClassInit::Kind:
|
||||
case Converted::Kind:
|
||||
case Deref::Kind:
|
||||
case ExternDecl::Kind:
|
||||
case FieldDecl::Kind:
|
||||
case FloatLiteral::Kind:
|
||||
case FunctionDecl::Kind:
|
||||
@@ -640,6 +648,8 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
|
||||
case ClassDecl::Kind:
|
||||
case ClassType::Kind:
|
||||
case ConstType::Kind:
|
||||
case ExternDecl::Kind:
|
||||
case ExternType::Kind:
|
||||
case FacetTypeAccess::Kind:
|
||||
case FloatLiteral::Kind:
|
||||
case FloatType::Kind:
|
||||
|
||||
@@ -48,6 +48,8 @@ CARBON_SEM_IR_INST_KIND(ClassType)
|
||||
CARBON_SEM_IR_INST_KIND(ConstType)
|
||||
CARBON_SEM_IR_INST_KIND(Converted)
|
||||
CARBON_SEM_IR_INST_KIND(Deref)
|
||||
CARBON_SEM_IR_INST_KIND(ExternDecl)
|
||||
CARBON_SEM_IR_INST_KIND(ExternType)
|
||||
CARBON_SEM_IR_INST_KIND(FacetTypeAccess)
|
||||
CARBON_SEM_IR_INST_KIND(FloatLiteral)
|
||||
CARBON_SEM_IR_INST_KIND(FloatType)
|
||||
|
||||
@@ -434,6 +434,22 @@ struct Deref {
|
||||
InstId pointer_id;
|
||||
};
|
||||
|
||||
struct ExternDecl {
|
||||
static constexpr auto Kind =
|
||||
InstKind::ExternDecl.Define<Parse::NodeId>("extern_decl");
|
||||
|
||||
TypeId type_id;
|
||||
InstId decl_id;
|
||||
};
|
||||
|
||||
struct ExternType {
|
||||
static constexpr auto Kind =
|
||||
InstKind::ExternType.Define<Parse::NodeId>("extern_type");
|
||||
|
||||
TypeId type_id;
|
||||
TypeId non_extern_type_id;
|
||||
};
|
||||
|
||||
// Represents accessing the `type` field in a facet value, which is notionally a
|
||||
// pair of a type and a witness.
|
||||
struct FacetTypeAccess {
|
||||
|
||||
Reference in New Issue
Block a user