Remove some false positives and enable the check.
[smatch.git] / smatch_helper.c
blob789d389e5b9f27bb3fa420d7f5ce48aab36a6098
1 /*
2 * sparse/smatch_helper.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "allocate.h"
13 #include "smatch.h"
15 static int star_count;
16 #define VAR_LEN 512
19 char *alloc_string(const char *str)
21 char *tmp;
23 if (!str)
24 return NULL;
25 tmp = malloc(strlen(str) + 1);
26 strcpy(tmp, str);
27 return tmp;
30 void free_string(char *str)
32 free(str);
35 static void prepend(char *dest, const char *data, int buff_len)
37 int space_needed;
38 int i;
40 space_needed = strlen(data);
41 for (i = buff_len - space_needed - 1; i >= 0 ; i--)
42 dest[i + space_needed] = dest[i];
43 for (i = 0; i < space_needed % buff_len ; i++)
44 dest[i] = data[i];
45 dest[buff_len - 1] = '\0';
49 * If you have "foo(a, b, 1);" then use
50 * get_argument_from_call_expr(expr, 0) to return the expression for
51 * a. Yes, it does start counting from 0.
53 struct expression *get_argument_from_call_expr(struct expression_list *args,
54 int num)
56 struct expression *expr;
57 int i = 0;
59 if (!args)
60 return NULL;
62 FOR_EACH_PTR(args, expr) {
63 if (i == num)
64 return expr;
65 i++;
66 } END_FOR_EACH_PTR(expr);
67 return NULL;
70 static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf,
71 struct expression *expr, int len,
72 int *complicated)
74 switch(expr->type) {
75 case EXPR_DEREF:
76 prepend(buf, expr->member->name, len);
77 if (!strcmp(show_special(expr->deref->op), "*"))
78 prepend(buf, "->", len);
79 else
80 prepend(buf, ".", len);
82 //printf("debug: %d\n", expr->deref
84 __get_variable_from_expr(sym_ptr, buf, expr->deref,
85 len, complicated);
86 return;
87 case EXPR_SYMBOL:
88 if (expr->symbol_name)
89 prepend(buf, expr->symbol_name->name, len);
90 if (sym_ptr) {
91 if (*sym_ptr)
92 *complicated = 1;
93 *sym_ptr = expr->symbol;
95 return;
96 case EXPR_PREOP: {
97 const char *tmp;
99 if (expr->op == '*')
100 star_count++;
102 __get_variable_from_expr(sym_ptr, buf, expr->unop,
103 len, complicated);
104 tmp = show_special(expr->op);
105 if (tmp[0] == '*') {
106 if (star_count-- >= 0) {
107 prepend(buf, tmp, len);
109 } else {
110 prepend(buf, tmp, len);
113 if (tmp[0] == '(') {
114 strncat(buf, ")", len);
115 buf[len - 1] = '\0';
118 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
119 *complicated = 1;
121 return;
123 case EXPR_POSTOP: {
124 const char *tmp;
126 tmp = show_special(expr->op);
127 prepend(buf, tmp, len);
128 __get_variable_from_expr(sym_ptr, buf, expr->unop,
129 len, complicated);
131 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
132 *complicated = 1;
134 return;
136 case EXPR_BINOP: {
137 const char *tmp;
139 *complicated = 1;
140 prepend(buf, ")", len);
141 __get_variable_from_expr(NULL, buf, expr->right, len,
142 complicated);
143 tmp = show_special(expr->op);
144 prepend(buf, tmp, len);
145 __get_variable_from_expr(sym_ptr, buf, expr->left,
146 len, complicated);
147 prepend(buf, "(", len);
148 return;
150 case EXPR_VALUE: {
151 char tmp[25];
153 snprintf(tmp, 25, "%lld", expr->value);
154 prepend(buf, tmp, len);
155 return;
157 case EXPR_STRING:
158 prepend(buf, expr->string->data, len);
159 return;
160 case EXPR_CALL: {
161 struct expression *tmp;
162 int i = 0;
164 *complicated = 1;
165 prepend(buf, ")", len);
166 FOR_EACH_PTR_REVERSE(expr->args, tmp) {
167 if (i++)
168 prepend(buf, ", ", len);
169 __get_variable_from_expr(NULL, buf, tmp, len,
170 complicated);
171 } END_FOR_EACH_PTR_REVERSE(tmp);
172 prepend(buf, "(", len);
173 __get_variable_from_expr(NULL, buf, expr->fn, len,
174 complicated);
175 return;
177 case EXPR_CAST:
178 __get_variable_from_expr(sym_ptr, buf,
179 expr->cast_expression, len,
180 complicated);
181 return;
182 case EXPR_SIZEOF: {
183 int size;
184 char tmp[25];
186 if (expr->cast_type && get_base_type(expr->cast_type)) {
187 size = (get_base_type(expr->cast_type))->bit_size;
188 snprintf(tmp, 25, "%d", size);
189 prepend(buf, tmp, len);
191 return;
193 default:
194 *complicated = 1;
195 //printf("unknown type = %d\n", expr->type);
196 return;
202 * This is returns a stylized "c looking" representation of the
203 * variable name.
205 * It uses the same buffer every time so you have to save the result
206 * yourself if you want to keep it.
210 char *get_variable_from_expr_complex(struct expression *expr, struct symbol **sym_ptr)
212 static char var_name[VAR_LEN];
213 int junk;
215 if (sym_ptr)
216 *sym_ptr = NULL;
217 star_count = 0;
218 var_name[0] = '\0';
220 if (!expr)
221 return NULL;
222 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
223 &junk);
225 return var_name;
229 * get_variable_from_expr_simple() only returns simple variables.
230 * If it's a complicated variable like a->foo instead of just 'a'
231 * then it returns NULL.
234 char *get_variable_from_expr(struct expression *expr,
235 struct symbol **sym_ptr)
237 static char var_name[VAR_LEN];
238 int complicated = 0;
240 if (sym_ptr)
241 *sym_ptr = NULL;
242 star_count = 0;
243 var_name[0] = '\0';
245 if (!expr)
246 return NULL;
247 expr = strip_expr(expr);
248 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
249 &complicated);
251 if (complicated) {
252 if (sym_ptr)
253 *sym_ptr = NULL;
254 return NULL;
256 return alloc_string(var_name);
259 int sym_name_is(const char *name, struct expression *expr)
261 if (!expr)
262 return 0;
263 if (expr->type != EXPR_SYMBOL)
264 return 0;
265 if (!strcmp(expr->symbol_name->name, name))
266 return 1;
267 return 0;
270 static int _get_value(struct expression *expr, int *discard)
272 int dis = 0;
273 int ret = UNDEFINED;
275 if (!expr)
276 return UNDEFINED;
277 if (!discard)
278 discard = &dis;
279 if (*discard)
280 return UNDEFINED;
282 expr = strip_expr(expr);
284 switch (expr->type){
285 case EXPR_VALUE:
286 ret = expr->value;
287 break;
288 case EXPR_PREOP:
289 if (!strcmp("-", show_special(expr->op)))
290 ret = - _get_value(expr->unop, discard);
291 else
292 *discard = 1;
293 break;
294 case EXPR_BINOP: {
295 int left, right;
297 if (!show_special(expr->op)) {
298 *discard = 1;
299 break;
301 left = _get_value(expr->left, discard);
302 right = _get_value(expr->right, discard);
303 if (!strcmp("*", show_special(expr->op))) {
304 ret = left * right;
305 } else if (!strcmp("/", show_special(expr->op))) {
306 ret = left / right;
307 } else if (!strcmp("+", show_special(expr->op))) {
308 ret = left + right;
309 } else if (!strcmp("-", show_special(expr->op))) {
310 ret = left - right;
311 } else if (!strcmp("|", show_special(expr->op))) {
312 ret = left | right;
313 } else {
314 *discard = 1;
316 break;
318 case EXPR_SIZEOF:
319 if (expr->cast_type && get_base_type(expr->cast_type))
320 ret = (get_base_type(expr->cast_type))->bit_size / 8;
321 else
322 *discard = 1;
323 break;
324 default:
325 //printf("ouchies-->%d\n", expr->type);
326 *discard = 1;
328 if (*discard)
329 return UNDEFINED;
330 return ret;
333 int get_value(struct expression *expr)
335 return _get_value(expr, NULL);
338 int is_zero(struct expression *expr)
340 if (get_value(expr) == 0)
341 return 1;
342 return 0;
345 const char *show_state(struct smatch_state *state)
347 if (!state)
348 return NULL;
349 return state->name;
352 struct statement *get_block_thing(struct expression *expr)
354 /* What are those things called? if (({....; ret;})) { ...*/
356 if (expr->type != EXPR_PREOP)
357 return NULL;
358 if (expr->op != '(')
359 return NULL;
360 if (expr->unop->type != EXPR_STATEMENT)
361 return NULL;
362 if (expr->unop->statement->type != STMT_COMPOUND)
363 return NULL;
364 return expr->unop->statement;
367 struct expression *strip_expr(struct expression *expr)
369 if (!expr)
370 return NULL;
372 switch(expr->type) {
373 case EXPR_CAST:
374 return strip_expr(expr->cast_expression);
375 case EXPR_PREOP:
376 if (expr->op == '(' && expr->unop->type == EXPR_STATEMENT &&
377 expr->unop->statement->type == STMT_COMPOUND)
378 return expr;
379 if (expr->op == '(')
380 return strip_expr(expr->unop);
382 return expr;