From 19cdaa91b74da17a78809433ff7e6a2c084d8385 Mon Sep 17 00:00:00 2001 From: zinc Date: Wed, 14 Oct 2026 16:11:59 +0330 Subject: fndef: a prototype after a definition in the same module keeps the definition (appendix b.2.4) --- src/compiler/decl.zc | 9 +++++---- tests/conformance/known.txt | 1 - tests/langerrors/proto_after_def_mismatch.zc | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 tests/langerrors/proto_after_def_mismatch.zc diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc index 6794373..67aceb1 100644 --- a/src/compiler/decl.zc +++ b/src/compiler/decl.zc @@ -280,16 +280,17 @@ int body() { // into stype, checked against any earlier prototype or prescan result, and // where the o3 region for an o3 function is handed to the core) int fndef(int chk, int rty, int ret, int n) { - int s, np = 0, tags = 0, t, sig, i; char*[24] pn; word[24] pt; word[24] pty; int typed = 0, ft, explicit_rty = !!rty, o3f = o3nxt, lo, hi, pk, lt, lend, lfl = tline; + int s, np = 0, tags = 0, t, sig, i; char*[24] pn; word[24] pt; word[24] pty; int typed = 0, ft, explicit_rty = !!rty, o3f = o3nxt, lo, hi, pk, lt, lend, lfl = tline, redef; o3nxt = 0; if (rty || ntp) typed = 1; if (!dnm) dnm = n; s = lookup(n); - if (s >= ubase && skind[s] == K_FN && (sflag[s] & F_DEF) && !(sflag[s] & F_TPL) && !ginst && !ntp) { // appendix b.2.3: the same name in the same module + redef = 0; // a function this module already defined: a prototype after it keeps it (b.2.4), a second body is defined twice (b.2.3) + if (s >= ubase && skind[s] == K_FN && (sflag[s] & F_DEF) && !(sflag[s] & F_TPL) && !ginst && !ntp) { word qn = n; if (module_name) qn = module_symbol(n); - if (rt.eq_w(sname[s], qn)) serrn(n, "is defined twice"); + redef = rt.eq_w(sname[s], qn); } - if (s < 0 || s < ubase || skind[s] != K_FN || (sflag[s] & F_DEF)) { + if (!redef && (s < 0 || s < ubase || skind[s] != K_FN || (sflag[s] & F_DEF))) { s = addsym(n, K_FN, 0); sflag[s] = 0; } diff --git a/tests/conformance/known.txt b/tests/conformance/known.txt index ff67f6b..7b2082c 100644 --- a/tests/conformance/known.txt +++ b/tests/conformance/known.txt @@ -3,7 +3,6 @@ # appendix b.2.8 (a global named in an initializer is its address) is documented behavior per 5.3.2 and 3.14.2: no entry 4-statements/o3_outside_function_ordinary_block.zc zy c top-level o3 { } is rejected; spec 4.10.2 says it is an ordinary block 5-declarations/enum_member_names_earlier_b2.zc zy a appendix b.2.2 confirmed: enum members can't name earlier members -5-declarations/fn_prototype_after_definition_b4.zc zy a appendix b.2.4 confirmed: a prototype after the definition hides it 5-declarations/fn_prototype_unnamed_params_b13.zc zy a appendix b.2.13 confirmed (message now: doesn't match its earlier declaration) 5-declarations/global_float_init_b7.zc zy a appendix b.2.7 confirmed: float global initializer rejected 5-declarations/include_in_function_b9.zc zy a appendix b.2.9 confirmed: include in a body gives "return outside a function" diff --git a/tests/langerrors/proto_after_def_mismatch.zc b/tests/langerrors/proto_after_def_mismatch.zc new file mode 100644 index 0000000..94a04e6 --- /dev/null +++ b/tests/langerrors/proto_after_def_mismatch.zc @@ -0,0 +1,4 @@ +// expect: f: doesn't match its earlier declaration +int f(int a) { return a; } +int f(int a, int b); +fn main() { return f(1); } -- cgit v1.2.3