aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/decl.zc9
-rw-r--r--tests/conformance/known.txt1
-rw-r--r--tests/langerrors/proto_after_def_mismatch.zc4
3 files changed, 9 insertions, 5 deletions
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); }