aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-09-10 20:15:26 +0200
committerlemon <lsof@mailbox.org>2025-09-10 20:15:26 +0200
commit3fc3b2680581a59b3d08244a190d5d7bdcf80e45 (patch)
tree48ba5f49f02023f0e4967b583ea280d547e05ec6
parent45591bc221bb8268567acdaa523cbac94d31a90e (diff)
c: warn redefinition, allow redeclaratinos
-rw-r--r--c.c23
-rw-r--r--c.h1
2 files changed, 20 insertions, 4 deletions
diff --git a/c.c b/c.c
index 268b01c..16348c4 100644
--- a/c.c
+++ b/c.c
@@ -198,6 +198,11 @@ 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:
case SCTYPEDEF:
return old->ty.bits == new->ty.bits;
}
@@ -209,9 +214,16 @@ putdecl(struct comp *cm, const struct decl *decl)
{
struct decl *l;
for (l = NULL; enviterdecl(&l, cm->env);) {
- if (decl->name == l->name && !redeclarationok(l, decl)) {
- error(&decl->span, "incompatible redeclaration of '%s'", decl->name);
- note(&l->span, "previously declared here");
+ if (decl->name == l->name) {
+ if (l->isdef && decl->isdef) {
+ error(&decl->span, "redefinition of '%s'", decl->name);
+ note(&l->span, "previously defined here");
+ break;
+ } else if (!redeclarationok(l, decl)) {
+ error(&decl->span, "incompatible redeclaration of '%s'", decl->name);
+ note(&l->span, "previously declared here");
+ break;
+ }
}
}
l = envadddecl(cm->env, decl);
@@ -2201,7 +2213,7 @@ pdecl(struct declstate *st, struct comp *cm) {
}
if (first && st->tagdecl && match(cm, &tk, ';')) {
- decl = (struct decl) { st->base, st->scls, st->qual, st->align, tk.span };
+ decl = (struct decl) { st->base, st->scls, st->qual, st->align, 0, tk.span };
return decl;
}
decl = declarator(st, cm);
@@ -3268,6 +3280,7 @@ localdecl(struct comp *cm, struct function *fn, bool forini)
}
}
} else if (decl.scls == SCSTATIC) {
+ assert(0);
}
break;
case SCTYPEDEF:
@@ -3394,11 +3407,13 @@ docomp(struct comp *cm)
noscls = 1;
decl.scls = SCEXTERN;
}
+ decl.isdef = st.varini;
if (st.funcdef) {
const struct typedata *td = &typedata[decl.ty.dat];
struct function fn = { cm->fnarena, decl.name, .globl = decl.scls != SCSTATIC };
fn.fnty = decl.ty;
fn.retty = td->ret;
+ decl.isdef = 1;
putdecl(cm, &decl);
irinit(&fn);
function(cm, &fn, st.pnames, st.pspans);
diff --git a/c.h b/c.h
index 33eef54..d9466fc 100644
--- a/c.h
+++ b/c.h
@@ -65,6 +65,7 @@ struct decl {
uchar scls;
uchar qual : 2;
uchar isenum : 1;
+ uchar isdef : 1;
struct span span;
const char *name;
union {