scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit a564bb5b0d450239b5e5f7379a631dee4593ca28
parent 18071c940a707f9de54540e4ddbb405bbf8cba19
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 23 Jul 2015 18:30:53 +0200

Force expressions in case and array sizes to be int constants

C89/C90 needs integer constant in array sizes (C99 admits VLA, but
this is something we will see later), so the size must be known at
compile time. In the same way, case labels must be a constant
integer expression.

Diffstat:
Mcc1/cc1.h | 3++-
Mcc1/decl.c | 11+++++------
Mcc1/expr.c | 22++++++++++++++++++++--
Mcc1/stmt.c | 5++---
4 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -330,7 +330,8 @@ extern Node *simplify(unsigned char, Type *tp, Node *lp, Node *rp); extern Node *usimplify(unsigned char op, Type *tp, Node *np); /* expr.c */ -extern Node *expr(void), *negate(Node *np), *constexpr(void); +extern Node *expr(void), *negate(Node *np), *constexpr(void), + *iconstexpr(void); /* cpp.c */ extern void icpp(void); diff --git a/cc1/decl.c b/cc1/decl.c @@ -39,17 +39,16 @@ queue(struct dcldata *dp, unsigned op, short nelem, void *data) static struct dcldata * arydcl(struct dcldata *dp) { - Node *np; + Node *np = NULL; TINT n; expect('['); - np = (yytoken != ']') ? constexpr() : NULL; + if (yytoken != ']') { + if ((np = iconstexpr()) == NULL) + error("invalid storage size"); + } expect(']'); - /* - * TODO: check that the type of the constant expression - * is the correct, that in this case should be int - */ n = (np == NULL) ? 0 : np->sym->u.i; freetree(np); diff --git a/cc1/expr.c b/cc1/expr.c @@ -853,12 +853,30 @@ constexpr(void) Node *np; np = ternary(); - if (!np->constant) - error("constant expression required"); + if (!np->constant) { + freetree(np); + return NULL; + } return np; } Node * +iconstexpr(void) +{ + Node *np; + + if ((np = constexpr()) == NULL) + return NULL; + + if (np->type->op != INT) { + freetree(np); + return NULL; + } + + return convert(np, inttype, 0); +} + +Node * expr(void) { Node *lp, *rp; diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -250,9 +250,8 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) expect(CASE); if (!lswitch) error("case label not within a switch statement"); - np = expr(); - if ((np = convert(np, inttype, 0)) == NULL) - error("incorrect type in case statement"); + if ((np = iconstexpr()) == NULL) + error("case label does not reduce to an integer constant"); expect(':'); pcase = xmalloc(sizeof(*pcase)); pcase->expr = np;