diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index f4e428ac6f556..7fa0bc3e85cf8 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -50,6 +50,7 @@ cc_library( cc_library( name = "context", srcs = [ + "class.cpp", "context.cpp", "convert.cpp", "decl_name_stack.cpp", @@ -63,6 +64,7 @@ cc_library( "subst.cpp", ], hdrs = [ + "class.h", "context.h", "convert.h", "decl_name_stack.h", diff --git a/toolchain/check/class.cpp b/toolchain/check/class.cpp new file mode 100644 index 0000000000000..8a19556cb7a1f --- /dev/null +++ b/toolchain/check/class.cpp @@ -0,0 +1,57 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/class.h" + +#include "toolchain/check/merge.h" + +namespace Carbon::Check { + +auto MergeClassRedecl(Context& context, SemIRLoc new_loc, + 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 { + auto& prev_class = context.classes().Get(prev_class_id); + SemIRLoc prev_loc = + prev_class.is_defined() ? prev_class.definition_id : prev_class.decl_id; + + // TODO: Check that the generic parameter list agrees with the prior + // declaration. + + CheckIsAllowedRedecl(context, Lex::TokenKind::Class, prev_class.name_id, + {.loc = new_loc, + .is_definition = new_is_definition, + .is_extern = new_is_extern}, + {.loc = prev_loc, + .is_definition = prev_class.is_defined(), + .is_extern = prev_is_extern}, + prev_import_ir_inst_id); + + // The introducer kind must match the previous declaration. + // TODO: The rule here is not yet decided. See #3384. + if (prev_class.inheritance_kind != new_class.inheritance_kind) { + CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducer, Error, + "Class redeclared with different inheritance kind."); + CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducerPrevious, Note, + "Previously declared here."); + context.emitter() + .Build(new_loc, ClassRedeclarationDifferentIntroducer) + .Note(prev_loc, ClassRedeclarationDifferentIntroducerPrevious) + .Emit(); + } + + if (new_is_definition) { + prev_class.definition_id = new_class.definition_id; + prev_class.scope_id = new_class.scope_id; + prev_class.body_block_id = new_class.body_block_id; + prev_class.adapt_id = new_class.adapt_id; + prev_class.base_id = new_class.base_id; + prev_class.object_repr_id = new_class.object_repr_id; + } + + return true; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/class.h b/toolchain/check/class.h new file mode 100644 index 0000000000000..2a52656977063 --- /dev/null +++ b/toolchain/check/class.h @@ -0,0 +1,28 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_CLASS_H_ +#define CARBON_TOOLCHAIN_CHECK_CLASS_H_ + +#include "toolchain/check/context.h" +#include "toolchain/sem_ir/class.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +// Tries to merge new_class into prev_class_id. Since new_class won't have a +// definition even if one is upcoming, set is_definition to indicate the planned +// result. +// +// If merging is successful, returns true and may update the previous class. +// Otherwise, returns false. Prints a diagnostic when appropriate. +auto MergeClassRedecl(Context& context, SemIRLoc new_loc, + 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; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_CLASS_H_ diff --git a/toolchain/check/function.h b/toolchain/check/function.h index 9138f949d5e6f..22fa24ed699e6 100644 --- a/toolchain/check/function.h +++ b/toolchain/check/function.h @@ -40,8 +40,8 @@ auto CheckFunctionTypeMatches(Context& context, // have a definition even if one is upcoming, set is_definition to indicate the // planned result. // -// If merging is successful, updates the FunctionId on new_function and returns -// true. Otherwise, returns false. Prints a diagnostic when appropriate. +// If merging is successful, returns true and may update the previous function. +// Otherwise, returns false. Prints a diagnostic when appropriate. auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc, SemIR::Function& new_function, bool new_is_import, bool new_is_definition, diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index cded323e3d04a..7aa67913a2576 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -2,8 +2,10 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include "toolchain/check/class.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" +#include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/sem_ir/typed_insts.h" @@ -33,7 +35,8 @@ auto HandleClassIntroducer(Context& context, Parse::ClassIntroducerId node_id) return true; } -static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) +static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, + bool is_definition) -> std::tuple { if (context.node_stack().PopIf()) { context.TODO(node_id, "generic class"); @@ -50,8 +53,11 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) CheckAccessModifiersOnDecl(context, Lex::TokenKind::Class, name_context.target_scope_id); LimitModifiersOnDecl(context, - KeywordModifierSet::Class | KeywordModifierSet::Access, + KeywordModifierSet::Class | KeywordModifierSet::Access | + KeywordModifierSet::Extern, Lex::TokenKind::Class); + RestrictExternModifierOnDecl(context, Lex::TokenKind::Class, + name_context.target_scope_id, is_definition); auto modifiers = context.decl_state_stack().innermost().modifier_set; if (!!(modifiers & KeywordModifierSet::Access)) { @@ -59,6 +65,8 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) ModifierOrder::Access), "access modifier"); } + + bool is_extern = !!(modifiers & KeywordModifierSet::Extern); auto inheritance_kind = !!(modifiers & KeywordModifierSet::Abstract) ? SemIR::Class::Abstract : !!(modifiers & KeywordModifierSet::Base) ? SemIR::Class::Base @@ -72,34 +80,35 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) SemIR::ClassId::Invalid, decl_block_id}; auto class_decl_id = context.AddPlaceholderInst({node_id, class_decl}); + SemIR::Class class_info = { + .name_id = name_context.name_id_for_new_inst(), + .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(), + // `.self_type_id` depends on the ClassType, so is set below. + .self_type_id = SemIR::TypeId::Invalid, + .decl_id = class_decl_id, + .inheritance_kind = inheritance_kind}; + // Check whether this is a redeclaration. - auto existing_id = + auto prev_id = context.decl_name_stack().LookupOrAddName(name_context, class_decl_id); - if (existing_id.is_valid()) { - if (auto existing_class_decl = - context.insts().Get(existing_id).TryAs()) { - // This is a redeclaration of an existing class. - class_decl.class_id = existing_class_decl->class_id; - auto& class_info = context.classes().Get(class_decl.class_id); - - // The introducer kind must match the previous declaration. - // TODO: The rule here is not yet decided. See #3384. - if (class_info.inheritance_kind != inheritance_kind) { - CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducer, Error, - "Class redeclared with different inheritance kind."); - CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducerPrevious, Note, - "Previously declared here."); - context.emitter() - .Build(node_id, ClassRedeclarationDifferentIntroducer) - .Note(existing_id, ClassRedeclarationDifferentIntroducerPrevious) - .Emit(); + 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()) { + // 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; } - - // TODO: Check that the generic parameter list agrees with the prior - // declaration. } else { // This is a redeclaration of something other than a class. - context.DiagnoseDuplicateName(class_decl_id, existing_id); + context.DiagnoseDuplicateName(class_decl_id, prev_id); } } @@ -109,13 +118,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) // TODO: If this is an invalid redeclaration of a non-class entity or there // was an error in the qualifier, we will have lost track of the class name // here. We should keep track of it even if the name is invalid. - class_decl.class_id = context.classes().Add( - {.name_id = name_context.name_id_for_new_inst(), - .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(), - // `.self_type_id` depends on the ClassType, so is set below. - .self_type_id = SemIR::TypeId::Invalid, - .decl_id = class_decl_id, - .inheritance_kind = inheritance_kind}); + class_decl.class_id = context.classes().Add(class_info); } // Write the class ID into the ClassDecl. @@ -131,27 +134,19 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id) } auto HandleClassDecl(Context& context, Parse::ClassDeclId node_id) -> bool { - BuildClassDecl(context, node_id); + BuildClassDecl(context, node_id, /*is_definition=*/false); context.decl_name_stack().PopScope(); return true; } auto HandleClassDefinitionStart(Context& context, Parse::ClassDefinitionStartId node_id) -> bool { - auto [class_id, class_decl_id] = BuildClassDecl(context, node_id); + auto [class_id, class_decl_id] = + BuildClassDecl(context, node_id, /*is_definition=*/true); auto& class_info = context.classes().Get(class_id); // Track that this declaration is the definition. - if (class_info.is_defined()) { - CARBON_DIAGNOSTIC(ClassRedefinition, Error, "Redefinition of class {0}.", - SemIR::NameId); - CARBON_DIAGNOSTIC(ClassPreviousDefinition, Note, - "Previous definition was here."); - context.emitter() - .Build(node_id, ClassRedefinition, class_info.name_id) - .Note(class_info.definition_id, ClassPreviousDefinition) - .Emit(); - } else { + if (!class_info.is_defined()) { class_info.definition_id = class_decl_id; class_info.scope_id = context.name_scopes().Add( class_decl_id, SemIR::NameId::Invalid, class_info.enclosing_scope_id); diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index badb823f4a064..6e59a90e50f25 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -47,22 +47,13 @@ static auto DiagnoseModifiers(Context& context, bool is_definition, -> KeywordModifierSet { const Lex::TokenKind decl_kind = Lex::TokenKind::Fn; CheckAccessModifiersOnDecl(context, decl_kind, target_scope_id); - if (is_definition) { - ForbidExternModifierOnDefinition(context, decl_kind); - } - if (target_scope_id.is_valid()) { - auto target_id = context.name_scopes().Get(target_scope_id).inst_id; - if (target_id.is_valid() && - !context.insts().Is(target_id)) { - ForbidModifiersOnDecl(context, KeywordModifierSet::Extern, decl_kind, - " that is a member"); - } - } LimitModifiersOnDecl(context, KeywordModifierSet::Access | KeywordModifierSet::Extern | KeywordModifierSet::Method | KeywordModifierSet::Interface, decl_kind); + RestrictExternModifierOnDecl(context, decl_kind, target_scope_id, + is_definition); CheckMethodModifiersOnFunction(context, target_scope_id); RequireDefaultFinalOnlyInInterfaces(context, decl_kind, target_scope_id); @@ -163,14 +154,14 @@ static auto BuildFunctionDecl(Context& context, auto prev_inst_for_merge = ResolvePrevInstForMerge(context, node_id, prev_id); - if (auto existing_function_decl = + if (auto prev_function_decl = prev_inst_for_merge.inst.TryAs()) { if (MergeFunctionRedecl(context, node_id, function_info, /*new_is_import=*/false, is_definition, - existing_function_decl->function_id, + prev_function_decl->function_id, prev_inst_for_merge.import_ir_inst_id)) { // When merging, use the existing function rather than adding a new one. - function_decl.function_id = existing_function_decl->function_id; + function_decl.function_id = prev_function_decl->function_id; } } else { // This is a redeclaration of something other than a function. This diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index fb9a39b75fed6..3ec995f89cdb7 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -571,6 +571,8 @@ class ImportRefResolver { SemIR::Class& new_class, SemIR::ConstantId object_repr_const_id, SemIR::ConstantId base_const_id) -> void { + new_class.definition_id = new_class.decl_id; + new_class.object_repr_id = context_.GetTypeIdForTypeConstant(object_repr_const_id); diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index 7f08cc7b3027b..a66693dac5b91 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/merge.h" #include "toolchain/base/kind_switch.h" +#include "toolchain/check/class.h" #include "toolchain/check/function.h" #include "toolchain/check/import_ref.h" #include "toolchain/sem_ir/ids.h" @@ -232,6 +233,20 @@ auto MergeImportRef(Context& context, SemIR::InstId new_inst_id, prev_inst->import_ir_inst_id); return; } + case CARBON_KIND(SemIR::ClassType new_type): { + auto prev_type = prev_inst->inst.TryAs(); + if (!prev_type) { + break; + } + + 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); + return; + } default: context.TODO(new_inst_id, llvm::formatv("Merging {0} not yet supported.", new_inst->inst.kind())); diff --git a/toolchain/check/modifiers.cpp b/toolchain/check/modifiers.cpp index 39dc899ab8e4a..f641867cfb458 100644 --- a/toolchain/check/modifiers.cpp +++ b/toolchain/check/modifiers.cpp @@ -136,10 +136,21 @@ auto CheckMethodModifiersOnFunction(Context& context, " outside of a class"); } -auto ForbidExternModifierOnDefinition(Context& context, - Lex::TokenKind decl_kind) -> void { - ForbidModifiersOnDecl(context, KeywordModifierSet::Extern, decl_kind, - " that provides a definition"); +auto RestrictExternModifierOnDecl(Context& context, Lex::TokenKind decl_kind, + SemIR::NameScopeId target_scope_id, + bool is_definition) -> void { + if (is_definition) { + ForbidModifiersOnDecl(context, KeywordModifierSet::Extern, decl_kind, + " that provides a definition"); + } + if (target_scope_id.is_valid()) { + auto target_id = context.name_scopes().Get(target_scope_id).inst_id; + if (target_id.is_valid() && + !context.insts().Is(target_id)) { + ForbidModifiersOnDecl(context, KeywordModifierSet::Extern, decl_kind, + " that is a member"); + } + } } auto RequireDefaultFinalOnlyInInterfaces(Context& context, diff --git a/toolchain/check/modifiers.h b/toolchain/check/modifiers.h index 39a2483cdf944..32cfcdd761fa4 100644 --- a/toolchain/check/modifiers.h +++ b/toolchain/check/modifiers.h @@ -43,10 +43,13 @@ inline auto LimitModifiersOnDecl(Context& context, KeywordModifierSet allowed, ForbidModifiersOnDecl(context, ~allowed, decl_kind, ""); } -// If the `extern` modifier is present, diagnoses and updates the declaration -// state to remove it. Only called for declarations with definitions. -auto ForbidExternModifierOnDefinition(Context& context, - Lex::TokenKind decl_kind) -> void; +// Restricts the `extern` modifier to only be used on namespace-scoped +// declarations, diagnosing and removing it on: +// - `extern` on a definition. +// - `extern` on a scoped entity. +auto RestrictExternModifierOnDecl(Context& context, Lex::TokenKind decl_kind, + SemIR::NameScopeId target_scope_id, + bool is_definition) -> void; // Report a diagonostic if `default` and `final` modifiers are used on // declarations where they are not allowed. Right now they are only allowed diff --git a/toolchain/check/testdata/class/cross_package_import.carbon b/toolchain/check/testdata/class/cross_package_import.carbon index a92b6047b5458..efe43a1413126 100644 --- a/toolchain/check/testdata/class/cross_package_import.carbon +++ b/toolchain/check/testdata/class/cross_package_import.carbon @@ -18,8 +18,7 @@ class C {} package Other library "extern" api; -// TODO: Mark extern -class C; +extern class C; // --- other_conflict.carbon @@ -51,26 +50,32 @@ import Other library "extern"; // CHECK:STDERR: fail_extern.carbon:[[@LINE-5]]:1: In import. // CHECK:STDERR: import Other library "extern"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: other_extern.carbon:5:1: Class was forward declared here. -// CHECK:STDERR: class C; -// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: other_extern.carbon:4:1: Class was forward declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: var c: Other.C = {}; -// --- fail_merge_define_extern.carbon +// --- fail_todo_merge_define_extern.carbon -library "fail_merge_define_extern" api; +library "merge_define_extern" api; import Other library "define"; -// CHECK:STDERR: fail_merge_define_extern.carbon:[[@LINE+6]]:1: In import. +// 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:5:1: ERROR: Semantics TODO: `Merging ClassType not yet supported.`. -// CHECK:STDERR: class C; -// 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_merge_define_extern.carbon:[[@LINE+4]]:8: In name lookup for `C`. +// 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: @@ -227,7 +232,7 @@ var c: Other.C = {}; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_merge_define_extern.carbon +// CHECK:STDOUT: --- fail_todo_merge_define_extern.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C.1: type = class_type @C.1 [template] @@ -266,10 +271,10 @@ var c: Other.C = {}; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc17_19.1: {} = struct_literal () -// CHECK:STDOUT: %.loc17_19.2: init C = class_init (), file.%c.var [template = constants.%.4] -// CHECK:STDOUT: %.loc17_20: init C = converted %.loc17_19.1, %.loc17_19.2 [template = constants.%.4] -// CHECK:STDOUT: assign file.%c.var, %.loc17_20 +// 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: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/extern.carbon b/toolchain/check/testdata/class/extern.carbon new file mode 100644 index 0000000000000..735c12369d3df --- /dev/null +++ b/toolchain/check/testdata/class/extern.carbon @@ -0,0 +1,762 @@ +// 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 +// ============================================================================ + +// --- decl.carbon + +library "decl" api; + +class C; + +// --- extern_decl.carbon + +library "extern_decl" api; + +extern class C; + +// --- extern_decl_copy.carbon + +library "extern_decl_copy" api; + +extern class C; + +// --- def.carbon + +library "def" api; + +class C {} + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_decl_fn_in_extern.carbon + +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: 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(); + +// --- fail_extern_def.carbon + +library "fail_extern_def" api; + +// CHECK:STDERR: fail_extern_def.carbon:[[@LINE+4]]:1: ERROR: `extern` not allowed on `class` declaration that provides a definition. +// CHECK:STDERR: extern class C {} +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +extern class C {} + +// --- fail_extern_decl_after_extern_decl.carbon + +library "fail_extern_decl_after_extern_decl" api; + +extern class C; +// CHECK:STDERR: fail_extern_decl_after_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclaration of `class C` is redundant. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_decl_after_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +extern class C; + +// --- fail_decl_after_extern_decl.carbon + +library "fail_decl_after_extern_decl" api; + +extern class C; +// CHECK:STDERR: fail_decl_after_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclaration of `class C` is redundant. +// CHECK:STDERR: class C; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: fail_decl_after_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +class C; + +// --- fail_extern_member_class.carbon + +library "fail_extern_member_class" api; + +class C { + // CHECK:STDERR: fail_extern_member_class.carbon:[[@LINE+4]]:3: ERROR: `extern` not allowed on `class` declaration that is a member. + // CHECK:STDERR: extern class D; + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: + extern class D; +} + +// --- todo_fail_def_after_extern_decl.carbon + +library "fail_def_after_extern_decl" api; + +extern class C; +class C {} + +// --- fail_extern_decl_after_decl.carbon + +library "fail_extern_decl_after_decl" api; + +class C; +// CHECK:STDERR: fail_extern_decl_after_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclaration of `class C` is redundant. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_decl_after_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: class C; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: +extern class C; + +// --- fail_todo_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 + +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 + +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 + +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: 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: ^~~~~~ +// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +import library "def"; + +// --- fail_todo_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 + +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 + +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 + +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 + +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 +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_decl_copy.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- def.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 [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// 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: --- fail_decl_fn_in_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %.loc12: = fn_decl @.1 [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_def.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 [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// 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: --- fail_extern_decl_after_extern_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_decl_after_extern_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_member_class.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D; +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_decl_after_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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: %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 [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.1; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.2; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_import_decl_then_extern_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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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: %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 [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.1; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.2; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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: %C.decl.1: invalid = class_decl @C.1 [template = constants.%C.1] {} +// CHECK:STDOUT: %import_ref.3 = import_ref ir3, inst+3, unloaded +// CHECK:STDOUT: %C.decl.2: invalid = class_decl @C.2 [template = constants.%C.2] {} +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_ownership_conflict.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: %C.3: type = class_type @C.3 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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: %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: %import_ref.3: type = import_ref ir4, inst+2, loaded [template = constants.%C.3] +// CHECK:STDOUT: %C.decl.3: invalid = class_decl @C.3 [template = constants.%C.3] {} +// CHECK:STDOUT: %import_ref.4 = import_ref ir4, inst+3, unloaded +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.1; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.4 +// CHECK:STDOUT: } +// 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: +// 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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: %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 [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.1; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C.2; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+2, loaded [template = constants.%C] +// CHECK:STDOUT: %Core: = 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: } +// 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: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: type = import_ref ir2, inst+2, loaded [template = constants.%C] +// CHECK:STDOUT: %Core: = 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: } +// 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: +// 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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] +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// 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: +// 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// 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] +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1; +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index 40159af8b7022..1c9262245db06 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -74,7 +74,7 @@ abstract protected class WrongOrder; // CHECK:STDERR: abstract base class AbstractAndBase {} -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+3]]:1: ERROR: `extern` not allowed on `class` declaration. +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+3]]:1: ERROR: `extern` not allowed on `class` declaration that provides a definition. // CHECK:STDERR: extern class ExternDefined {} // CHECK:STDERR: ^~~~~~ extern class ExternDefined {} diff --git a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon b/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon index 18d2962e7a37e..0dd1366ebd755 100644 --- a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon +++ b/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon @@ -4,123 +4,104 @@ // // AUTOUPDATE +// --- fail_add_base.carbon + +library "fail_add_base" api; + class A; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_add_base.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: base class A {} // CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_add_base.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: class A; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: base class A {} +// --- fail_add_abstract.carbon + +library "fail_add_abstract" api; + class B; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_add_abstract.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: abstract class B {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_add_abstract.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: class B; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: abstract class B {} +// --- fail_remove_base.carbon + +library "fail_remove_base" api; + base class C; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_remove_base.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: class C {} // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_remove_base.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: base class C; // CHECK:STDERR: ^~~~~~~~~~~~~ // CHECK:STDERR: class C {} +// --- fail_base_to_abstract.carbon + +library "fail_base_to_abstract" api; + base class D; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: abstract class D {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: base class D; // CHECK:STDERR: ^~~~~~~~~~~~~ // CHECK:STDERR: abstract class D {} +// --- fail_remove_abstract.carbon + +library "fail_remove_abstract" api; + abstract class E; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: class E {} // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: abstract class E; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: class E {} +// --- fail_abstract_to_base.carbon + +library "fail_abstract_to_base" api; + abstract class F; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. +// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind. // CHECK:STDERR: base class F {} // CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: abstract class F; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: base class F {} -class G {} -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+7]]:1: ERROR: Class redeclared with different inheritance kind. -// CHECK:STDERR: abstract class G; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here. -// CHECK:STDERR: class G {} -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: -abstract class G; -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind. -// CHECK:STDERR: base class G; -// CHECK:STDERR: ^~~~~~~~~~~~~ -// CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-12]]:1: Previously declared here. -// CHECK:STDERR: class G {} -// CHECK:STDERR: ^~~~~~~~~ -base class G; - -// CHECK:STDOUT: --- fail_redeclaration_introducer.carbon +// CHECK:STDOUT: --- fail_add_base.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %B: type = class_type @B [template] -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %D: type = class_type @D [template] -// CHECK:STDOUT: %E: type = class_type @E [template] -// CHECK:STDOUT: %F: type = class_type @F [template] -// CHECK:STDOUT: %G: type = class_type @G [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .A = %A.decl.loc7 -// CHECK:STDOUT: .B = %B.decl.loc17 -// CHECK:STDOUT: .C = %C.decl.loc27 -// CHECK:STDOUT: .D = %D.decl.loc37 -// CHECK:STDOUT: .E = %E.decl.loc47 -// CHECK:STDOUT: .F = %F.decl.loc57 -// CHECK:STDOUT: .G = %G.decl.loc67 +// CHECK:STDOUT: .A = %A.decl.loc4 // CHECK:STDOUT: } // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %A.decl.loc7: type = class_decl @A [template = constants.%A] {} -// CHECK:STDOUT: %A.decl.loc15: type = class_decl @A [template = constants.%A] {} -// CHECK:STDOUT: %B.decl.loc17: type = class_decl @B [template = constants.%B] {} -// CHECK:STDOUT: %B.decl.loc25: type = class_decl @B [template = constants.%B] {} -// CHECK:STDOUT: %C.decl.loc27: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %C.decl.loc35: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %D.decl.loc37: type = class_decl @D [template = constants.%D] {} -// CHECK:STDOUT: %D.decl.loc45: type = class_decl @D [template = constants.%D] {} -// CHECK:STDOUT: %E.decl.loc47: type = class_decl @E [template = constants.%E] {} -// CHECK:STDOUT: %E.decl.loc55: type = class_decl @E [template = constants.%E] {} -// CHECK:STDOUT: %F.decl.loc57: type = class_decl @F [template = constants.%F] {} -// CHECK:STDOUT: %F.decl.loc65: type = class_decl @F [template = constants.%F] {} -// CHECK:STDOUT: %G.decl.loc67: type = class_decl @G [template = constants.%G] {} -// CHECK:STDOUT: %G.decl.loc75: type = class_decl @G [template = constants.%G] {} -// CHECK:STDOUT: %G.decl.loc82: type = class_decl @G [template = constants.%G] {} +// CHECK:STDOUT: %A.decl.loc4: type = class_decl @A [template = constants.%A] {} +// CHECK:STDOUT: %A.decl.loc12: type = class_decl @A [template = constants.%A] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @A { @@ -128,33 +109,113 @@ base class G; // CHECK:STDOUT: .Self = constants.%A // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_add_abstract.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %B: type = class_type @B [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .B = %B.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %B.decl.loc4: type = class_decl @B [template = constants.%B] {} +// CHECK:STDOUT: %B.decl.loc12: type = class_decl @B [template = constants.%B] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: class @B { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_remove_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 [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = 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: } +// CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_base_to_abstract.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .D = %D.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %D.decl.loc4: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: %D.decl.loc12: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: class @D { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_remove_abstract.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %E: type = class_type @E [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .E = %E.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %E.decl.loc4: type = class_decl @E [template = constants.%E] {} +// CHECK:STDOUT: %E.decl.loc12: type = class_decl @E [template = constants.%E] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: class @E { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%E // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @F { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%F +// CHECK:STDOUT: --- fail_abstract_to_base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = class_type @F [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @G { +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .F = %F.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %F.decl.loc4: type = class_decl @F [template = constants.%F] {} +// CHECK:STDOUT: %F.decl.loc11: type = class_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @F { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%G +// CHECK:STDOUT: .Self = constants.%F // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_redefinition.carbon b/toolchain/check/testdata/class/fail_redefinition.carbon index 3b13c7fa7184a..85bf47e0d9557 100644 --- a/toolchain/check/testdata/class/fail_redefinition.carbon +++ b/toolchain/check/testdata/class/fail_redefinition.carbon @@ -10,40 +10,30 @@ class Class { fn I() {} } -// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:1: ERROR: Redefinition of class Class. +// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:1: ERROR: Redefinition of `class Class`. // CHECK:STDERR: class Class { // CHECK:STDERR: ^~~~~~~~~~~~~ -// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-9]]:1: Previous definition was here. +// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-9]]:1: Previously defined here. // CHECK:STDERR: class Class { // CHECK:STDERR: ^~~~~~~~~~~~~ // CHECK:STDERR: class Class { fn G(); - // CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:3: ERROR: Redeclaration of `fn H` is redundant. - // CHECK:STDERR: fn H(); - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: fail_redefinition.carbon:[[@LINE-16]]:3: Previously declared here. - // CHECK:STDERR: fn H(); - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: fn H(); - // CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:3: ERROR: Redefinition of `fn I`. - // CHECK:STDERR: fn I() {} - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: fail_redefinition.carbon:[[@LINE-23]]:3: Previously defined here. - // CHECK:STDERR: fn I() {} - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: fn I() {} } +// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+4]]:10: ERROR: Out-of-line declaration requires a declaration in scoped entity. +// CHECK:STDERR: fn Class.F() {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fn Class.F() {} fn Class.G() {} fn Class.H() {} // CHECK:STDERR: fail_redefinition.carbon:[[@LINE+6]]:1: ERROR: Redefinition of `fn I`. // CHECK:STDERR: fn Class.I() {} // CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-9]]:3: Previously defined here. +// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-13]]:3: Previously defined here. // CHECK:STDERR: fn I() {} // CHECK:STDERR: ^~~~~~~~ fn Class.I() {} @@ -63,47 +53,53 @@ fn Class.I() {} // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Class.decl.loc7: type = class_decl @Class [template = constants.%Class] {} // CHECK:STDOUT: %Class.decl.loc20: type = class_decl @Class [template = constants.%Class] {} -// CHECK:STDOUT: %F: = fn_decl @F [template] {} +// CHECK:STDOUT: %F: = fn_decl @F.2 [template] {} // CHECK:STDOUT: %G: = fn_decl @G [template] {} -// CHECK:STDOUT: %H: = fn_decl @H [template] {} -// CHECK:STDOUT: %I: = fn_decl @I [template] {} +// CHECK:STDOUT: %H: = fn_decl @H.2 [template] {} +// CHECK:STDOUT: %I: = fn_decl @I.2 [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Class { // CHECK:STDOUT: %G: = fn_decl @G [template] {} -// CHECK:STDOUT: %H: = fn_decl @H [template] {} -// CHECK:STDOUT: %I: = fn_decl @I [template] {} +// CHECK:STDOUT: %H: = fn_decl @H.2 [template] {} +// CHECK:STDOUT: %I: = fn_decl @I.2 [template] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class -// CHECK:STDOUT: .F = -// CHECK:STDOUT: .H = -// CHECK:STDOUT: .I = // CHECK:STDOUT: .G = %G +// CHECK:STDOUT: .H = %H +// CHECK:STDOUT: .I = %I +// CHECK:STDOUT: .F = file.%F // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: fn @F.1(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @H.1(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @I.1() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @H() { +// CHECK:STDOUT: fn @G() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @I() { +// CHECK:STDOUT: fn @H.2() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: !.loc37: +// CHECK:STDOUT: fn @I.2() { +// CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: -// CHECK:STDOUT: !.loc49: +// CHECK:STDOUT: !.loc39: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: fn @F.2() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 976cc1bf28267..ff4d22e39cf8a 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -191,10 +191,8 @@ CARBON_DIAGNOSTIC_KIND(AdaptFieldHere) CARBON_DIAGNOSTIC_KIND(BaseIsFinal) CARBON_DIAGNOSTIC_KIND(BaseMissingExtend) CARBON_DIAGNOSTIC_KIND(ClassForwardDeclaredHere) -CARBON_DIAGNOSTIC_KIND(ClassPreviousDefinition) CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducer) CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducerPrevious) -CARBON_DIAGNOSTIC_KIND(ClassRedefinition) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclOutsideClass) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclPrevious) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclRepeated)