add a check for passing stack variables to dma functions
[smatch.git] / check_signed.c
blob06363671267acec98cc46c03d92239451811a327
1 /*
2 * sparse/check_signed.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * Check for things which are signed but probably should be unsigned.
13 * Hm... It seems like at this point in the processing, sparse makes all
14 * bitfields unsigned. Which is logical but not what GCC does.
18 #include "smatch.h"
20 static int my_id;
22 static unsigned long long max_size(struct symbol *base_type)
25 I wanted to say:
27 unsigned long long ret = 0xffffffffffffffff;
29 But gcc complained that was too large. What am I doing wrong?
30 Oh well. I expect most of the problems are with smaller
31 values anyway
34 unsigned long long ret = 0xffffffff;
35 int bits;
37 bits = base_type->bit_size;
38 if (base_type->ctype.modifiers & MOD_SIGNED)
39 bits--;
40 ret >>= (32 - bits);
41 return ret;
44 static void match_assign(struct expression *expr)
46 struct symbol *sym;
47 long long val;
48 long long max;
49 char *name;
51 sym = get_type(expr->left);
52 if (!sym) {
53 //sm_msg("could not get type");
54 return;
56 if (sym->bit_size >= 32) /* max_val limits this */
57 return;
58 if (!get_implied_value(expr->right, &val))
59 return;
60 max = max_size(sym);
61 if (max < val) {
62 name = get_variable_from_expr_complex(expr->left, NULL);
63 sm_msg("error: value %lld can't fit into %lld %s", val, max, name);
64 free_string(name);
68 static void match_condition(struct expression *expr)
70 long long known;
71 struct expression *var = NULL;
72 struct symbol *sym = NULL;
73 long long max;
74 char *name;
76 if (expr->type != EXPR_COMPARE)
77 return;
78 if (get_implied_value(expr->left, &known))
79 var = expr->right;
80 else if (get_implied_value(expr->right, &known))
81 var = expr->left;
82 if (!var)
83 return;
84 sym = get_type(var);
86 if (!sym || sym->bit_size >= 32)
87 return;
88 max = max_size(sym);
89 if (max < known) {
90 name = get_variable_from_expr_complex(var, NULL);
91 sm_msg("error: value %lld is higher than %lld so this is always false.",
92 known, max);
93 free_string(name);
97 void check_signed(int id)
99 my_id = id;
101 if (!option_spammy)
102 return;
103 add_hook(&match_assign, ASSIGNMENT_HOOK);
104 add_hook(&match_condition, CONDITION_HOOK);