negative_error_code: add special handling for negative checks
[smatch.git] / smatch_expressions.c
blobb1440ecd66fe4005456b2f15129aa6eedf6a1f6e
1 #include "smatch.h"
2 #include "smatch_extra.h"
4 DECLARE_ALLOCATOR(sname);
5 __ALLOCATOR(struct expression, "temporary expr", tmp_expression);
7 static struct position get_cur_pos(void)
9 static struct position pos;
10 static struct position none;
11 struct expression *expr;
12 struct statement *stmt;
14 expr = last_ptr_list((struct ptr_list *)big_expression_stack);
15 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
16 if (expr)
17 pos = expr->pos;
18 else if (stmt)
19 pos = stmt->pos;
20 else
21 pos = none;
22 return pos;
25 struct expression *alloc_tmp_expression(struct position pos, int type)
27 struct expression *expr;
29 expr = __alloc_tmp_expression(0);
30 expr->smatch_flags |= Tmp;
31 expr->type = type;
32 expr->pos = pos;
33 return expr;
36 void free_tmp_expressions(void)
38 clear_tmp_expression_alloc();
41 struct expression *zero_expr(void)
43 struct expression *zero;
45 zero = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
46 zero->value = 0;
47 zero->ctype = &int_ctype;
48 return zero;
51 struct expression *sval_to_expr(sval_t sval)
53 struct expression *expr;
55 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
56 expr->value = sval.value;
57 expr->ctype = sval.type;
58 return expr;
61 struct expression *value_expr(long long val)
63 struct expression *expr;
65 if (!val)
66 return zero_expr();
68 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
69 expr->value = val;
70 expr->ctype = &llong_ctype;
71 return expr;
74 static struct expression *symbol_expression_helper(struct symbol *sym, bool perm)
76 struct expression *expr;
78 if (perm)
79 expr = alloc_expression(sym->pos, EXPR_SYMBOL);
80 else
81 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL);
82 expr->symbol = sym;
83 expr->symbol_name = sym->ident;
84 return expr;
87 struct expression *symbol_expression(struct symbol *sym)
89 return symbol_expression_helper(sym, false);
92 struct expression *cast_expression(struct expression *expr, struct symbol *type)
94 struct expression *cast;
96 cast = alloc_tmp_expression(expr->pos, EXPR_CAST);
97 cast->cast_type = type;
98 cast->cast_expression = expr;
99 return cast;
102 struct expression *member_expression(struct expression *deref, int op, struct ident *member)
104 struct expression *expr;
106 expr = alloc_tmp_expression(deref->pos, EXPR_DEREF);
107 expr->op = op;
108 expr->deref = deref;
109 expr->member = member;
110 expr->member_offset = -1;
111 return expr;
114 struct expression *preop_expression(struct expression *expr, int op)
116 struct expression *preop;
118 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP);
119 preop->unop = expr;
120 preop->op = op;
121 return preop;
124 struct expression *deref_expression(struct expression *expr)
126 /* The *&foo is just foo */
127 if (expr->type == EXPR_PREOP && expr->op == '&')
128 return strip_expr(expr->unop);
129 if (expr->type == EXPR_BINOP)
130 expr = preop_expression(expr, '(');
131 return preop_expression(expr, '*');
134 struct expression *deref_expression_no_parens(struct expression *expr)
136 return preop_expression(expr, '*');
139 struct expression *assign_expression(struct expression *left, int op, struct expression *right)
141 struct expression *expr;
143 if (!right)
144 return NULL;
146 /* FIXME: make this a tmp expression. */
147 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT);
148 expr->op = op;
149 expr->left = left;
150 expr->right = right;
151 return expr;
154 struct expression *assign_expression_perm(struct expression *left, int op, struct expression *right)
156 struct expression *expr;
158 if (!right)
159 return NULL;
161 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT);
162 expr->op = op;
163 expr->left = left;
164 expr->right = right;
165 return expr;
168 struct expression *create_fake_assign(const char *name, struct symbol *type, struct expression *right)
170 struct expression *left, *assign;
172 if (!right)
173 return NULL;
175 if (!type) {
176 type = get_type(right);
177 if (!type)
178 return NULL;
181 left = fake_variable_perm(type, name);
183 assign = assign_expression_perm(left, '=', right);
185 assign->smatch_flags |= Fake;
187 assign->parent = right->parent;
188 expr_set_parent_expr(right, assign);
190 __fake_state_cnt++;
192 return assign;
195 struct expression *binop_expression(struct expression *left, int op, struct expression *right)
197 struct expression *expr;
199 expr = alloc_tmp_expression(right->pos, EXPR_BINOP);
200 expr->op = op;
201 expr->left = left;
202 expr->right = right;
203 return expr;
206 struct expression *array_element_expression(struct expression *array, struct expression *offset)
208 struct expression *expr;
210 expr = binop_expression(array, '+', offset);
211 return deref_expression_no_parens(expr);
214 struct expression *compare_expression(struct expression *left, int op, struct expression *right)
216 struct expression *expr;
218 if (!left || !right)
219 return NULL;
221 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE);
222 expr->op = op;
223 expr->left = left;
224 expr->right = right;
225 return expr;
228 struct expression *alloc_expression_stmt_perm(struct statement *last_stmt)
230 struct expression *expr;
232 if (!last_stmt)
233 return NULL;
235 expr = alloc_tmp_expression(last_stmt->pos, EXPR_STATEMENT);
236 expr->statement = last_stmt;
238 return expr;
241 struct expression *gen_string_expression(char *str)
243 struct expression *ret;
244 struct string *string;
245 int len;
247 len = strlen(str) + 1;
248 string = (void *)__alloc_sname(4 + len);
249 string->length = len;
250 string->immutable = 0;
251 memcpy(string->data, str, len);
253 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING);
254 ret->wide = 0;
255 ret->string = string;
257 return ret;
260 struct expression *call_expression(struct expression *fn, struct expression_list *args)
262 struct expression *expr;
264 expr = alloc_tmp_expression(fn->pos, EXPR_CALL);
265 expr->fn = fn;
266 expr->args = args;
268 return expr;
271 static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition)
273 struct expression *ret = NULL;
274 struct token *token, *prev, *end;
275 char *alloc;
277 if (addition[0] == '\0')
278 return base;
280 alloc = alloc_string_newline(addition);
282 token = tokenize_buffer(alloc, strlen(alloc), &end);
283 if (!token)
284 goto free;
285 if (token_type(token) != TOKEN_STREAMBEGIN)
286 goto free;
287 token = token->next;
289 ret = base;
290 while (token_type(token) == TOKEN_SPECIAL &&
291 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
292 prev = token;
293 token = token->next;
294 if (token_type(token) != TOKEN_IDENT)
295 goto free;
296 switch (prev->special) {
297 case SPECIAL_DEREFERENCE:
298 ret = deref_expression(ret);
299 ret = member_expression(ret, '*', token->ident);
300 break;
301 case '.':
302 ret = member_expression(ret, '.', token->ident);
303 break;
304 default:
305 goto free;
307 token = token->next;
310 if (token_type(token) != TOKEN_STREAMEND)
311 goto free;
313 free:
314 free_string(alloc);
316 return ret;
319 static struct expression *gen_expression_from_name_sym_helper(const char *name, struct symbol *sym)
321 struct expression *ret;
322 int skip = 0;
324 if (!sym)
325 return NULL;
327 if (name[0] == '&' ||
328 name[0] == '*' ||
329 name[0] == '(') {
330 ret = gen_expression_from_name_sym_helper(name + 1, sym);
331 return preop_expression(ret, name[0]);
333 while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-')
334 skip++;
336 return get_expression_from_base_and_str(symbol_expression(sym), name + skip);
339 struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym)
341 struct expression *ret;
343 ret = gen_expression_from_name_sym_helper(name, sym);
344 if (ret) {
345 char *new = expr_to_str(ret);
348 * FIXME: this sometimes changes "foo->bar.a.b->c" into
349 * "foo->bar.a.b.c". I don't know why... :(
352 if (!new || strcmp(name, new) != 0)
353 return NULL;
355 return ret;
358 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
360 struct expression *ret;
361 struct token *token, *end;
362 const char *p = key;
363 char buf[4095];
364 char *alloc;
365 int cnt = 0;
366 size_t len;
367 bool star;
369 if (strcmp(key, "*$") == 0) {
370 if (arg->type == EXPR_PREOP &&
371 arg->op == '&')
372 return strip_expr(arg->unop);
373 return deref_expression(arg);
376 /* The idea is that we can parse either $0->foo or $->foo */
377 if (key[0] != '$')
378 return NULL;
379 p++;
380 while (*p >= '0' && *p <= '9')
381 p++;
382 len = snprintf(buf, sizeof(buf), "%s\n", p);
383 alloc = alloc_string(buf);
385 token = tokenize_buffer(alloc, len, &end);
386 if (!token)
387 return NULL;
388 if (token_type(token) != TOKEN_STREAMBEGIN)
389 return NULL;
390 token = token->next;
392 ret = arg;
393 while (token_type(token) == TOKEN_SPECIAL &&
394 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
395 if (token->special == SPECIAL_DEREFERENCE)
396 star = true;
397 else
398 star = false;
400 if (cnt++ == 0 && ret->type == EXPR_PREOP && ret->op == '&') {
401 ret = strip_expr(ret->unop);
402 star = false;
405 token = token->next;
406 if (token_type(token) != TOKEN_IDENT)
407 return NULL;
409 if (star)
410 ret = deref_expression(ret);
411 ret = member_expression(ret, star ? '*' : '.', token->ident);
412 token = token->next;
415 if (token_type(token) != TOKEN_STREAMEND)
416 return NULL;
418 return ret;
421 struct expression *gen_expr_from_param_key(struct expression *expr, int param, const char *key)
423 struct expression *call, *arg;
425 if (!expr)
426 return NULL;
428 call = expr;
429 while (call->type == EXPR_ASSIGNMENT)
430 call = strip_expr(call->right);
431 if (call->type != EXPR_CALL)
432 return NULL;
434 if (param == -1) {
435 if (expr->type != EXPR_ASSIGNMENT)
436 return NULL;
437 arg = expr->left;
438 } else {
439 arg = get_argument_from_call_expr(call->args, param);
440 if (!arg)
441 return NULL;
444 return gen_expression_from_key(arg, key);
447 bool is_fake_var(struct expression *expr)
449 if (expr && (expr->smatch_flags & Fake))
450 return true;
451 return false;
454 bool is_fake_var_assign(struct expression *expr)
456 struct expression *left;
457 struct symbol *sym;
459 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
460 return false;
461 left = expr->left;
462 if (left->type != EXPR_SYMBOL)
463 return false;
464 if (!is_fake_var(left))
465 return false;
467 sym = left->symbol;
468 if (strncmp(sym->ident->name, "__fake_", 7) != 0)
469 return false;
470 return true;
473 static struct expression *fake_variable_helper(struct symbol *type, const char *name, bool perm)
475 struct symbol *sym, *node;
476 struct expression *ret;
477 struct ident *ident;
479 if (!type)
480 type = &llong_ctype;
482 ident = alloc_ident(name, strlen(name));
484 sym = alloc_symbol(get_cur_pos(), type->type);
485 sym->ident = ident;
486 sym->ctype.base_type = type;
487 sym->ctype.modifiers |= MOD_AUTO;
489 node = alloc_symbol(get_cur_pos(), SYM_NODE);
490 node->ident = ident;
491 node->ctype.base_type = type;
492 node->ctype.modifiers |= MOD_AUTO;
494 if (perm)
495 ret = symbol_expression_helper(node, true);
496 else
497 ret = symbol_expression(node);
499 ret->smatch_flags |= Fake;
501 return ret;
504 struct expression *fake_variable(struct symbol *type, const char *name)
506 return fake_variable_helper(type, name, false);
509 struct expression *fake_variable_perm(struct symbol *type, const char *name)
511 return fake_variable_helper(type, name, true);
514 void expr_set_parent_expr(struct expression *expr, struct expression *parent)
516 struct expression *prev;
518 if (!expr || !parent)
519 return;
521 prev = expr_get_parent_expr(expr);
522 if (prev == parent)
523 return;
525 if (parent && parent->smatch_flags & Tmp)
526 return;
528 expr->parent = (unsigned long)parent | 0x1UL;
531 void expr_set_parent_stmt(struct expression *expr, struct statement *parent)
533 if (!expr)
534 return;
535 expr->parent = (unsigned long)parent;
538 struct expression *expr_get_parent_expr(struct expression *expr)
540 struct expression *parent;
542 if (!expr)
543 return NULL;
544 if (!(expr->parent & 0x1UL))
545 return NULL;
547 parent = (struct expression *)(expr->parent & ~0x1UL);
548 if (parent && (parent->smatch_flags & Fake))
549 return expr_get_parent_expr(parent);
550 return parent;
553 struct expression *expr_get_fake_parent_expr(struct expression *expr)
555 struct expression *parent;
557 if (!expr)
558 return NULL;
559 if (!(expr->parent & 0x1UL))
560 return NULL;
562 parent = (struct expression *)(expr->parent & ~0x1UL);
563 if (parent && (parent->smatch_flags & Fake))
564 return parent;
565 return NULL;
568 struct statement *expr_get_parent_stmt(struct expression *expr)
570 struct expression *parent;
572 if (!expr)
573 return NULL;
574 if (expr->parent & 0x1UL) {
575 parent = (struct expression *)(expr->parent & ~0x1UL);
576 if (parent->smatch_flags & Fake)
577 return expr_get_parent_stmt(parent);
578 return NULL;
580 return (struct statement *)expr->parent;
583 struct statement *get_parent_stmt(struct expression *expr)
585 struct expression *tmp;
586 int count = 10;
588 if (!expr)
589 return NULL;
590 while (--count > 0 && (tmp = expr_get_parent_expr(expr)))
591 expr = tmp;
592 if (!count)
593 return NULL;
595 return expr_get_parent_stmt(expr);