aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/decl.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/decl.zc')
-rw-r--r--src/compiler/decl.zc26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc
index 3a02b90..87281ad 100644
--- a/src/compiler/decl.zc
+++ b/src/compiler/decl.zc
@@ -282,12 +282,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, amb = 0, nonm = 0;
o3nxt = 0;
if (rty || ntp) typed = 1;
if (!dnm) dnm = n;
s = lookup(n);
- if (s < 0 || s < ubase || skind[s] != K_FN || (sflag[s] & F_DEF)) {
+ 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);
+ redef = rt.eq_w(sname[s], qn);
+ }
+ if (!redef && (s < 0 || s < ubase || skind[s] != K_FN || (sflag[s] & F_DEF))) {
s = addsym(n, K_FN, 0);
sflag[s] = 0;
}
@@ -322,7 +327,9 @@ int fndef(int chk, int rty, int ret, int n) {
} else if (tv == s_d) t = 2; else die("a parameter tag is .m or .d");
next();
}
- pnoffs[np] = toff; pnplaces[np] = tpack(); rs_note(RS_PARAM, toff); pn[np] = name();
+ pnoffs[np] = toff; pnplaces[np] = tpack(); rs_note(RS_PARAM, toff);
+ if (!pk && !t && tk == T_ID && istypename(tv)) amb = amb | (1 << np); // int f(int): a name, or a type if this is a prototype
+ if (pk && tk == T_OP && (tv == s_comma || tv == s_rp)) { pn[np] = 0; nonm = 1; } else pn[np] = name(); // int f(int*, int): a prototype's parameters may be unnamed
if (o3f && pty[np] == tword) serr("o3 parameters need a type");
if (np >= 12 && t) die("only the first 12 parameters can be tagged");
pt[np] = t;
@@ -333,6 +340,13 @@ int fndef(int chk, int rty, int ret, int n) {
}
}
expect(s_rp);
+ if (is_op(s_semi)) { // a prototype: a lone type name is an unnamed parameter of that type (b.2.13)
+ i = 0;
+ while (i < np) {
+ if (((amb >> i) & 1) && pn[i]) { t = lookup(pn[i]); if (t >= 0 && skind[t] == K_TYPE) { pty[i] = sval[t]; typed = 1; } }
+ i++;
+ }
+ } else if (nonm) serr("a parameter needs a name");
sig = ret + np + np + tags * 64;
if ((sflag[s] & F_SIG) && !(sflag[s] & F_PRE)) {
if (ssig[s] != sig) serrn(n, "doesn't match its earlier declaration");
@@ -475,8 +489,12 @@ int gdecl2(int t, int tg, int n) {
if (arraytype[0] != TY_ARR || !is_op(s_lb)) serr("a global compound literal needs an array initializer");
else { array_literal(arraytype); vv = xcval; *(a + hdelta) = vv; if (!t) stype[s] = decay(xty); }
}
+ else if (t && isfl(t) && tk == T_FLT) { // float g = 1.5; (appendix b.2.7)
+ vv = tv; next(); if (t == tf32) vv = rt.zs2f(rt.zf2s(vv)); *(a + hdelta) = vv; // an f32 scalar is a rounded double
+ }
else {
- vv = cnorm(t, cexpr()); *(a + hdelta) = vv;
+ vv = cnorm(t, cexpr()); if (t && isfl(t)) { vv = vf_i2f(vv); if (t == tf32) vv = rt.zs2f(rt.zf2s(vv)); } // float g = 2; is 2.0
+ *(a + hdelta) = vv;
if (gok) { if (!gty) gty = tint; else if (gty != tint) gok = 0; }
}
} else if (gok) gok = 0; // no initializer: nothing says what it is