aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h3
-rw-r--r--decl.c28
-rw-r--r--eval.c2
-rw-r--r--expr.c1
-rw-r--r--qbe.c8
5 files changed, 24 insertions, 18 deletions
diff --git a/cc.h b/cc.h
index cae963d..c076de3 100644
--- a/cc.h
+++ b/cc.h
@@ -252,6 +252,7 @@ struct decl {
enum declkind kind;
enum linkage linkage;
struct type *type;
+ enum typequal qual;
struct value *value;
/* objects and functions */
@@ -416,7 +417,7 @@ extern struct type typevalist, typevalistptr;
/* decl */
-struct decl *mkdecl(enum declkind, struct type *, enum linkage);
+struct decl *mkdecl(enum declkind, struct type *, enum typequal, enum linkage);
_Bool decl(struct scope *, struct func *);
struct type *typename(struct scope *);
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;
diff --git a/eval.c b/eval.c
index 46dfd5c..9324c1e 100644
--- a/eval.c
+++ b/eval.c
@@ -78,7 +78,7 @@ eval(struct expr *expr)
expr->constant.i = intconstvalue(expr->ident.decl->value);
break;
case EXPRCOMPOUND:
- d = mkdecl(DECLOBJECT, mkqualifiedtype(expr->type, expr->qual), LINKNONE);
+ d = mkdecl(DECLOBJECT, expr->type, expr->qual, LINKNONE);
d->value = mkglobal(NULL, true);
emitdata(d, expr->compound.init);
expr->kind = EXPRIDENT;
diff --git a/expr.c b/expr.c
index 755fdef..6e35a29 100644
--- a/expr.c
+++ b/expr.c
@@ -312,6 +312,7 @@ primaryexpr(struct scope *s)
if (!d)
error(&tok.loc, "undeclared identifier: %s", tok.lit);
e = mkexpr(EXPRIDENT, d->type);
+ e->qual = d->qual;
e->lvalue = d->kind == DECLOBJECT;
e->ident.decl = d;
if (d->kind != DECLBUILTIN)
diff --git a/qbe.c b/qbe.c
index 1fa637d..8fa2b88 100644
--- a/qbe.c
+++ b/qbe.c
@@ -364,7 +364,7 @@ mkfunc(char *name, struct type *t, struct scope *s)
if (!t->func.isprototype && !typecompatible(p->type, typeargpromote(p->type)))
error(&tok.loc, "old-style function definition with parameter type incompatible with promoted type is not yet supported");
emittype(p->type);
- d = mkdecl(DECLOBJECT, mkqualifiedtype(p->type, p->qual), LINKNONE);
+ d = mkdecl(DECLOBJECT, p->type, p->qual, LINKNONE);
p->value = xmalloc(sizeof(*p->value));
functemp(f, p->value, p->type->repr);
if (p->type->repr->abi.id) {
@@ -379,7 +379,7 @@ mkfunc(char *name, struct type *t, struct scope *s)
}
t = mkarraytype(mkqualifiedtype(&typechar, QUALCONST), strlen(name) + 1);
- d = mkdecl(DECLOBJECT, t, LINKNONE);
+ d = mkdecl(DECLOBJECT, t, QUALNONE, LINKNONE);
d->value = mkglobal("__func__", true);
scopeputdecl(s, "__func__", d);
/*
@@ -469,7 +469,7 @@ objectaddr(struct func *f, struct expr *e)
d = stringdecl(e);
return d->value;
case EXPRCOMPOUND:
- d = mkdecl(DECLOBJECT, mkqualifiedtype(e->type, e->qual), LINKNONE);
+ d = mkdecl(DECLOBJECT, e->type, e->qual, LINKNONE);
funcinit(f, d, e->compound.init);
return d->value;
case EXPRUNARY:
@@ -578,7 +578,7 @@ funcexpr(struct func *f, struct expr *e)
case EXPRIDENT:
d = e->ident.decl;
switch (d->kind) {
- case DECLOBJECT: return funcload(f, typeunqual(d->type, NULL), d->value);
+ case DECLOBJECT: return funcload(f, d->type, d->value);
case DECLCONST: return d->value;
default:
fatal("unimplemented declaration kind %d", d->kind);