Make get_all_states() not segfault every time.
[smatch.git] / smatch_extra.c
bloba3125d8aa9ce5d7415e5a49f3e6e1870ab40d25e
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_simple(tmp->unop, &sym);
44 if (name) {
45 name = alloc_string(name);
46 set_state(name, my_id, sym, &undefined);
49 i++;
50 } END_FOR_EACH_PTR(tmp);
53 static void match_assign(struct expression *expr)
55 struct expression *left;
56 struct symbol *sym;
57 char *name;
59 left = strip_expr(expr->left);
60 name = get_variable_from_expr_simple(left, &sym);
61 if (!name)
62 return;
63 name = alloc_string(name);
64 set_state(name, my_id, sym, alloc_state(get_value(expr->right)));
67 static void undef_expr(struct expression *expr)
69 struct symbol *sym;
70 char *name;
72 name = get_variable_from_expr_simple(expr->unop, &sym);
73 if (!name)
74 return;
75 if (!get_state(name, my_id, sym))
76 return;
77 name = alloc_string(name);
78 set_state(name, my_id, sym, &undefined);
81 static void match_declarations(struct symbol *sym)
83 const char *name;
85 if (sym->ident) {
86 name = sym->ident->name;
87 if (sym->initializer) {
88 set_state(name, my_id, sym, alloc_state(get_value(sym->initializer)));
93 void register_smatch_extra(int id)
95 my_id = id;
96 add_merge_hook(my_id, &merge_func);
97 add_hook(&undef_expr, OP_HOOK);
98 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
99 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
100 add_hook(&match_declarations, DECLARATION_HOOK);
101 add_hook(&__implied_states_hook, WHOLE_CONDITION_HOOK);
104 static int expr_to_val(struct expression *expr)
106 struct smatch_state *state;
107 int val;
108 struct symbol *sym;
109 char *name;
111 val = get_value(expr);
112 if (val != UNDEFINED)
113 return val;
115 name = get_variable_from_expr_simple(expr, &sym);
116 if (!name)
117 return UNDEFINED;
118 state = get_state(name, my_id, sym);
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;