aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--decl.c8
-rw-r--r--expr.c4
-rw-r--r--expr.h2
-rw-r--r--init.c2
-rw-r--r--stmt.c2
5 files changed, 10 insertions, 8 deletions
diff --git a/decl.c b/decl.c
index ac72f23..870d72a 100644
--- a/decl.c
+++ b/decl.c
@@ -212,7 +212,7 @@ tagspec(struct scope *s)
scopeputdecl(s, tok.lit, d);
next();
if (consume(TASSIGN))
- i = intconstexpr(s);
+ i = intconstexpr(s, true);
d->value = mkintconst(t->repr, i);
if (!consume(TCOMMA))
break;
@@ -336,7 +336,7 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspecifier *fs, int *a
if (t) {
*align = t->align;
} else {
- i = intconstexpr(s);
+ i = intconstexpr(s, false);
if (!i || i & (i - 1) || i > 16)
error(&tok.loc, "invalid alignment: %d", i);
*align = (int)i;
@@ -511,7 +511,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
i = 0;
next();
} else {
- i = intconstexpr(s);
+ i = intconstexpr(s, false);
expect(TRBRACK, "after array length");
}
if (tq) {
@@ -712,7 +712,7 @@ decl(struct scope *s, struct function *f)
if (consume(T_STATIC_ASSERT)) {
expect(TLPAREN, "after _Static_assert");
- c = intconstexpr(s);
+ c = intconstexpr(s, true);
expect(TCOMMA, "after static assertion expression");
expect(TSTRINGLIT, "after static assertion expression");
if (!c)
diff --git a/expr.c b/expr.c
index 501e0e5..a09f2d6 100644
--- a/expr.c
+++ b/expr.c
@@ -847,13 +847,15 @@ condexpr(struct scope *s)
}
uint64_t
-intconstexpr(struct scope *s)
+intconstexpr(struct scope *s, bool allowneg)
{
struct expression *e;
e = eval(condexpr(s));
if (e->kind != EXPRCONST || !(typeprop(e->type) & PROPINT))
error(&tok.loc, "not an integer constant expression");
+ if (!allowneg && e->type->basic.issigned && e->constant.i > INT64_MAX)
+ error(&tok.loc, "integer constant expression cannot be negative");
return e->constant.i;
}
diff --git a/expr.h b/expr.h
index 7de6635..8e7aa4c 100644
--- a/expr.h
+++ b/expr.h
@@ -88,7 +88,7 @@ struct scope;
struct expression *expr(struct scope *);
struct expression *assignexpr(struct scope *);
-uint64_t intconstexpr(struct scope *);
+uint64_t intconstexpr(struct scope *, _Bool);
void delexpr(struct expression *);
void exprpromote(struct expression **); // XXX: move to type
diff --git a/init.c b/init.c
index ec76ef3..20e2f51 100644
--- a/init.c
+++ b/init.c
@@ -129,7 +129,7 @@ designator(struct scope *s, struct initparser *p)
if (t->kind != TYPEARRAY)
error(&tok.loc, "index designator is only valid for array types");
next();
- p->sub->idx = intconstexpr(s);
+ p->sub->idx = intconstexpr(s, false);
if (t->incomplete)
updatearray(t, p->sub->idx);
else if (p->sub->idx >= t->array.length)
diff --git a/stmt.c b/stmt.c
index a5192c5..e642353 100644
--- a/stmt.c
+++ b/stmt.c
@@ -52,7 +52,7 @@ stmt(struct function *f, struct scope *s)
error(&tok.loc, "'case' label must be in switch");
label[0] = mkblock("switch_case");
funclabel(f, label[0]);
- i = intconstexpr(s);
+ i = intconstexpr(s, true);
switchcase(s->switchcases, i, label[0]);
expect(TCOLON, "after case expression");
stmt(f, s);