sval: signed: pretty much re-write the whole thing
[smatch.git] / smatch_capped.c
blob4a1ff6ac7ce4514d473476f49bdad6916e166381
1 /*
2 * smatch/smatch_capped.c
4 * Copyright (C) 2011 Oracle. All rights reserved.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This is trying to make a list of the variables which
12 * have capped values. Sometimes we don't know what the
13 * cap is, for example if we are comparing variables but
14 * we don't know the values of the variables. In that
15 * case we only know that our variable is capped and we
16 * sort that information here.
19 #include "smatch.h"
20 #include "smatch_slist.h"
22 static int my_id;
24 STATE(capped);
25 STATE(uncapped);
27 static int is_capped_macro(struct expression *expr)
29 char *name;
31 name = get_macro_name(expr->pos);
32 if (!name)
33 return 0;
35 if (strcmp(name, "min") == 0)
36 return 1;
37 if (strcmp(name, "MIN") == 0)
38 return 1;
39 if (strcmp(name, "min_t") == 0)
40 return 1;
42 return 0;
45 int is_capped(struct expression *expr)
47 sval_t sval;
49 expr = strip_expr(expr);
50 if (!expr)
51 return 0;
53 if (is_capped_macro(expr))
54 return 1;
56 if (expr->type == EXPR_BINOP) {
57 if (expr->op == '&')
58 return 1;
59 if (expr->op == SPECIAL_RIGHTSHIFT)
60 return 1;
61 if (expr->op == '%')
62 return is_capped(expr->right);
63 if (!is_capped(expr->left))
64 return 0;
65 if (expr->op == '/')
66 return 1;
67 if (!is_capped(expr->right))
68 return 0;
69 return 1;
71 if (get_implied_max_sval(expr, &sval))
72 return 1;
73 if (get_state_expr(my_id, expr) == &capped)
74 return 1;
75 return 0;
78 void set_param_capped_data(const char *name, struct symbol *sym, char *key, char *value)
80 char fullname[256];
82 if (strncmp(key, "$$", 2))
83 return;
84 snprintf(fullname, 256, "%s%s", name, key + 2);
85 set_state(my_id, fullname, sym, &capped);
88 static void match_condition(struct expression *expr)
90 struct smatch_state *left_true = NULL;
91 struct smatch_state *left_false = NULL;
92 struct smatch_state *right_true = NULL;
93 struct smatch_state *right_false = NULL;
96 if (expr->type != EXPR_COMPARE)
97 return;
99 switch (expr->op) {
100 case '<':
101 case SPECIAL_LTE:
102 case SPECIAL_UNSIGNED_LT:
103 case SPECIAL_UNSIGNED_LTE:
104 left_true = &capped;
105 right_false = &capped;
106 break;
107 case '>':
108 case SPECIAL_GTE:
109 case SPECIAL_UNSIGNED_GT:
110 case SPECIAL_UNSIGNED_GTE:
111 left_false = &capped;
112 right_true = &capped;
113 break;
114 case SPECIAL_EQUAL:
115 left_true = &capped;
116 right_true = &capped;
117 break;
118 case SPECIAL_NOTEQUAL:
119 left_false = &capped;
120 right_false = &capped;
121 break;
123 default:
124 return;
127 set_true_false_states_expr(my_id, expr->right, right_true, right_false);
128 set_true_false_states_expr(my_id, expr->left, left_true, left_false);
131 static void match_assign(struct expression *expr)
133 if (is_capped(expr->right)) {
134 set_state_expr(my_id, expr->left, &capped);
135 } else {
136 if (get_state_expr(my_id, expr->left))
137 set_state_expr(my_id, expr->left, &uncapped);
141 static void match_caller_info(struct expression *expr)
143 struct expression *tmp;
144 char *func;
145 int i;
147 func = get_fnptr_name(expr->fn);
148 if (!func)
149 return;
151 i = 0;
152 FOR_EACH_PTR(expr->args, tmp) {
153 if (is_capped(tmp))
154 sm_msg("info: passes capped_data %s %d '$$' %s", func,
155 i, is_static(expr->fn) ? "static" : "global");
156 i++;
157 } END_FOR_EACH_PTR(tmp);
160 static void struct_member_callback(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state)
162 if (state != &capped)
163 return;
164 sm_msg("info: passes capped_data '%s' %d '%s' %s", fn, param, printed_name, global_static);
167 void register_capped(int id)
169 my_id = id;
171 add_definition_db_callback(set_param_capped_data, CAPPED_DATA);
172 add_hook(&match_condition, CONDITION_HOOK);
173 add_hook(&match_assign, ASSIGNMENT_HOOK);
174 if (option_info) {
175 add_hook(&match_caller_info, FUNCTION_CALL_HOOK);
176 add_member_info_callback(my_id, struct_member_callback);