aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c/c.c51
-rw-r--r--ir/builder.c2
-rw-r--r--obj/elf.c14
-rw-r--r--obj/obj.c7
-rw-r--r--obj/obj.h1
5 files changed, 57 insertions, 18 deletions
diff --git a/c/c.c b/c/c.c
index e669baf..36ef6d5 100644
--- a/c/c.c
+++ b/c/c.c
@@ -230,9 +230,6 @@ redeclarationok(const struct decl *old, const struct decl *new)
if (old->scls != new->scls) return 0;
switch (old->scls) {
case SCSTATIC:
- if (old->ty.t != TYFUNC)
- break;
- /*fallthru*/
case SCEXTERN:
if (old->ty.t == TYARRAY && new->ty.t == TYARRAY
&& typechild(old->ty).bits == typechild(new->ty).bits
@@ -253,7 +250,7 @@ putdecl(struct comp *cm, const struct decl *decl)
assert(!decl->isbuiltin);
for (struct decl *l = NULL; enviterdecl(&l, cm->env);) {
if (decl->name == l->name) {
- if (l->isdef && decl->isdef) {
+ if ((cm->env->up != NULL && decl->scls == SCSTATIC) || (l->isdef && decl->isdef)) {
error(&decl->span, "redefinition of '%s'", decl->name);
note(&l->span, "previously defined here");
break;
@@ -262,6 +259,7 @@ putdecl(struct comp *cm, const struct decl *decl)
note(&l->span, "previously declared here");
break;
}
+ if (l->isdef && !decl->isdef) return l;
}
}
return envadddecl(cm->env, decl);
@@ -1627,7 +1625,8 @@ initializer(struct comp *cm, union type *ty, enum evalmode ev, bool globl,
memset(ip->ddat.p, 0, typesize(*ty));
} else {
ip->sec = qual & QCONST ? Srodata : Sdata;
- ip->off = objnewdat(sym, ip->sec, globl, typesize(*ty), typealign(*ty));
+ if (!nerror)
+ ip->off = objnewdat(sym, ip->sec, globl, typesize(*ty), typealign(*ty));
}
} else {
ip->init = &res;
@@ -1713,13 +1712,15 @@ initializer(struct comp *cm, union type *ty, enum evalmode ev, bool globl,
sec = Srodata;
else
sec = Sdata;
- off = objnewdat(sym, sec, globl, siz = typesize(*ty), align = typealign(*ty));
- p = sec == Srodata ? objout.rodata.p : objout.data.p;
- memcpy(p + off, ip->ddat.p, ip->ddat.n);
- memset(p + off + ip->ddat.n, 0, typesize(*ty) - ip->ddat.n);
- vfree(&ip->ddat);
- for (struct dreloc *rel = ip->drel; rel; rel = rel->link) {
- objreloc(rel->sym, targ_64bit ? REL_ABS64 : REL_ABS32, sec, off + rel->off, rel->addend);
+ if (!nerror) {
+ off = objnewdat(sym, sec, globl, siz = typesize(*ty), align = typealign(*ty));
+ p = sec == Srodata ? objout.rodata.p : objout.data.p;
+ memcpy(p + off, ip->ddat.p, ip->ddat.n);
+ memset(p + off + ip->ddat.n, 0, typesize(*ty) - ip->ddat.n);
+ vfree(&ip->ddat);
+ for (struct dreloc *rel = ip->drel; rel; rel = rel->link) {
+ objreloc(rel->sym, targ_64bit ? REL_ABS64 : REL_ABS32, sec, off + rel->off, rel->addend);
+ }
}
}
dumpini(ip);
@@ -3226,10 +3227,13 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
//eval((struct expr *)ex, EVFOLD);
sub = ex->sub;
- if (ex->ty.t != TYVOID && !isscalar(ex->ty))
+ if (ex->ty.t != TYVOID && !isscalar(ex->ty)) {
/* fn & array designators evaluate to their address;
* so do aggregates for the purpose of code generation */
+ if (isagg(ex->ty) && isincomplete(ex->ty))
+ error(&ex->span, "use of incomplete type '%ty'", ex->ty);
return expraddr(fn, ex);
+ }
switch (ex->t) {
case ENUMLIT:
if (discard) return NOREF;
@@ -4281,13 +4285,26 @@ docomp(struct comp *cm)
} else if (decl.name) {
struct decl *d = putdecl(cm, &decl);
if (st.varini) {
+ if (isagg(d->ty) && isincomplete(d->ty))
+ error(&d->span, "initialization of variable with incomplete type '%ty'", d->ty);
(void) initializer(cm, &d->ty, EVSTATICINI, decl.scls != SCSTATIC, decl.qual, decl.sym);
pdecl(&st, cm);
} else if (decl.ty.t != TYFUNC && decl.scls != SCTYPEDEF && (decl.scls != SCEXTERN || noscls)) {
- if (!isincomplete(decl.ty))
- objnewdat(d->sym, Sbss, decl.scls == SCEXTERN, typesize(d->ty), typealign(d->ty));
- else
- error(&decl.span, "definition of static variable with incomplete type");
+ /* tentative definitions */
+ if (!objhassym(decl.sym)) {
+ uint size = typesize(d->ty);
+ if (isincomplete(d->ty)) {
+ if (d->ty.t == TYARRAY) {
+ warn(&d->span, "tentative array definition assumed to have one element");
+ size = typesize(typechild(d->ty));
+ assert(size != 0);
+ } else if (isagg(d->ty)) {
+ warn(&d->span, "tentative definition with incomplete type '%ty'", d->ty);
+ assert(size == 0);
+ } else assert(0);
+ }
+ if (size) objnewdat(d->sym, Sbss, decl.scls == SCEXTERN, size, typealign(d->ty));
+ }
}
if (ccopt.dbg.p) bfmt(ccopt.dbgout, "var %s : %tq\n", d->name, d->ty, d->qual);
} else {
diff --git a/ir/builder.c b/ir/builder.c
index 4b25329..ee83961 100644
--- a/ir/builder.c
+++ b/ir/builder.c
@@ -214,7 +214,7 @@ useblk(struct function *fn, struct block *blk)
extern int nerror;
if (fn->curblk && nerror == 0) assert(fn->curblk->jmp.t && "never finished block");
if (blk) assert(!blk->jmp.t && "reusing built block");
- if (!blk->lprev) { /* initialize */
+ if (blk && !blk->lprev) { /* initialize */
blk->lnext = fn->entry;
blk->lprev = fn->entry->lprev;
blk->lprev->lnext = blk;
diff --git a/obj/elf.c b/obj/elf.c
index d889fdd..5578452 100644
--- a/obj/elf.c
+++ b/obj/elf.c
@@ -87,6 +87,20 @@ enum {
BSS_SHNDX = 4,
};
+enum section
+elfhassym(const char *nam)
+{
+ struct sym *sym = findsym(str2idx(nam));
+ if (sym) switch (sym->shndx) {
+ case SHN_UND: return Snone;
+ case TEXT_SHNDX: return Stext;
+ case RODATA_SHNDX: return Srodata;
+ case DATA_SHNDX: return Sdata;
+ case BSS_SHNDX: return Sbss;
+ }
+ return Snone;
+}
+
void
elfaddsym(const char *nam, int info, enum section sect, uvlong value, uvlong size)
{
diff --git a/obj/obj.c b/obj/obj.c
index b9e2c79..fa62e9e 100644
--- a/obj/obj.c
+++ b/obj/obj.c
@@ -6,6 +6,7 @@
void elfinit(void);
+enum section elfhassym(const char *);
void elfaddsym(const char *, int info, enum section, uvlong value, uvlong size);
void elfreloc(const char *sym, enum relockind, enum section, uint off, vlong addend);
void elffini(struct wbuf *);
@@ -38,6 +39,12 @@ objdeffunc(const char *nam, bool globl, uint off, uint siz)
}
}
+enum section
+objhassym(const char *name)
+{
+ return elfhassym(name);
+}
+
uint
objnewdat(const char *name, enum section sec, bool globl, uint siz, uint align)
{
diff --git a/obj/obj.h b/obj/obj.h
index 235ab4d..8e9dea8 100644
--- a/obj/obj.h
+++ b/obj/obj.h
@@ -23,6 +23,7 @@ enum section { Snone, Stext, Srodata, Sdata, Sbss };
void objini(const char *infile, const char *outfile);
void objdeffunc(const char *nam, bool globl, uint off, uint siz);
+enum section objhassym(const char *name);
uint objnewdat(const char *name, enum section, bool globl, uint siz, uint align);
void objreloc(const char *sym, enum relockind, enum section, uint off, vlong addend);
void objfini(void);