aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c.c49
-rw-r--r--ir.c2
-rw-r--r--lex.c2
-rw-r--r--test/pp.c5
-rw-r--r--test/pp.h3
-rw-r--r--test/reloc.c7
-rw-r--r--test/test3.c2
7 files changed, 54 insertions, 16 deletions
diff --git a/c.c b/c.c
index 16348c4..d4fb280 100644
--- a/c.c
+++ b/c.c
@@ -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);
}
diff --git a/ir.c b/ir.c
index 30239ed..4afd341 100644
--- a/ir.c
+++ b/ir.c
@@ -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;
diff --git a/lex.c b/lex.c
index 128233b..d17bef0 100644
--- a/lex.c
+++ b/lex.c
@@ -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);
diff --git a/test/pp.c b/test/pp.c
index f850c08..1c1549f 100644
--- a/test/pp.c
+++ b/test/pp.c
@@ -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));
}
diff --git a/test/pp.h b/test/pp.h
index 5ac7aac..029c6ee 100644
--- a/test/pp.h
+++ b/test/pp.h
@@ -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;
}