Add namespace-scoped private keyword support. (#4026)

Adds access to the name lookup table in name scopes. This is so that we
can quickly check access during name lookup without resolving the entity
itself. Does this for names in general, but does not implement handling
for entity-scoped names, only namespace-scoped names (where they're
essentially just not exported).

Excludes `private` names from exports. Although names should be
accessible to `impl` files, that's not implemented here because we'll
probably want to do it by directly copying name lookup tables.
This commit is contained in:
Jon Ross-Perkins
2024-06-06 00:19:56 +00:00
committed by GitHub
parent d1862e829b
commit 807a3f1370
33 changed files with 2022 additions and 335 deletions
@@ -34,10 +34,6 @@ default protected fn WrongOrder();
// CHECK:STDERR:
virtual virtual fn DuplicateVirtual() {}
// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: ERROR: Semantics TODO: `access modifier`.
// CHECK:STDERR: private protected fn TwoAccess();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: ERROR: `protected` not allowed on declaration with `private`.
// CHECK:STDERR: private protected fn TwoAccess();
// CHECK:STDERR: ^~~~~~~~~
@@ -122,7 +118,7 @@ extern private fn ExternOrderAndConflict() {}
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .WrongOrder = %WrongOrder.decl
// CHECK:STDOUT: .DuplicateVirtual = %DuplicateVirtual.decl
// CHECK:STDOUT: .TwoAccess = %TwoAccess.decl
// CHECK:STDOUT: .TwoAccess [private] = %TwoAccess.decl
// CHECK:STDOUT: .ModifiersConflict = %ModifiersConflict.decl
// CHECK:STDOUT: .InvalidModifier = %InvalidModifier.decl
// CHECK:STDOUT: .ModifiersConflict2 = %ModifiersConflict2.decl
@@ -1,32 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon
// CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`.
// CHECK:STDERR: private fn F();
// CHECK:STDERR: ^~~~~~~
private fn F();
// CHECK:STDOUT: --- fail_todo_modifiers.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: F = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
@@ -0,0 +1,479 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/import_access.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/import_access.carbon
// ============================================================================
// Setup files
// ============================================================================
// --- def.carbon
package Test library "def";
private fn Def() {}
// --- forward_with_def.carbon
package Test library "forward_with_def";
private fn ForwardWithDef();
fn ForwardWithDef() {}
// --- forward.carbon
package Test library "forward";
private fn Forward();
// ============================================================================
// Test files
// ============================================================================
// --- fail_todo_def.impl.carbon
impl package Test library "def";
// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found.
// CHECK:STDERR: var f: () = Def();
// CHECK:STDERR: ^~~
// CHECK:STDERR:
var f: () = Def();
// --- fail_local_def.carbon
package Test library "fail_local_def";
import library "def";
// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found.
// CHECK:STDERR: var f: () = Def();
// CHECK:STDERR: ^~~
// CHECK:STDERR:
var f: () = Def();
// --- fail_other_def.carbon
package Other library "fail_other_def";
import Test library "def";
// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found.
// CHECK:STDERR: var f: () = Test.Def();
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
var f: () = Test.Def();
// --- fail_todo_forward_with_def.impl.carbon
impl package Test library "forward_with_def";
// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found.
// CHECK:STDERR: var f: () = ForwardWithDef();
// CHECK:STDERR: ^~~~~~~~~~~~~~
// CHECK:STDERR:
var f: () = ForwardWithDef();
// --- fail_local_forward_with_def.carbon
package Test library "fail_local_forward_with_def";
import library "forward_with_def";
// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found.
// CHECK:STDERR: var f: () = ForwardWithDef();
// CHECK:STDERR: ^~~~~~~~~~~~~~
// CHECK:STDERR:
var f: () = ForwardWithDef();
// --- fail_other_forward_with_def.carbon
package Other library "fail_other_forward_with_def";
import Test library "forward_with_def";
// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found.
// CHECK:STDERR: var f: () = Test.ForwardWithDef();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var f: () = Test.ForwardWithDef();
// --- fail_todo_forward.impl.carbon
impl package Test library "forward";
// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Forward` not found.
// CHECK:STDERR: var f: () = Forward();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
var f: () = Forward();
fn Forward() {}
// --- fail_local_forward.carbon
package Test library "fail_local_forward";
import library "forward";
// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:13: ERROR: Name `Forward` not found.
// CHECK:STDERR: var f: () = Forward();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
var f: () = Forward();
// --- fail_other_forward.carbon
package Other library "fail_other_forward";
import Test library "forward";
// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+3]]:13: ERROR: Name `Forward` not found.
// CHECK:STDERR: var f: () = Test.Forward();
// CHECK:STDERR: ^~~~~~~~~~~~
var f: () = Test.Forward();
// --- todo_fail_private_on_redecl.carbon
library "fail_private_on_redecl";
private fn Redecl();
private fn Redecl() {}
// CHECK:STDOUT: --- def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Def: type = fn_type @Def [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: Def = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Def [private] = %Def.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Def.decl: Def = fn_decl @Def [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Def() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- forward_with_def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %ForwardWithDef: type = fn_type @ForwardWithDef [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: ForwardWithDef = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .ForwardWithDef [private] = %ForwardWithDef.decl.loc4
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %ForwardWithDef.decl.loc4: ForwardWithDef = fn_decl @ForwardWithDef [template = constants.%struct] {}
// CHECK:STDOUT: %ForwardWithDef.decl.loc6: ForwardWithDef = fn_decl @ForwardWithDef [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ForwardWithDef() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- forward.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Forward: type = fn_type @Forward [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: Forward = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Forward [private] = %Forward.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Forward.decl: Forward = fn_decl @Forward [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Forward();
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_def.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Def.ref: <error> = name_ref Def, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_local_def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Def.ref: <error> = name_ref Def, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_other_def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Test = %Test
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Test: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Test.ref: <namespace> = name_ref Test, file.%Test [template = file.%Test]
// CHECK:STDOUT: %Def.ref: <error> = name_ref Def, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_local_forward_with_def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_other_forward_with_def.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Test = %Test
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Test: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Test.ref: <namespace> = name_ref Test, file.%Test [template = file.%Test]
// CHECK:STDOUT: %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_forward.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %Forward: type = fn_type @Forward [template]
// CHECK:STDOUT: %struct: Forward = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: .Forward = %Forward.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: %Forward.decl: Forward = fn_decl @Forward [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Forward() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Forward.ref: <error> = name_ref Forward, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_local_forward.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Forward.ref: <error> = name_ref Forward, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_other_forward.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Test = %Test
// CHECK:STDOUT: .f = %f
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Test: <namespace> = namespace [template] {}
// CHECK:STDOUT: %.loc9_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_9.2: type = converted %.loc9_9.1, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %f.var: ref () = var f
// CHECK:STDOUT: %f: ref () = bind_name f, %f.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Test.ref: <namespace> = name_ref Test, file.%Test [template = file.%Test]
// CHECK:STDOUT: %Forward.ref: <error> = name_ref Forward, <error> [template = <error>]
// CHECK:STDOUT: assign file.%f.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Redecl: type = fn_type @Redecl [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %struct: Redecl = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = %Core
// CHECK:STDOUT: .Redecl [private] = %Redecl.decl.loc4
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
// CHECK:STDOUT: %Redecl.decl.loc4: Redecl = fn_decl @Redecl [template = constants.%struct] {}
// CHECK:STDOUT: %Redecl.decl.loc6: Redecl = fn_decl @Redecl [template = constants.%struct] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Redecl() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: