mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 13:21:05 +01:00
Adds ImportIRId::ApiForImpl to reserve a specific slot for the `api` import, so that the code can trivially determine whether an import is from the same library. This is then used for merging function declarations, because the rules for redeclarations in the same library slightly differ as compared to other imports (note they're also not identical to same-file rules). The main thing this leaves from the recent #3762 is verifying that entities forward declared in the `impl` file are also defined, but that's not in-scope for merging; it's moreso post-checking validation. Note, a lot of our `invalid <entity> ID` comments in ids.h were incorrectly copy-pasted, so I've cut `<entity>`.
233 lines
6.7 KiB
Plaintext
233 lines
6.7 KiB
Plaintext
// 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
|
|
|
|
// --- basic.carbon
|
|
|
|
library "basic" api;
|
|
|
|
fn A();
|
|
|
|
// --- basic.impl.carbon
|
|
|
|
library "basic" impl;
|
|
|
|
fn A() {}
|
|
|
|
// --- extern_api.carbon
|
|
|
|
library "extern_api" api;
|
|
|
|
extern fn A();
|
|
|
|
// --- fail_extern_api.impl.carbon
|
|
|
|
library "extern_api" impl;
|
|
|
|
// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations in the same library must match use of `extern`.
|
|
// CHECK:STDERR: fn A() {}
|
|
// CHECK:STDERR: ^~~~~~~~
|
|
// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE-5]]:1: In import.
|
|
// CHECK:STDERR: library "extern_api" impl;
|
|
// CHECK:STDERR: ^~~~~~~
|
|
// CHECK:STDERR: extern_api.carbon:4:1: Previously declared here.
|
|
// CHECK:STDERR: extern fn A();
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
fn A() {}
|
|
|
|
// --- extern_impl.carbon
|
|
|
|
library "extern_impl" api;
|
|
|
|
fn A();
|
|
|
|
// --- fail_extern_impl.impl.carbon
|
|
|
|
library "extern_impl" impl;
|
|
|
|
// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+4]]:1: ERROR: `extern` not allowed on `fn` declaration that provides a definition.
|
|
// CHECK:STDERR: extern fn A() {}
|
|
// CHECK:STDERR: ^~~~~~
|
|
// CHECK:STDERR:
|
|
extern fn A() {}
|
|
|
|
// --- redecl_after_def.carbon
|
|
|
|
library "redecl_after_def" api;
|
|
|
|
fn A() {}
|
|
|
|
// --- fail_redecl_after_def.impl.carbon
|
|
|
|
library "redecl_after_def" impl;
|
|
|
|
// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE+10]]:1: ERROR: Redundant redeclaration of function A.
|
|
// CHECK:STDERR: fn A();
|
|
// CHECK:STDERR: ^~~~~~~
|
|
// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE-5]]:1: In import.
|
|
// CHECK:STDERR: library "redecl_after_def" impl;
|
|
// CHECK:STDERR: ^~~~~~~
|
|
// CHECK:STDERR: redecl_after_def.carbon:4:1: Previously declared here.
|
|
// CHECK:STDERR: fn A() {}
|
|
// CHECK:STDERR: ^~~~~~~~
|
|
// CHECK:STDERR:
|
|
fn A();
|
|
|
|
// --- redef_after_def.carbon
|
|
|
|
library "redef_after_def" api;
|
|
|
|
fn A() {}
|
|
|
|
// --- fail_redef_after_def.impl.carbon
|
|
|
|
library "redef_after_def" impl;
|
|
|
|
// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE+9]]:1: ERROR: Redefinition of function A.
|
|
// CHECK:STDERR: fn A() {}
|
|
// CHECK:STDERR: ^~~~~~~~
|
|
// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE-5]]:1: In import.
|
|
// CHECK:STDERR: library "redef_after_def" impl;
|
|
// CHECK:STDERR: ^~~~~~~
|
|
// CHECK:STDERR: redef_after_def.carbon:4:1: Previously defined here.
|
|
// CHECK:STDERR: fn A() {}
|
|
// CHECK:STDERR: ^~~~~~~~
|
|
fn A() {}
|
|
|
|
// CHECK:STDOUT: --- basic.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A();
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- basic.impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, loaded [template = imports.%A]
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- extern_api.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: extern fn @A();
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_extern_api.impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, loaded [template = imports.%A]
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- extern_impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A();
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_extern_impl.impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, loaded [template = imports.%A]
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- redecl_after_def.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_redecl_after_def.impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, loaded [template = imports.%A]
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A();
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- redef_after_def.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: --- fail_redef_after_def.impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .A = %A
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: <function> = import_ref ir1, inst+1, loaded [template = imports.%A]
|
|
// CHECK:STDOUT: %A: <function> = fn_decl @A [template] {}
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|