commit b86fdca96b49c9000d32995a427f2ac8fad4ef6a
parent 73e8f02ee56e42272698ef92ec8b593cec130843
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 24 Jul 2015 17:27:23 +0200
Merge branch 'master' of ssh://suckless.org/gitrepos/scc
Conflicts:
cc1/cc1.h
Diffstat:
5 files changed, 84 insertions(+), 20 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -327,10 +327,13 @@ extern Node *constnode(Symbol *sym);
extern Node *sizeofnode(Type *tp);
extern void freetree(Node *np);
extern Node *simplify(unsigned char, Type *tp, Node *lp, Node *rp);
+extern Node *usimplify(unsigned char op, Type *tp, Node *np);
#define BTYPE(np) ((np)->type->op)
/* expr.c */
extern Node *expr(void), *negate(Node *np), *constexpr(void);
+extern Node *convert(Node *np, Type *tp1, char iscast);
+extern Node *iszero(Node *np), *eval(Node *np), *iconstexpr(void);
/* cpp.c */
extern void icpp(void);
diff --git a/cc1/code.c b/cc1/code.c
@@ -463,8 +463,6 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
case OOR:
FOLDINT(sym, ls, rs, ||);
break;
- default:
- abort();
}
break;
case FLOAT:
@@ -481,3 +479,45 @@ division_by_0:
no_simplify:
return node(op, tp, lp, rp);
}
+
+#define UFOLDINT(sym, ls, op) (((sym)->type->sign) ? \
+ ((sym)->u.i = (op (ls)->u.i)) : \
+ ((sym)->u.u = (op (ls)->u.u)))
+
+Node *
+usimplify(unsigned char op, Type *tp, Node *np)
+{
+ Symbol *sym, *ns;
+
+ if (!np->constant)
+ goto no_simplify;
+ ns = np->sym;
+
+ switch (tp->op) {
+ case INT:
+ switch (op) {
+ case ONEG:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ UFOLDINT(sym, ns, -);
+ break;
+ case OCPL:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ UFOLDINT(sym, ns, ~);
+ break;
+ default:
+ goto no_simplify;
+ }
+ break;
+ case FLOAT:
+ /* TODO: implement floats */
+ default:
+ goto no_simplify;
+ }
+
+ return constnode(sym);
+
+no_simplify:
+ return node(op, tp, np, NULL);
+}
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
@@ -88,7 +88,7 @@ numericaluop(char op, Node *np)
case FLOAT:
if (op == OADD)
return np;
- return node(op, np->type, np, NULL);
+ return usimplify(op, np->type, np);
default:
error("unary operator requires integer operand");
}
@@ -100,7 +100,7 @@ integeruop(char op, Node *np)
np = eval(np);
if (BTYPE(np) != INT)
error("unary operator requires integer operand");
- return node(op, np->type, np, NULL);
+ return usimplify(op, np->type, np);
}
static Node *
@@ -123,13 +123,18 @@ convert(Node *np, Type *tp, char iscast)
if (eqtype(np->type, tp))
return np;
switch (BTYPE(np)) {
- case ENUM: case INT: case FLOAT:
+ case ENUM:
+ case INT:
+ case FLOAT:
switch (tp->op) {
case PTR:
if (!iscast || BTYPE(np) == FLOAT)
return NULL;
/* PASSTHROUGH */
- case INT: case FLOAT: case ENUM: case VOID:
+ case INT:
+ case FLOAT:
+ case ENUM:
+ case VOID:
break;
default:
return NULL;
@@ -137,7 +142,9 @@ convert(Node *np, Type *tp, char iscast)
break;
case PTR:
switch (tp->op) {
- case ENUM: case INT: case VOID: /* TODO: allow p = 0 */
+ case ENUM: /* TODO: allow p = 0 */
+ case INT:
+ case VOID:
if (!iscast)
return NULL;;
break;
@@ -851,12 +858,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
@@ -9,8 +9,6 @@
Symbol *curfun;
-extern Node *convert(Node *np, Type *tp1, char iscast);
-extern Node *iszero(Node *np), *eval(Node *np);
static void stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
static void
@@ -251,9 +249,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;