comparison: select the caller_info
[smatch.git] / smatch_expressions.c
blobf741c90db0aef5ef2a52266e0a800ea937747a4a
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 *value_expr(long long val)
53 struct expression *expr;
55 if (!val)
56 return zero_expr();
58 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
59 expr->value = val;
60 expr->ctype = &llong_ctype;
61 return expr;
64 struct expression *member_expression(struct expression *deref, int op, struct ident *member)
66 struct expression *expr;
68 expr = alloc_tmp_expression(deref->pos, EXPR_DEREF);
69 expr->op = op;
70 expr->deref = deref;
71 expr->member = member;
72 expr->member_offset = -1;
73 return expr;
76 struct expression *preop_expression(struct expression *expr, int op)
78 struct expression *preop;
80 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP);
81 preop->unop = expr;
82 preop->op = op;
83 return preop;
86 struct expression *deref_expression(struct expression *expr)
88 if (expr->type == EXPR_BINOP)
89 expr = preop_expression(expr, '(');
90 return preop_expression(expr, '*');
93 struct expression *assign_expression(struct expression *left, int op, struct expression *right)
95 struct expression *expr;
97 if (!right)
98 return NULL;
100 /* FIXME: make this a tmp expression. */
101 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT);
102 expr->op = op;
103 expr->left = left;
104 expr->right = right;
105 return expr;
108 struct expression *binop_expression(struct expression *left, int op, struct expression *right)
110 struct expression *expr;
112 expr = alloc_tmp_expression(right->pos, EXPR_BINOP);
113 expr->op = op;
114 expr->left = left;
115 expr->right = right;
116 return expr;
119 struct expression *array_element_expression(struct expression *array, struct expression *offset)
121 struct expression *expr;
123 expr = binop_expression(array, '+', offset);
124 return deref_expression(expr);
127 struct expression *symbol_expression(struct symbol *sym)
129 struct expression *expr;
131 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL);
132 expr->symbol = sym;
133 expr->symbol_name = sym->ident;
134 return expr;
137 struct expression *compare_expression(struct expression *left, int op, struct expression *right)
139 struct expression *expr;
141 if (!left || !right)
142 return NULL;
144 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE);
145 expr->op = op;
146 expr->left = left;
147 expr->right = right;
148 return expr;
151 struct expression *gen_string_expression(char *str)
153 struct expression *ret;
154 struct string *string;
155 int len;
157 len = strlen(str) + 1;
158 string = (void *)__alloc_sname(4 + len);
159 string->length = len;
160 string->immutable = 0;
161 memcpy(string->data, str, len);
163 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING);
164 ret->wide = 0;
165 ret->string = string;
167 return ret;
170 struct expression *call_expression(struct expression *fn, struct expression_list *args)
172 struct expression *expr;
174 expr = alloc_tmp_expression(fn->pos, EXPR_CALL);
175 expr->fn = fn;
176 expr->args = args;
178 return expr;
181 static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition)
183 struct expression *ret = NULL;
184 struct token *token, *prev, *end;
185 char *alloc;
187 if (addition[0] == '\0')
188 return base;
190 alloc = alloc_string_newline(addition);
192 token = tokenize_buffer(alloc, strlen(alloc), &end);
193 if (!token)
194 goto free;
195 if (token_type(token) != TOKEN_STREAMBEGIN)
196 goto free;
197 token = token->next;
199 ret = base;
200 while (token_type(token) == TOKEN_SPECIAL &&
201 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
202 prev = token;
203 token = token->next;
204 if (token_type(token) != TOKEN_IDENT)
205 goto free;
206 switch (prev->special) {
207 case SPECIAL_DEREFERENCE:
208 ret = deref_expression(ret);
209 ret = member_expression(ret, '*', token->ident);
210 break;
211 case '.':
212 ret = member_expression(ret, '.', token->ident);
213 break;
214 default:
215 goto free;
217 token = token->next;
220 if (token_type(token) != TOKEN_STREAMEND)
221 goto free;
223 free:
224 free_string(alloc);
226 return ret;
229 static struct expression *gen_expression_from_name_sym_helper(const char *name, struct symbol *sym)
231 struct expression *ret;
232 int skip = 0;
234 if (name[0] == '&' ||
235 name[0] == '*' ||
236 name[0] == '(') {
237 ret = gen_expression_from_name_sym_helper(name + 1, sym);
238 return preop_expression(ret, name[0]);
240 while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-')
241 skip++;
243 return get_expression_from_base_and_str(symbol_expression(sym), name + skip);
246 struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym)
248 struct expression *ret;
250 ret = gen_expression_from_name_sym_helper(name, sym);
251 if (ret) {
252 char *new = expr_to_str(ret);
255 * FIXME: this sometimes changes "foo->bar.a.b->c" into
256 * "foo->bar.a.b.c". I don't know why... :(
259 if (!new || strcmp(name, new) != 0)
260 return NULL;
262 return ret;
265 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
267 struct expression *ret;
268 struct token *token, *prev, *end;
269 const char *p = key;
270 char buf[4095];
271 char *alloc;
272 size_t len;
274 /* The idea is that we can parse either $0->foo or $->foo */
275 if (key[0] != '$')
276 return NULL;
277 p++;
278 while (*p >= '0' && *p <= '9')
279 p++;
280 len = snprintf(buf, sizeof(buf), "%s\n", p);
281 alloc = alloc_string(buf);
283 token = tokenize_buffer(alloc, len, &end);
284 if (!token)
285 return NULL;
286 if (token_type(token) != TOKEN_STREAMBEGIN)
287 return NULL;
288 token = token->next;
290 ret = arg;
291 while (token_type(token) == TOKEN_SPECIAL &&
292 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
293 prev = token;
294 token = token->next;
295 if (token_type(token) != TOKEN_IDENT)
296 return NULL;
297 ret = deref_expression(ret);
298 ret = member_expression(ret,
299 (prev->special == SPECIAL_DEREFERENCE) ? '*' : '.',
300 token->ident);
301 token = token->next;
304 if (token_type(token) != TOKEN_STREAMEND)
305 return NULL;
307 return ret;
310 struct expression *gen_expr_from_param_key(struct expression *expr, int param, const char *key)
312 struct expression *ret = NULL;
313 struct symbol *sym;
314 char *name;
316 name = get_name_sym_from_param_key(expr, param, key, &sym);
317 if (!name || !sym)
318 goto free;
320 ret = gen_expression_from_name_sym(name, sym);
321 free:
322 free_string(name);
323 return ret;
326 bool is_fake_var(struct expression *expr)
328 if (expr && (expr->smatch_flags & Fake))
329 return true;
330 return false;
333 struct expression *fake_variable(struct symbol *type, const char *name)
335 struct symbol *sym, *node;
336 struct expression *ret;
337 struct ident *ident;
339 if (!type)
340 type = &llong_ctype;
342 ident = alloc_ident(name, strlen(name));
344 sym = alloc_symbol(get_cur_pos(), type->type);
345 sym->ident = ident;
346 sym->ctype.base_type = type;
347 sym->ctype.modifiers |= MOD_AUTO;
349 node = alloc_symbol(get_cur_pos(), SYM_NODE);
350 node->ident = ident;
351 node->ctype.base_type = type;
352 node->ctype.modifiers |= MOD_AUTO;
354 ret = symbol_expression(node);
355 ret->smatch_flags |= Fake;
357 return ret;
360 void expr_set_parent_expr(struct expression *expr, struct expression *parent)
362 if (!expr)
363 return;
364 if (parent && parent->smatch_flags & Tmp)
365 return;
367 expr->parent = (unsigned long)parent | 0x1UL;
370 void expr_set_parent_stmt(struct expression *expr, struct statement *parent)
372 if (!expr)
373 return;
374 expr->parent = (unsigned long)parent;
377 struct expression *expr_get_parent_expr(struct expression *expr)
379 struct expression *parent;
381 if (!expr)
382 return NULL;
383 if (!(expr->parent & 0x1UL))
384 return NULL;
386 parent = (struct expression *)(expr->parent & ~0x1UL);
387 if (parent && (parent->smatch_flags & Fake))
388 return expr_get_parent_expr(parent);
389 return parent;
392 struct expression *expr_get_fake_parent_expr(struct expression *expr)
394 struct expression *parent;
396 if (!expr)
397 return NULL;
398 if (!(expr->parent & 0x1UL))
399 return NULL;
401 parent = (struct expression *)(expr->parent & ~0x1UL);
402 if (parent && (parent->smatch_flags & Fake))
403 return parent;
404 return NULL;
407 struct statement *expr_get_parent_stmt(struct expression *expr)
409 if (!expr)
410 return NULL;
411 if (expr->parent & 0x1UL)
412 return NULL;
413 return (struct statement *)expr->parent;
416 struct statement *get_parent_stmt(struct expression *expr)
418 struct expression *tmp;
419 int count = 10;
421 if (!expr)
422 return NULL;
423 while (--count >= 0 && (tmp = expr_get_parent_expr(expr)))
424 expr = tmp;
425 if (!count)
426 return NULL;
428 return expr_get_parent_stmt(expr);