mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 06:54:44 +01:00
Expand handling of function redeclarations. (#3739)
This detects more cases of incorrect matches between declaration and definition. It also factors the logic out to a separate file for easier sharing, particularly when it comes to merging imports (I'm not sure if this exact API will be reshared, but the core logic should apply).
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
fn A();
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE+6]]:1: ERROR: Redundant redeclaration of function A.
|
||||
// CHECK:STDERR: fn A();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: Previously declared here.
|
||||
// CHECK:STDERR: fn A();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
fn A();
|
||||
|
||||
fn B(x: i32);
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE+6]]:1: ERROR: Redundant redeclaration of function B.
|
||||
// CHECK:STDERR: fn B(x: i32);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: Previously declared here.
|
||||
// CHECK:STDERR: fn B(x: i32);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
fn B(x: i32);
|
||||
|
||||
fn C();
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because of parameter count of 1.
|
||||
// CHECK:STDERR: fn C(x: i32);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: Previously declared with parameter count of 0.
|
||||
// CHECK:STDERR: fn C();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
fn C(x: i32);
|
||||
|
||||
fn D() {}
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE+6]]:1: ERROR: Redundant redeclaration of function D.
|
||||
// CHECK:STDERR: fn D();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: Previously declared here.
|
||||
// CHECK:STDERR: fn D() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
fn D();
|
||||
|
||||
fn E() {}
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE+6]]:1: ERROR: Redefinition of function E.
|
||||
// CHECK:STDERR: fn E() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: Previously defined here.
|
||||
// CHECK:STDERR: fn E() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
fn E() {}
|
||||
|
||||
// CHECK:STDOUT: --- fail_redecl.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .A = %A.loc7
|
||||
// CHECK:STDOUT: .B = %B.loc16
|
||||
// CHECK:STDOUT: .C = %C
|
||||
// CHECK:STDOUT: .D = %D.loc34
|
||||
// CHECK:STDOUT: .E = %E.loc43
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %A.loc7: <function> = fn_decl @A [template] {}
|
||||
// CHECK:STDOUT: %A.loc14: <function> = fn_decl @A [template] {}
|
||||
// CHECK:STDOUT: %B.loc16: <function> = fn_decl @B [template] {
|
||||
// CHECK:STDOUT: %x.loc16_6.1: i32 = param x
|
||||
// CHECK:STDOUT: @B.%x: i32 = bind_name x, %x.loc16_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %B.loc23: <function> = fn_decl @B [template] {
|
||||
// CHECK:STDOUT: %x.loc23_6.1: i32 = param x
|
||||
// CHECK:STDOUT: %x.loc23_6.2: i32 = bind_name x, %x.loc23_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %C: <function> = fn_decl @C [template] {}
|
||||
// CHECK:STDOUT: %.loc32: <function> = fn_decl @.1 [template] {
|
||||
// CHECK:STDOUT: %x.loc32_6.1: i32 = param x
|
||||
// CHECK:STDOUT: @.1.%x: i32 = bind_name x, %x.loc32_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %D.loc34: <function> = fn_decl @D [template] {}
|
||||
// CHECK:STDOUT: %D.loc41: <function> = fn_decl @D [template] {}
|
||||
// CHECK:STDOUT: %E.loc43: <function> = fn_decl @E [template] {}
|
||||
// CHECK:STDOUT: %E.loc50: <function> = fn_decl @E [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @A();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @B(%x: i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @C();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.1(%x: i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @D() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !.loc50:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
// 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
|
||||
|
||||
fn F();
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because of parameter count of 1.
|
||||
// CHECK:STDERR: fn F(x: i32) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: Previously declared with parameter count of 0.
|
||||
// CHECK:STDERR: fn F();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
fn F(x: i32) {}
|
||||
|
||||
fn G(x: i32);
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because of parameter count of 0.
|
||||
// CHECK:STDERR: fn G() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: Previously declared with parameter count of 1.
|
||||
// CHECK:STDERR: fn G(x: i32);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
fn G() {}
|
||||
|
||||
fn H(x: i32);
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:6: ERROR: Function redeclaration differs at parameter 1.
|
||||
// CHECK:STDERR: fn H(x: bool) {}
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:6: Previous declaration's corresponding parameter here.
|
||||
// CHECK:STDERR: fn H(x: i32);
|
||||
// CHECK:STDERR: ^
|
||||
fn H(x: bool) {}
|
||||
|
||||
fn I();
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because return type is `i32`.
|
||||
// CHECK:STDERR: fn I() -> i32 { return 0; }
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: Previously declared with no return type.
|
||||
// CHECK:STDERR: fn I();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
fn I() -> i32 { return 0; }
|
||||
|
||||
fn J() -> i32;
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because no return type is provided.
|
||||
// CHECK:STDERR: fn J() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: Previously declared with return type `i32`.
|
||||
// CHECK:STDERR: fn J() -> i32;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
fn J() {}
|
||||
|
||||
fn K() -> i32;
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+6]]:1: ERROR: Function redeclaration differs because return type is `bool`.
|
||||
// CHECK:STDERR: fn K() -> bool { return false; }
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: Previously declared with return type `i32`.
|
||||
// CHECK:STDERR: fn K() -> i32;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
fn K() -> bool { return false; }
|
||||
|
||||
// CHECK:STDOUT: --- fail_decl_param_mismatch.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: i32 = int_literal 0 [template]
|
||||
// CHECK:STDOUT: %.2: bool = bool_literal false [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: .G = %G
|
||||
// CHECK:STDOUT: .H = %H
|
||||
// CHECK:STDOUT: .I = %I
|
||||
// CHECK:STDOUT: .J = %J
|
||||
// CHECK:STDOUT: .K = %K
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {}
|
||||
// CHECK:STDOUT: %.loc14: <function> = fn_decl @.1 [template] {
|
||||
// CHECK:STDOUT: %x.loc14_6.1: i32 = param x
|
||||
// CHECK:STDOUT: @.1.%x: i32 = bind_name x, %x.loc14_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %G: <function> = fn_decl @G [template] {
|
||||
// CHECK:STDOUT: %x.loc16_6.1: i32 = param x
|
||||
// CHECK:STDOUT: @G.%x: i32 = bind_name x, %x.loc16_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc23: <function> = fn_decl @.2 [template] {}
|
||||
// CHECK:STDOUT: %H: <function> = fn_decl @H [template] {
|
||||
// CHECK:STDOUT: %x.loc25_6.1: i32 = param x
|
||||
// CHECK:STDOUT: @H.%x: i32 = bind_name x, %x.loc25_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc32: <function> = fn_decl @.3 [template] {
|
||||
// CHECK:STDOUT: %x.loc32_6.1: bool = param x
|
||||
// CHECK:STDOUT: @.3.%x: bool = bind_name x, %x.loc32_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %I: <function> = fn_decl @I [template] {}
|
||||
// CHECK:STDOUT: %.loc41: <function> = fn_decl @.4 [template] {
|
||||
// CHECK:STDOUT: %return.var.loc41: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %J: <function> = fn_decl @J [template] {
|
||||
// CHECK:STDOUT: %return.var.loc43: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc50: <function> = fn_decl @.5 [template] {}
|
||||
// CHECK:STDOUT: %K: <function> = fn_decl @K [template] {
|
||||
// CHECK:STDOUT: %return.var.loc52: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc59: <function> = fn_decl @.6 [template] {
|
||||
// CHECK:STDOUT: %return.var.loc59: ref bool = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.1(%x: i32) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @G(%x: i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.2() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @H(%x: i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.3(%x: bool) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @I();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.4() -> i32 {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc41: i32 = int_literal 0 [template = constants.%.1]
|
||||
// CHECK:STDOUT: return %.loc41
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @J() -> i32;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.5() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @K() -> i32;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @.6() -> bool {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc59: bool = bool_literal false [template = constants.%.2]
|
||||
// CHECK:STDOUT: return %.loc59
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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
|
||||
|
||||
fn F() {}
|
||||
// CHECK:STDERR: fail_redef.carbon:[[@LINE+6]]:1: ERROR: Redefinition of function F.
|
||||
// CHECK:STDERR: fn F() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_redef.carbon:[[@LINE-4]]:1: Previously defined here.
|
||||
// CHECK:STDERR: fn F() {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
fn F() {}
|
||||
|
||||
// CHECK:STDOUT: --- fail_redef.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .F = %F.loc7
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %F.loc7: <function> = fn_decl @F [template] {}
|
||||
// CHECK:STDOUT: %F.loc14: <function> = fn_decl @F [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !.loc14:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
Reference in New Issue
Block a user