Ignore stuff like foo.bar. We only care about foo->bar.
[smatch.git] / smatch_extra.c
blob9349d56dc942cc3385b0c6205e3f14b40f808104
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 symbol *sym;
56 char *name;
58 name = get_variable_from_expr_simple(expr->left, &sym);
59 if (!name)
60 return;
61 name = alloc_string(name);
62 set_state(name, my_id, sym, alloc_state(get_value(expr->right, NULL)));
65 static void undef_expr(struct expression *expr)
67 struct symbol *sym;
68 char *name;
70 name = get_variable_from_expr_simple(expr->unop, &sym);
71 if (!name)
72 return;
73 if (!get_state(name, my_id, sym))
74 return;
75 name = alloc_string(name);
76 set_state(name, my_id, sym, &undefined);
79 static void match_declarations(struct symbol *sym)
81 const char *name;
83 if (sym->ident) {
84 name = sym->ident->name;
85 if (sym->initializer) {
86 set_state(name, my_id, sym, alloc_state(get_value(sym->initializer, NULL)));
91 void register_smatch_extra(int id)
93 my_id = id;
94 add_merge_hook(my_id, &merge_func);
95 add_hook(&undef_expr, OP_HOOK);
96 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
97 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
98 add_hook(&match_declarations, DECLARATION_HOOK);
101 static int expr_to_val(struct expression *expr)
103 struct smatch_state *state;
104 int val;
105 struct symbol *sym;
106 char *name;
108 val = get_value(expr, NULL);
109 if (val != UNDEFINED)
110 return val;
112 name = get_variable_from_expr_simple(expr, &sym);
113 if (!name)
114 return UNDEFINED;
115 state = get_state(name, my_id, sym);
116 if (!state || !state->data)
117 return UNDEFINED;
118 return *(int *)state->data;
121 static int true_comparison(int left, int comparison, int right)
123 switch(comparison){
124 case '<':
125 case SPECIAL_UNSIGNED_LT:
126 if (left < right)
127 return 1;
128 return 0;
129 case SPECIAL_UNSIGNED_LTE:
130 case SPECIAL_LTE:
131 if (left < right)
132 return 1;
133 case SPECIAL_EQUAL:
134 if (left == right)
135 return 1;
136 return 0;
137 case SPECIAL_UNSIGNED_GTE:
138 case SPECIAL_GTE:
139 if (left == right)
140 return 1;
141 case '>':
142 case SPECIAL_UNSIGNED_GT:
143 if (left > right)
144 return 1;
145 return 0;
146 case SPECIAL_NOTEQUAL:
147 if (left != right)
148 return 1;
149 return 0;
150 default:
151 smatch_msg("unhandled comparison %d\n", comparison);
153 return 0;
156 int known_condition_true(struct expression *expr)
158 int left, right, ret;
160 if (!expr || expr->type != EXPR_COMPARE)
161 return 0;
163 if ((left = expr_to_val(expr->left)) == UNDEFINED)
164 return 0;
166 if ((right = expr_to_val(expr->right)) == UNDEFINED)
167 return 0;
169 ret = true_comparison(left, expr->op, right);
170 smatch_msg("known condition: %d & %d => %s", left, right, (ret?"true":"false"));
172 return ret;