expressions: just allocate zero_expr() fresh every time
[smatch.git] / smatch_expressions.c
blob4c7bde808c30eefb74d39d993e0af6d5a8e6a0e1
1 #include "smatch.h"
2 #include "smatch_extra.h"
4 __ALLOCATOR(struct expression, "temporary expr", tmp_expression);
6 static struct position get_cur_pos(void)
8 static struct position pos;
9 static struct position none;
10 struct expression *expr;
11 struct statement *stmt;
13 expr = last_ptr_list((struct ptr_list *)big_expression_stack);
14 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
15 if (expr)
16 pos = expr->pos;
17 else if (stmt)
18 pos = stmt->pos;
19 else
20 pos = none;
21 return pos;
24 struct expression *alloc_tmp_expression(struct position pos, int type)
26 struct expression *expr = __alloc_tmp_expression(0);
27 expr->type = type;
28 expr->pos = pos;
29 return expr;
32 void free_tmp_expressions(void)
34 clear_tmp_expression_alloc();
37 struct expression *zero_expr(void)
39 struct expression *zero;
41 zero = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
42 zero->value = 0;
43 zero->ctype = &int_ctype;
44 return zero;
47 struct expression *value_expr(long long val)
49 struct expression *expr;
51 if (!val)
52 return zero_expr();
54 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
55 expr->value = val;
56 expr->ctype = &llong_ctype;
57 return expr;
60 struct expression *member_expression(struct expression *deref, int op, struct ident *member)
62 struct expression *expr;
64 expr = alloc_tmp_expression(deref->pos, EXPR_DEREF);
65 expr->op = op;
66 expr->deref = deref;
67 expr->member = member;
68 expr->member_offset = -1;
69 return expr;
72 struct expression *deref_expression(struct expression *expr)
74 struct expression *preop;
76 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP);
77 preop->unop = expr;
78 preop->op = '*';
79 return preop;
82 struct expression *assign_expression(struct expression *left, struct expression *right)
84 struct expression *expr;
86 expr = alloc_tmp_expression(right->pos, EXPR_ASSIGNMENT);
87 expr->op = '=';
88 expr->left = left;
89 expr->right = right;
90 return expr;
93 struct expression *binop_expression(struct expression *left, int op, struct expression *right)
95 struct expression *expr;
97 expr = alloc_tmp_expression(right->pos, EXPR_BINOP);
98 expr->op = op;
99 expr->left = left;
100 expr->right = right;
101 return expr;
104 struct expression *array_element_expression(struct expression *array, struct expression *offset)
106 struct expression *expr;
108 expr = binop_expression(array, '+', offset);
109 return deref_expression(expr);
112 struct expression *symbol_expression(struct symbol *sym)
114 struct expression *expr;
116 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL);
117 expr->symbol = sym;
118 expr->symbol_name = sym->ident;
119 return expr;
122 struct expression *compare_expression(struct expression *left, int op, struct expression *right)
124 struct expression *expr;
126 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE);
127 expr->op = op;
128 expr->left = left;
129 expr->right = right;
130 return expr;
133 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
135 struct expression *ret;
136 struct token *token, *end;
137 const char *p = key;
138 char buf[4095];
139 char *alloc;
140 size_t len;
142 /* The idea is that we can parse either $0->foo or $->foo */
143 if (key[0] != '$')
144 return NULL;
145 p++;
146 while (*p >= '0' && *p <= '9')
147 p++;
148 len = snprintf(buf, sizeof(buf), "%s\n", p);
149 alloc = alloc_string(buf);
151 token = tokenize_buffer(alloc, len, &end);
152 if (!token)
153 return NULL;
154 if (token_type(token) != TOKEN_STREAMBEGIN)
155 return NULL;
156 token = token->next;
158 ret = arg;
159 while (token_type(token) == TOKEN_SPECIAL &&
160 token->special == SPECIAL_DEREFERENCE) {
161 token = token->next;
162 if (token_type(token) != TOKEN_IDENT)
163 return NULL;
164 ret = deref_expression(ret);
165 ret = member_expression(ret, '*', token->ident);
166 token = token->next;
169 if (token_type(token) != TOKEN_STREAMEND)
170 return NULL;
172 return ret;
175 void expr_set_parent_expr(struct expression *expr, struct expression *parent)
177 if (!expr)
178 return;
180 expr->parent = (unsigned long)parent | 0x1UL;
183 void expr_set_parent_stmt(struct expression *expr, struct statement *parent)
185 if (!expr)
186 return;
187 expr->parent = (unsigned long)parent;
190 struct expression *expr_get_parent_expr(struct expression *expr)
192 if (!expr)
193 return NULL;
194 if (!(expr->parent & 0x1UL))
195 return NULL;
196 return (struct expression *)(expr->parent & ~0x1UL);
199 struct statement *expr_get_parent_stmt(struct expression *expr)
201 if (!expr)
202 return NULL;
203 if (expr->parent & 0x1UL)
204 return NULL;
205 return (struct statement *)expr->parent;