commit fa2b3a43dd98f64d34ec4024aab48dad84798a14
parent cf8f62f69138171d5983ab35ddf2bd6dda989fa9
Author: Eyal Sawady <ecs@d2evs.net>
Date: Sun, 31 Jan 2021 17:58:51 -0500
Implement static assertions
Diffstat:
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -211,6 +211,7 @@ check_expr_assert(struct context *ctx,
trace(TR_CHECK, "assert");
expr->type = EXPR_ASSERT;
expr->result = &builtin_type_void;
+ expr->assert.is_static = aexpr->assert.is_static;
if (aexpr->assert.cond != NULL) {
expr->assert.cond = xcalloc(1, sizeof(struct expression));
@@ -242,6 +243,28 @@ check_expr_assert(struct context *ctx,
expr->assert.message->constant.string.value = s;
expr->assert.message->constant.string.len = n;
}
+
+ if (expr->assert.is_static) {
+ bool cond;
+ if (expr->assert.cond != NULL) {
+ struct expression out = {0};
+ enum eval_result r =
+ eval_expr(ctx, expr->assert.cond, &out);
+ expect(&aexpr->assert.cond->loc, r == EVAL_OK,
+ "Unable to evaluate static assertion at compile time");
+ assert(out.result->storage == TYPE_STORAGE_BOOL);
+ cond = out.constant.bval;
+ } else {
+ cond = false;
+ }
+ if (aexpr->assert.message != NULL) {
+ expect(&aexpr->assert.cond->loc, cond,
+ "Static assertion failed: %s",
+ expr->assert.message->constant.string.value);
+ } else {
+ expect(&aexpr->loc, cond, "Static assertion failed");
+ }
+ }
}
static void
diff --git a/src/gen.c b/src/gen.c
@@ -644,6 +644,9 @@ gen_expr_assert(struct gen_context *ctx,
const struct qbe_value *out)
{
assert(expr->assert.message); // Invariant
+ if (expr->assert.is_static) {
+ return;
+ }
struct qbe_statement failedl = {0}, passedl = {0};
struct qbe_value bfailed = {0}, bpassed = {0};
diff --git a/src/parse.c b/src/parse.c
@@ -983,7 +983,7 @@ parse_plain_expression(struct lexer *lexer)
static struct ast_expression *
parse_assertion_expression(struct lexer *lexer, bool is_static)
{
- trace(TR_PARSE, "assertion");
+ trace(TR_PARSE, is_static ? "static assertion" : "assertion");
struct ast_expression *exp = mkexpr(&lexer->loc);
exp->type = EXPR_ASSERT;
@@ -991,16 +991,11 @@ parse_assertion_expression(struct lexer *lexer, bool is_static)
struct token tok;
switch (lex(lexer, &tok)) {
- case T_STATIC:
- // XXX: The caller should deal with this for us
- exp->assert.is_static = true;
- lex(lexer, &tok);
- break;
case T_ASSERT:
case T_ABORT:
break;
default:
- synassert(false, &tok, T_STATIC, T_ASSERT, T_ABORT, T_EOF);
+ synassert(false, &tok, T_ASSERT, T_ABORT, T_EOF);
}
switch (tok.token) {