diff options
| author | 2025-09-12 17:10:35 +0200 | |
|---|---|---|
| committer | 2025-09-12 17:10:35 +0200 | |
| commit | 89710916cfa82f50be0092347744a5e06a3b5420 (patch) | |
| tree | 02cff596fad2f6b4ea577ad35bc77d53dcb4a413 | |
| parent | c8af181799015ea39b8868ef5d07b10ed255e799 (diff) | |
c: function-local static vars
| -rw-r--r-- | c.c | 49 | ||||
| -rw-r--r-- | ir.c | 2 | ||||
| -rw-r--r-- | lex.c | 2 | ||||
| -rw-r--r-- | test/pp.c | 5 | ||||
| -rw-r--r-- | test/pp.h | 3 | ||||
| -rw-r--r-- | test/reloc.c | 7 | ||||
| -rw-r--r-- | test/test3.c | 2 |
7 files changed, 54 insertions, 16 deletions
@@ -965,7 +965,7 @@ Postfix: span.ex = tk.span.ex; ty = condtype(&tmp, &rhs); if (!ty.t) { - error(&span, "bad operands to conditional expression (%ty, %ty)", tmp.ty, rhs.ty); + error(&span, "incompatible types in conditional expression (%ty, %ty)", tmp.ty, rhs.ty); ty = tmp.ty; } sub = alloc(&cm->exarena, 3 * sizeof*sub, 0); @@ -2109,7 +2109,6 @@ declarator(struct declstate *st, struct comp *cm) { else if (decl.ty.t == TYFUNC) error(&l->span, "array has element has function type (%ty)", decl.ty); decl.ty = mkarrtype(decl.ty, decl.qual, l->len); - decl.qual = 0; break; case TYFUNC: if (decl.ty.t == TYFUNC) @@ -2211,6 +2210,7 @@ pdecl(struct declstate *st, struct comp *cm) { } declspec(st, cm); } + if (st->scls == SCTYPEDEF) iniallowed = 0; if (first && st->tagdecl && match(cm, &tk, ';')) { decl = (struct decl) { st->base, st->scls, st->qual, st->align, 0, tk.span }; @@ -2272,6 +2272,18 @@ structreturn(struct function *fn, const struct expr *src) static union ref compilecall(struct function *fn, const struct expr *ex); +static const char * +mkhiddensym(const char *fnname, const char *name, int id) +{ + char buf[200]; + struct wbuf wbuf = MEMBUF(buf, sizeof buf); + assert(id > 0); + bfmt(&wbuf, "%s.%s.%d", fnname, name, id); + ioputc(&wbuf, 0); + assert(!wbuf.err); + return intern(buf); +} + static union ref expraddr(struct function *fn, const struct expr *ex) { @@ -2289,8 +2301,10 @@ expraddr(struct function *fn, const struct expr *ex) case SCEXTERN: case SCNONE: return mksymref(decl->name); case SCSTATIC: - assert(!"nyi"); - break; + if (!decl->id) + return mksymref(decl->name); + else + return mksymref(mkhiddensym(fn->name, decl->name, decl->id)); default: assert(0); } @@ -3262,22 +3276,32 @@ localdecl(struct comp *cm, struct function *fn, bool forini) Initz: if (st.varini) { struct decl *d = putdecl(cm, &decl); + bool statik = st.scls & (SCSTATIC | SCEXTERN); + const char *name = decl.name; put = 1; - ini = initializer(cm, &d->ty, EVFOLD, 0, decl.qual, decl.name); + if (decl.scls == SCSTATIC) + name = mkhiddensym(fn->name, name, decl.id); + ini = initializer(cm, &d->ty, statik ? EVSTATICINI : EVFOLD, + /* globl? */ decl.scls == SCEXTERN, decl.qual, name); pdecl(&st, cm); - if (!assigncheck(decl.ty, &ini)) { - struct span span = decl.span; - joinspan(&span.ex, ini.span.ex); - error(&span, "cannot initialize '%ty' variable with '%ty'", - decl.ty, ini.ty); - } - if (decl.scls & (SCAUTO | SCREGISTER)) { + if (!statik) { + if (!assigncheck(decl.ty, &ini)) { + struct span span = decl.span; + joinspan(&span.ex, ini.span.ex); + error(&span, "cannot initialize '%ty' variable with '%ty'", + decl.ty, ini.ty); + } EMITS { if (isagg(decl.ty)) structcopy(fn, decl.ty, mkref(RTMP, decl.id), expraddr(fn, &ini)); else genstore(fn, decl.ty, mkref(RTMP, decl.id), exprvalue(fn, &ini)); } + } else if (decl.scls == SCEXTERN) { + struct span span = decl.span; + joinspan(&span.ex, ini.span.ex); + error(&span, + "declaration of block local with extern linkage cannot have an initializer"); } } else if (decl.scls == SCSTATIC) { assert(0); @@ -3290,6 +3314,7 @@ localdecl(struct comp *cm, struct function *fn, bool forini) case SCEXTERN: if (forini) error(&decl.span, "extern declaration in 'for' loop initializer"); + if (st.varini) goto Initz; break; default: assert(0); } @@ -242,6 +242,8 @@ newblk(struct function *fn) void freeblk(struct function *fn, struct block *blk) { + if (blk->npred > 1) + xbfree(blk->_pred); vfree(&blk->phi); vfree(&blk->ins); if (blk->lnext) blk->lnext->lprev = blk->lprev; @@ -1241,7 +1241,7 @@ tryexpand(struct lexer *lx, struct token *tk) } joinspan(&span.ex, tk.span.ex); if (narg < mac->nparam) - error(&span, "not enough arguments in function-like macro invocation"); + error(&excessspan, "macro `%s' passed %d arguments, but takes %d", mac->name, narg, mac->nparam); else if (toomany) { joinspan(&excessspan.ex, tk.span.ex); error(&excessspan, "macro `%s' passed %d arguments, but takes just %d", mac->name, narg, mac->nparam); @@ -5,7 +5,8 @@ int main(void) { - printf("%s\n",STR ( ok /1 "\n"\n ;.& - 05.5)); + printf("%s %s\n",STR ( ok /1 "\n"n ;.& + 05.5), STR(ADD(1,2))); hi(ADD(Foo, SQR(Bar+1))); + printf("%s %s\n", str(Foo), xstr(Foo)); } @@ -16,6 +16,9 @@ void hi(int x) { #define ADD(a,b) (a)+(b) #define STR(h) #h +#define xstr(s1) str(s1) +#define str(s) #s + #endif extern int printf(const char *, ...); diff --git a/test/reloc.c b/test/reloc.c new file mode 100644 index 0000000..70cba28 --- /dev/null +++ b/test/reloc.c @@ -0,0 +1,7 @@ + + +float get_value(unsigned x) +{ + static const float values [] = {1.1f, 1.2f, 1.3f, 1.4f}; + return x < 4 ? values[x] : 0.0f; +} diff --git a/test/test3.c b/test/test3.c index a5d165f..b99a543 100644 --- a/test/test3.c +++ b/test/test3.c @@ -27,7 +27,7 @@ struct bitset { unsigned long long u; }; void bscopy(struct bitset dst[/*siz*/], const struct bitset src[/*siz*/], unsigned siz) { - while (siz--) dst++->u = src++->u; + for (; siz; --siz, ++dst, ++src) dst->u = src->u; } |