flow: don't parse inline functions which aren't interesting
[smatch.git] / smatch_expressions.c
blobaafc213cb56c1328cd33818db3f0c88f19e78f6f
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;
28 expr = __alloc_tmp_expression(0);
29 expr->smatch_flags |= Fake;
30 expr->type = type;
31 expr->pos = pos;
32 return expr;
35 void free_tmp_expressions(void)
37 clear_tmp_expression_alloc();
40 struct expression *zero_expr(void)
42 struct expression *zero;
44 zero = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
45 zero->value = 0;
46 zero->ctype = &int_ctype;
47 return zero;
50 struct expression *value_expr(long long val)
52 struct expression *expr;
54 if (!val)
55 return zero_expr();
57 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE);
58 expr->value = val;
59 expr->ctype = &llong_ctype;
60 return expr;
63 struct expression *member_expression(struct expression *deref, int op, struct ident *member)
65 struct expression *expr;
67 expr = alloc_tmp_expression(deref->pos, EXPR_DEREF);
68 expr->op = op;
69 expr->deref = deref;
70 expr->member = member;
71 expr->member_offset = -1;
72 return expr;
75 struct expression *deref_expression(struct expression *expr)
77 struct expression *preop;
79 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP);
80 preop->unop = expr;
81 preop->op = '*';
82 return preop;
85 struct expression *assign_expression(struct expression *left, int op, struct expression *right)
87 struct expression *expr;
89 /* FIXME: make this a tmp expression. */
90 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT);
91 expr->op = op;
92 expr->left = left;
93 expr->right = right;
94 return expr;
97 struct expression *binop_expression(struct expression *left, int op, struct expression *right)
99 struct expression *expr;
101 expr = alloc_tmp_expression(right->pos, EXPR_BINOP);
102 expr->op = op;
103 expr->left = left;
104 expr->right = right;
105 return expr;
108 struct expression *array_element_expression(struct expression *array, struct expression *offset)
110 struct expression *expr;
112 expr = binop_expression(array, '+', offset);
113 return deref_expression(expr);
116 struct expression *symbol_expression(struct symbol *sym)
118 struct expression *expr;
120 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL);
121 expr->symbol = sym;
122 expr->symbol_name = sym->ident;
123 return expr;
126 struct expression *compare_expression(struct expression *left, int op, struct expression *right)
128 struct expression *expr;
130 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE);
131 expr->op = op;
132 expr->left = left;
133 expr->right = right;
134 return expr;
137 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
139 struct expression *ret;
140 struct token *token, *end;
141 const char *p = key;
142 char buf[4095];
143 char *alloc;
144 size_t len;
146 /* The idea is that we can parse either $0->foo or $->foo */
147 if (key[0] != '$')
148 return NULL;
149 p++;
150 while (*p >= '0' && *p <= '9')
151 p++;
152 len = snprintf(buf, sizeof(buf), "%s\n", p);
153 alloc = alloc_string(buf);
155 token = tokenize_buffer(alloc, len, &end);
156 if (!token)
157 return NULL;
158 if (token_type(token) != TOKEN_STREAMBEGIN)
159 return NULL;
160 token = token->next;
162 ret = arg;
163 while (token_type(token) == TOKEN_SPECIAL &&
164 token->special == SPECIAL_DEREFERENCE) {
165 token = token->next;
166 if (token_type(token) != TOKEN_IDENT)
167 return NULL;
168 ret = deref_expression(ret);
169 ret = member_expression(ret, '*', token->ident);
170 token = token->next;
173 if (token_type(token) != TOKEN_STREAMEND)
174 return NULL;
176 return ret;
179 void expr_set_parent_expr(struct expression *expr, struct expression *parent)
181 if (!expr)
182 return;
183 if (parent->smatch_flags & Fake)
184 return;
186 expr->parent = (unsigned long)parent | 0x1UL;
189 void expr_set_parent_stmt(struct expression *expr, struct statement *parent)
191 if (!expr)
192 return;
193 expr->parent = (unsigned long)parent;
196 struct expression *expr_get_parent_expr(struct expression *expr)
198 if (!expr)
199 return NULL;
200 if (!(expr->parent & 0x1UL))
201 return NULL;
202 return (struct expression *)(expr->parent & ~0x1UL);
205 struct statement *expr_get_parent_stmt(struct expression *expr)
207 if (!expr)
208 return NULL;
209 if (expr->parent & 0x1UL)
210 return NULL;
211 return (struct statement *)expr->parent;