aboutsummaryrefslogtreecommitdiff
path: root/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'decl.c')
-rw-r--r--decl.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/decl.c b/decl.c
index 665752b..141ccbd 100644
--- a/decl.c
+++ b/decl.c
@@ -56,14 +56,16 @@ struct structbuilder {
};
struct decl *
-mkdecl(enum declkind k, struct type *t, enum linkage linkage)
+mkdecl(enum declkind k, struct type *t, enum typequal tq, enum linkage linkage)
{
struct decl *d;
+ assert(t->kind != TYPEQUALIFIED);
d = xmalloc(sizeof(*d));
d->kind = k;
d->linkage = linkage;
d->type = t;
+ d->qual = tq;
d->tentative = false;
d->defined = false;
d->align = 0;
@@ -208,7 +210,7 @@ tagspec(struct scope *s)
break;
case TYPEBASIC: /* enum */
for (i = 0; tok.kind == TIDENT; ++i) {
- d = mkdecl(DECLCONST, &typeint, LINKNONE);
+ d = mkdecl(DECLCONST, &typeint, QUALNONE, LINKNONE);
scopeputdecl(s, tok.lit, d);
next();
if (consume(TASSIGN))
@@ -741,6 +743,7 @@ bool
decl(struct scope *s, struct func *f)
{
struct type *t, *base;
+ enum typequal tq;
enum storageclass sc;
enum funcspec fs;
struct init *init;
@@ -779,7 +782,8 @@ decl(struct scope *s, struct func *f)
return true;
}
for (;;) {
- t = declarator(s, base, &name, false);
+ tq = QUALNONE;
+ t = typeunqual(declarator(s, base, &name, false), &tq);
kind = sc & SCTYPEDEF ? DECLTYPE : t->kind == TYPEFUNC ? DECLFUNC : DECLOBJECT;
d = scopegetdecl(s, name, false);
if (d && d->kind != kind)
@@ -789,8 +793,8 @@ decl(struct scope *s, struct func *f)
if (align)
error(&tok.loc, "typedef '%s' declared with alignment specifier", name);
if (!d)
- scopeputdecl(s, name, mkdecl(DECLTYPE, t, LINKNONE));
- else if (!typesame(d->type, t))
+ scopeputdecl(s, name, mkdecl(DECLTYPE, t, tq, LINKNONE));
+ else if (!typesame(d->type, t) || d->qual != tq)
error(&tok.loc, "typedef '%s' redefined with different type", name);
break;
case DECLOBJECT:
@@ -802,7 +806,7 @@ decl(struct scope *s, struct func *f)
if (d->linkage != linkage)
error(&tok.loc, "object '%s' redeclared with different linkage", name);
}
- if (!typecompatible(d->type, t))
+ if (!typecompatible(d->type, t) || d->qual != tq)
error(&tok.loc, "object '%s' redeclared with incompatible type", name);
d->type = typecomposite(t, d->type);
} else {
@@ -814,7 +818,7 @@ decl(struct scope *s, struct func *f)
if (d) {
if (d->linkage != linkage)
error(&tok.loc, "object '%s' redeclared with different linkage", name);
- if (!typecompatible(d->type, t))
+ if (!typecompatible(d->type, t) || d->qual != tq)
error(&tok.loc, "object '%s' redeclared with incompatible type", name);
t = typecomposite(t, d->type);
}
@@ -822,7 +826,7 @@ decl(struct scope *s, struct func *f)
linkage = f ? LINKNONE : sc & SCSTATIC ? LINKINTERN : LINKEXTERN;
}
- d = mkdecl(kind, t, linkage);
+ d = mkdecl(kind, t, tq, linkage);
scopeputdecl(s, name, d);
if (linkage != LINKNONE || sc & SCSTATIC)
d->value = mkglobal(name, linkage == LINKNONE);
@@ -875,7 +879,7 @@ decl(struct scope *s, struct func *f)
}
}
if (d) {
- if (!typecompatible(t, d->type))
+ if (!typecompatible(t, d->type) || tq != d->qual)
error(&tok.loc, "function '%s' redeclared with incompatible type", name);
d->type = typecomposite(t, d->type);
} else {
@@ -883,13 +887,13 @@ decl(struct scope *s, struct func *f)
d = scopegetdecl(s->parent, name, 1);
if (d && d->linkage != LINKNONE) {
linkage = d->linkage;
- if (!typecompatible(t, d->type))
+ if (!typecompatible(t, d->type) || tq != d->qual)
error(&tok.loc, "function '%s' redeclared with incompatible type", name);
t = typecomposite(t, d->type);
} else {
linkage = sc & SCSTATIC ? LINKINTERN : LINKEXTERN;
}
- d = mkdecl(kind, t, linkage);
+ d = mkdecl(kind, t, tq, linkage);
d->value = mkglobal(name, false);
scopeputdecl(s, name, d);
}
@@ -936,7 +940,7 @@ struct decl *stringdecl(struct expr *expr)
entry = htabput(strings, &key);
d = *entry;
if (!d) {
- d = mkdecl(DECLOBJECT, expr->type, LINKNONE);
+ d = mkdecl(DECLOBJECT, expr->type, QUALNONE, LINKNONE);
d->value = mkglobal("string", true);
emitdata(d, mkinit(0, expr->type->size, expr));
*entry = d;