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
);
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
;
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
);
47 zero
->ctype
= &int_ctype
;
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
;
61 struct expression
*value_expr(long long val
)
63 struct expression
*expr
;
68 expr
= alloc_tmp_expression(get_cur_pos(), EXPR_VALUE
);
70 expr
->ctype
= &llong_ctype
;
74 static struct expression
*symbol_expression_helper(struct symbol
*sym
, bool perm
)
76 struct expression
*expr
;
79 expr
= alloc_expression(sym
->pos
, EXPR_SYMBOL
);
81 expr
= alloc_tmp_expression(sym
->pos
, EXPR_SYMBOL
);
83 expr
->symbol_name
= sym
->ident
;
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
;
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
);
109 expr
->member
= member
;
110 expr
->member_offset
= -1;
114 struct expression
*preop_expression(struct expression
*expr
, int op
)
116 struct expression
*preop
;
118 preop
= alloc_tmp_expression(expr
->pos
, EXPR_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
;
146 /* FIXME: make this a tmp expression. */
147 expr
= alloc_expression(right
->pos
, EXPR_ASSIGNMENT
);
154 struct expression
*assign_expression_perm(struct expression
*left
, int op
, struct expression
*right
)
156 struct expression
*expr
;
161 expr
= alloc_expression(right
->pos
, EXPR_ASSIGNMENT
);
168 struct expression
*create_fake_assign(const char *name
, struct symbol
*type
, struct expression
*right
)
170 struct expression
*left
, *assign
;
176 type
= get_type(right
);
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
);
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
);
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
;
221 expr
= alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE
);
228 struct expression
*alloc_expression_stmt_perm(struct statement
*last_stmt
)
230 struct expression
*expr
;
235 expr
= alloc_tmp_expression(last_stmt
->pos
, EXPR_STATEMENT
);
236 expr
->statement
= last_stmt
;
241 struct expression
*gen_string_expression(char *str
)
243 struct expression
*ret
;
244 struct string
*string
;
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
);
255 ret
->string
= string
;
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
);
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
;
277 if (addition
[0] == '\0')
280 alloc
= alloc_string_newline(addition
);
282 token
= tokenize_buffer(alloc
, strlen(alloc
), &end
);
285 if (token_type(token
) != TOKEN_STREAMBEGIN
)
290 while (token_type(token
) == TOKEN_SPECIAL
&&
291 (token
->special
== SPECIAL_DEREFERENCE
|| token
->special
== '.')) {
294 if (token_type(token
) != TOKEN_IDENT
)
296 switch (prev
->special
) {
297 case SPECIAL_DEREFERENCE
:
298 ret
= deref_expression(ret
);
299 ret
= member_expression(ret
, '*', token
->ident
);
302 ret
= member_expression(ret
, '.', token
->ident
);
310 if (token_type(token
) != TOKEN_STREAMEND
)
319 static struct expression
*gen_expression_from_name_sym_helper(const char *name
, struct symbol
*sym
)
321 struct expression
*ret
;
327 if (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
] != '-')
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
);
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)
358 struct expression
*gen_expression_from_key(struct expression
*arg
, const char *key
)
360 struct expression
*ret
;
361 struct token
*token
, *end
;
369 if (strcmp(key
, "$") == 0)
372 if (strcmp(key
, "*$") == 0) {
373 if (arg
->type
== EXPR_PREOP
&&
375 return strip_expr(arg
->unop
);
376 return deref_expression(arg
);
379 /* The idea is that we can parse either $0->foo or $->foo */
383 while (*p
>= '0' && *p
<= '9')
385 len
= snprintf(buf
, sizeof(buf
), "%s\n", p
);
386 alloc
= alloc_string(buf
);
388 token
= tokenize_buffer(alloc
, len
, &end
);
391 if (token_type(token
) != TOKEN_STREAMBEGIN
)
396 while (token_type(token
) == TOKEN_SPECIAL
&&
397 (token
->special
== SPECIAL_DEREFERENCE
|| token
->special
== '.')) {
398 if (token
->special
== SPECIAL_DEREFERENCE
)
403 if (cnt
++ == 0 && ret
->type
== EXPR_PREOP
&& ret
->op
== '&') {
404 ret
= strip_expr(ret
->unop
);
409 if (token_type(token
) != TOKEN_IDENT
)
413 ret
= deref_expression(ret
);
414 ret
= member_expression(ret
, star
? '*' : '.', token
->ident
);
418 if (token_type(token
) != TOKEN_STREAMEND
)
424 struct expression
*gen_expr_from_param_key(struct expression
*expr
, int param
, const char *key
)
426 struct expression
*call
, *arg
;
432 while (call
->type
== EXPR_ASSIGNMENT
)
433 call
= strip_expr(call
->right
);
434 if (call
->type
!= EXPR_CALL
)
438 if (expr
->type
!= EXPR_ASSIGNMENT
)
442 arg
= get_argument_from_call_expr(call
->args
, param
);
447 return gen_expression_from_key(arg
, key
);
450 bool is_fake_var(struct expression
*expr
)
452 if (expr
&& (expr
->smatch_flags
& Fake
))
457 bool is_fake_var_assign(struct expression
*expr
)
459 struct expression
*left
;
462 if (!expr
|| expr
->type
!= EXPR_ASSIGNMENT
|| expr
->op
!= '=')
465 if (left
->type
!= EXPR_SYMBOL
)
467 if (!is_fake_var(left
))
471 if (strncmp(sym
->ident
->name
, "__fake_", 7) != 0)
476 static struct expression
*fake_variable_helper(struct symbol
*type
, const char *name
, bool perm
)
478 struct symbol
*sym
, *node
;
479 struct expression
*ret
;
485 ident
= alloc_ident(name
, strlen(name
));
487 sym
= alloc_symbol(get_cur_pos(), type
->type
);
489 sym
->ctype
.base_type
= type
;
490 sym
->ctype
.modifiers
|= MOD_AUTO
;
492 node
= alloc_symbol(get_cur_pos(), SYM_NODE
);
494 node
->ctype
.base_type
= type
;
495 node
->ctype
.modifiers
|= MOD_AUTO
;
498 ret
= symbol_expression_helper(node
, true);
500 ret
= symbol_expression(node
);
502 ret
->smatch_flags
|= Fake
;
507 struct expression
*fake_variable(struct symbol
*type
, const char *name
)
509 return fake_variable_helper(type
, name
, false);
512 struct expression
*fake_variable_perm(struct symbol
*type
, const char *name
)
514 return fake_variable_helper(type
, name
, true);
517 void expr_set_parent_expr(struct expression
*expr
, struct expression
*parent
)
519 struct expression
*prev
;
521 if (!expr
|| !parent
)
524 prev
= expr_get_parent_expr(expr
);
528 if (parent
&& parent
->smatch_flags
& Tmp
)
531 expr
->parent
= (unsigned long)parent
| 0x1UL
;
534 void expr_set_parent_stmt(struct expression
*expr
, struct statement
*parent
)
538 expr
->parent
= (unsigned long)parent
;
541 struct expression
*expr_get_parent_expr(struct expression
*expr
)
543 struct expression
*parent
;
547 if (!(expr
->parent
& 0x1UL
))
550 parent
= (struct expression
*)(expr
->parent
& ~0x1UL
);
551 if (parent
&& (parent
->smatch_flags
& Fake
))
552 return expr_get_parent_expr(parent
);
556 struct expression
*expr_get_fake_parent_expr(struct expression
*expr
)
558 struct expression
*parent
;
562 if (!(expr
->parent
& 0x1UL
))
565 parent
= (struct expression
*)(expr
->parent
& ~0x1UL
);
566 if (parent
&& (parent
->smatch_flags
& Fake
))
571 struct statement
*expr_get_parent_stmt(struct expression
*expr
)
573 struct expression
*parent
;
577 if (expr
->parent
& 0x1UL
) {
578 parent
= (struct expression
*)(expr
->parent
& ~0x1UL
);
579 if (parent
->smatch_flags
& Fake
)
580 return expr_get_parent_stmt(parent
);
583 return (struct statement
*)expr
->parent
;
586 struct statement
*get_parent_stmt(struct expression
*expr
)
588 struct expression
*tmp
;
593 while (--count
> 0 && (tmp
= expr_get_parent_expr(expr
)))
598 return expr_get_parent_stmt(expr
);