aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-06-24 03:11:14 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2007-06-26 17:31:53 -0400
commita24a3adf3f0e3c22b0d98837090c55307f6fec84 (patch)
treeb78f5f0745a25bd3a05296497d1202caf508ec90 /expand.c
parent[PATCH] implement __builtin_offsetof() (diff)
downloadsparse-a24a3adf3f0e3c22b0d98837090c55307f6fec84.tar.gz
sparse-a24a3adf3f0e3c22b0d98837090c55307f6fec84.tar.bz2
sparse-a24a3adf3f0e3c22b0d98837090c55307f6fec84.zip
[PATCH] fix handling of integer constant expressions
Hopefully correct handling of integer constant expressions. Please, review. Rules: * two new flags for expression: int_const_expr and float_literal. * parser sets them by the following rules: * EXPR_FVALUE gets float_literal * EXPR_VALUE gets int_const_expr * EXPR_PREOP[(] inherits from argument * EXPR_SIZEOF, EXPR_PTRSIZEOF, EXPR_ALIGNOF get int_const_expr * EXPR_BINOP, EXPR_COMPARE, EXPR_LOGICAL, EXPR_CONDITIONAL, EXPR_PREOP[+,-,!,~]: get marked int_const_expr if all their arguments are marked that way * EXPR_CAST gets marked int_const_expr if argument is marked that way; if argument is marked float_literal but not int_const_expr, we get both flags set. * EXPR_TYPE also gets marked int_const_expr (to make it DTRT on the builtin_same_type_p() et.al.) * EXPR_OFFSETOF gets marked int_const_expr When we get an expression from parser, we know that having int_const_expr on it is almost equivalent to "it's an integer constant expression". Indeed, the only checks we still have not done are that all casts present in there are to integer types, that expression is correctly typed and that all indices in offsetof are integer constant expressions. That belongs to evaluate_expression() and is easily done there. * evaluate_expression() removes int_const_expr from some nodes: * EXPR_BINOP, EXPR_COMPARE, EXPR_LOGICAL, EXPR_CONDITIONAL, EXPR_PREOP: if the node is marked int_const_expr and some of its arguments are not marked that way once we have done evaluate_expression() on them, unmark our node. * EXPR_IMLICIT_CAST: inherit flags from argument. * cannibalizing nodes in *& and &* simplifications: unmark the result. * EXPR_CAST: unmark if we are casting not to an integer type. Unmark if argument is not marked with int_const_expr after evaluate_expression() on it *and* our node is not marked float_literal (i.e. (int)0.0 is fine with us). * EXPR_BINOP created (or cannibalizing EXPR_OFFSETOF) by evaluation of evaluate_offsetof() get int_const_expr if both arguments (already typechecked) have int_const_expr. * unmark node when we declare it mistyped. That does it - after evaluate_expression() we keep int_const_expr only if expression was a valid integer constant expression. Remaining issue: VLA handling. Right now sparse doesn't deal with those in any sane way, but once we start handling their sizeof, we'll need to check that type is constant-sized before marking EXPR_SIZEOF int_const_expr. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'expand.c')
-rw-r--r--expand.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/expand.c b/expand.c
index c6d188e..f945518 100644
--- a/expand.c
+++ b/expand.c
@@ -1144,7 +1144,7 @@ static int expand_statement(struct statement *stmt)
return SIDE_EFFECTS;
}
-long long get_expression_value(struct expression *expr)
+static long long __get_expression_value(struct expression *expr, int strict)
{
long long value, mask;
struct symbol *ctype;
@@ -1161,6 +1161,10 @@ long long get_expression_value(struct expression *expr)
expression_error(expr, "bad constant expression");
return 0;
}
+ if (strict && !(expr->flags & Int_const_expr)) {
+ expression_error(expr, "bad integer constant expression");
+ return 0;
+ }
value = expr->value;
mask = 1ULL << (ctype->bit_size-1);
@@ -1173,3 +1177,13 @@ long long get_expression_value(struct expression *expr)
}
return value;
}
+
+long long get_expression_value(struct expression *expr)
+{
+ return __get_expression_value(expr, 0);
+}
+
+long long const_expression_value(struct expression *expr)
+{
+ return __get_expression_value(expr, 1);
+}