[hackers] [scc] Force expressions in case and array sizes to be int constants || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Thu, 23 Jul 2015 18:33:56 +0200 (CEST)

commit a564bb5b0d450239b5e5f7379a631dee4593ca28
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Thu Jul 23 18:30:53 2015 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Thu Jul 23 18:30:53 2015 +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.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index e5273bf..ec2ff40 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -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
index 6390a41..4af9314 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
_AT_@ -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
index 42a3a3b..709b53b 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
_AT_@ -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
index 072686e..e409cd3 100644
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
_AT_@ -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;
Received on Thu Jul 23 2015 - 18:33:56 CEST

This archive was generated by hypermail 2.3.0 : Thu Jul 23 2015 - 18:36:14 CEST