rename two functions: get_variable_from_expr_simple() is the now just
[smatch.git] / smatch_extra.c
blob3e0f9b77508a8fdd79b290ab5d5a815026b97f55
1 /*
2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include "parse.h"
12 #include "smatch.h"
14 static int my_id;
16 static struct smatch_state *alloc_state(int val)
18 struct smatch_state *state;
20 state = malloc(sizeof(*state));
21 state->name = "value";
22 state->data = malloc(sizeof(int));
23 *(int *)state->data = val;
24 return state;
27 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
28 struct smatch_state *s1,
29 struct smatch_state *s2)
31 return &undefined;
34 static void match_function_call_after(struct expression *expr)
36 struct expression *tmp;
37 struct symbol *sym;
38 char *name;
39 int i = 0;
41 FOR_EACH_PTR(expr->args, tmp) {
42 if (tmp->op == '&') {
43 name = get_variable_from_expr(tmp->unop, &sym);
44 if (name) {
45 set_state(name, my_id, sym, &undefined);
48 i++;
49 } END_FOR_EACH_PTR(tmp);
52 static void match_assign(struct expression *expr)
54 struct expression *left;
55 struct symbol *sym;
56 char *name;
58 left = strip_expr(expr->left);
59 name = get_variable_from_expr(left, &sym);
60 if (!name)
61 return;
62 set_state(name, my_id, sym, alloc_state(get_value(expr->right)));
65 static void undef_expr(struct expression *expr)
67 struct symbol *sym;
68 char *name;
70 name = get_variable_from_expr(expr->unop, &sym);
71 if (!name)
72 return;
73 if (!get_state(name, my_id, sym)) {
74 free_string(name);
75 return;
77 set_state(name, my_id, sym, &undefined);
80 static void match_declarations(struct symbol *sym)
82 const char *name;
84 if (sym->ident) {
85 name = sym->ident->name;
86 if (sym->initializer) {
87 set_state(name, my_id, sym, alloc_state(get_value(sym->initializer)));
92 void register_smatch_extra(int id)
94 my_id = id;
95 add_merge_hook(my_id, &merge_func);
96 add_hook(&undef_expr, OP_HOOK);
97 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
98 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
99 add_hook(&match_declarations, DECLARATION_HOOK);
100 add_hook(&__implied_states_hook, WHOLE_CONDITION_HOOK);
103 static int expr_to_val(struct expression *expr)
105 struct smatch_state *state;
106 int val;
107 struct symbol *sym;
108 char *name;
110 val = get_value(expr);
111 if (val != UNDEFINED)
112 return val;
114 name = get_variable_from_expr(expr, &sym);
115 if (!name)
116 return UNDEFINED;
117 state = get_state(name, my_id, sym);
118 free_string(name);
119 if (!state || !state->data)
120 return UNDEFINED;
121 return *(int *)state->data;
124 static int true_comparison(int left, int comparison, int right)
126 switch(comparison){
127 case '<':
128 case SPECIAL_UNSIGNED_LT:
129 if (left < right)
130 return 1;
131 return 0;
132 case SPECIAL_UNSIGNED_LTE:
133 case SPECIAL_LTE:
134 if (left < right)
135 return 1;
136 case SPECIAL_EQUAL:
137 if (left == right)
138 return 1;
139 return 0;
140 case SPECIAL_UNSIGNED_GTE:
141 case SPECIAL_GTE:
142 if (left == right)
143 return 1;
144 case '>':
145 case SPECIAL_UNSIGNED_GT:
146 if (left > right)
147 return 1;
148 return 0;
149 case SPECIAL_NOTEQUAL:
150 if (left != right)
151 return 1;
152 return 0;
153 default:
154 smatch_msg("unhandled comparison %d\n", comparison);
156 return 0;
159 int known_condition_true(struct expression *expr)
161 int left, right, ret;
163 if (!expr || expr->type != EXPR_COMPARE)
164 return 0;
166 if ((left = expr_to_val(expr->left)) == UNDEFINED)
167 return 0;
169 if ((right = expr_to_val(expr->right)) == UNDEFINED)
170 return 0;
172 ret = true_comparison(left, expr->op, right);
173 if (ret)
174 SM_DEBUG("%d known condition: %d %s %d => true", get_lineno(),
175 left, show_special(expr->op), right);
176 else
177 smatch_msg("known condition: %d %s %d => false", left,
178 show_special(expr->op), right);
180 return ret;