aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2007-07-01 08:49:22 +0100
committerJosh Triplett <josh@freedesktop.org>2007-07-08 18:57:32 -0700
commitc3aac8e1fd7cbfab1f4c87baeb4b57453720d77a (patch)
tree2edc01916eaf2c8964a5587df5ea1c2af225c484 /expand.c
parentfix the comma handling in integer constant expressions (diff)
downloadsparse-c3aac8e1fd7cbfab1f4c87baeb4b57453720d77a.tar.gz
sparse-c3aac8e1fd7cbfab1f4c87baeb4b57453720d77a.tar.bz2
sparse-c3aac8e1fd7cbfab1f4c87baeb4b57453720d77a.zip
first pass at null pointer constants
AFAICS, that should do null pointer constants right. We assign special instance of void * (&null_ctype) to (void *)<zero integer constant expression> and replace it with normal void * when we don't want null pointer constant. is_zero_constant() checks if we have an integer constant expression, does conservative expand (i.e. instead of generating an error on 1/0, etc. leaves the node unreplaced) and checks if we have reduced the sucker to EXPR_VALUE[0] without comma taint. Implemented all (AFAICS) special cases involving null pointer constants; most changes in evaluate_compare() and evaluate_conditional(). Both are still incomplete; handling of qualifiers is still missing, but that's a separate story. Note that we get two new sets of warnings on the kernel build; one is due to wrong size_t (handled in the next patch; didn't show up until now since we didn't warn on comparison of pointers to incompatible types) and another is a pile of warnings about integer 0 used as NULL on if (p == 0) where p is a pointer. Additionally, there's an idiotic (p>0) in one place (again, p is a pointer). Bugger if I know how gcc doesn't warn on that one, it's certainly a standard violation and bloody pointless even as extension... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'expand.c')
-rw-r--r--expand.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/expand.c b/expand.c
index 780b643..b2eeef8 100644
--- a/expand.c
+++ b/expand.c
@@ -34,6 +34,7 @@
static int expand_expression(struct expression *);
static int expand_statement(struct statement *);
+static int conservative;
static int expand_symbol_expression(struct expression *expr)
{
@@ -97,7 +98,7 @@ Int:
expr->value = value & mask;
// Stop here unless checking for truncation
- if (!Wcast_truncate)
+ if (!Wcast_truncate || conservative)
return;
// Check if we dropped any bits..
@@ -138,10 +139,8 @@ Float:
static int check_shift_count(struct expression *expr, struct symbol *ctype, unsigned int count)
{
- if (count >= ctype->bit_size) {
- warning(expr->pos, "shift too big (%u) for type %s", count, show_typename(ctype));
- count &= ctype->bit_size-1;
- }
+ warning(expr->pos, "shift too big (%u) for type %s", count, show_typename(ctype));
+ count &= ctype->bit_size-1;
return count;
}
@@ -163,8 +162,12 @@ static int simplify_int_binop(struct expression *expr, struct symbol *ctype)
return 0;
r = right->value;
if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) {
- r = check_shift_count(expr, ctype, r);
- right->value = r;
+ if (r >= ctype->bit_size) {
+ if (conservative)
+ return 0;
+ r = check_shift_count(expr, ctype, r);
+ right->value = r;
+ }
}
if (left->type != EXPR_VALUE)
return 0;
@@ -257,10 +260,12 @@ static int simplify_int_binop(struct expression *expr, struct symbol *ctype)
expr->taint = left->taint | right->taint;
return 1;
Div:
- warning(expr->pos, "division by zero");
+ if (!conservative)
+ warning(expr->pos, "division by zero");
return 0;
Overflow:
- warning(expr->pos, "constant integer operation overflow");
+ if (!conservative)
+ warning(expr->pos, "constant integer operation overflow");
return 0;
}
@@ -340,7 +345,8 @@ static int simplify_float_binop(struct expression *expr)
expr->fvalue = res;
return 1;
Div:
- warning(expr->pos, "division by zero");
+ if (!conservative)
+ warning(expr->pos, "division by zero");
return 0;
}
@@ -660,7 +666,8 @@ static int simplify_preop(struct expression *expr)
return 1;
Overflow:
- warning(expr->pos, "constant integer operation overflow");
+ if (!conservative)
+ warning(expr->pos, "constant integer operation overflow");
return 0;
}
@@ -1222,3 +1229,12 @@ long long const_expression_value(struct expression *expr)
{
return __get_expression_value(expr, 1);
}
+
+int is_zero_constant(struct expression *expr)
+{
+ int saved = conservative;
+ conservative = 1;
+ expand_expression(expr);
+ conservative = saved;
+ return expr->type == EXPR_VALUE && !expr->value;
+}