diff options
Diffstat (limited to 'src/compiler/decl.zc')
| -rw-r--r-- | src/compiler/decl.zc | 26 |
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 |
