12166 resync smatch to 0.6.1-rc1-il-3
1 #include "smatch.h" 2 #include "smatch_extra.h" 3 4 DECLARE_ALLOCATOR(sname); 5 __ALLOCATOR(struct expression, "temporary expr", tmp_expression); 6 7 static struct position get_cur_pos(void) 8 { 9 static struct position pos; 10 static struct position none; 11 struct expression *expr; 12 struct statement *stmt; 13 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; 23 } 24 25 struct expression *alloc_tmp_expression(struct position pos, int type) 26 { 27 struct expression *expr; 28 29 expr = __alloc_tmp_expression(0); 30 expr->smatch_flags |= Fake; 31 expr->type = type; 32 expr->pos = pos; 33 return expr; 34 } 35 36 void free_tmp_expressions(void) 37 { 38 clear_tmp_expression_alloc(); 39 } 40 41 struct expression *zero_expr(void) 42 { 43 struct expression *zero; 44 45 zero = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE); 46 zero->value = 0; 47 zero->ctype = &int_ctype; 48 return zero; 49 } 50 51 struct expression *value_expr(long long val) 52 { 53 struct expression *expr; 54 55 if (!val) 56 return zero_expr(); 57 58 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE); 59 expr->value = val; 60 expr->ctype = &llong_ctype; 61 return expr; 62 } 63 64 struct expression *member_expression(struct expression *deref, int op, struct ident *member) 65 { 66 struct expression *expr; 67 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; 74 } 75 76 struct expression *preop_expression(struct expression *expr, int op) 77 { 78 struct expression *preop; 79 80 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP); 81 preop->unop = expr; 82 preop->op = op; 83 return preop; 84 } 85 86 struct expression *deref_expression(struct expression *expr) 87 { 88 return preop_expression(expr, '*'); 89 } 90 91 struct expression *assign_expression(struct expression *left, int op, struct expression *right) 92 { 93 struct expression *expr; 94 95 if (!right) 96 return NULL; 97 98 /* FIXME: make this a tmp expression. */ 99 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT); 100 expr->op = op; 101 expr->left = left; 102 expr->right = right; 103 return expr; 104 } 105 106 struct expression *binop_expression(struct expression *left, int op, struct expression *right) 107 { 108 struct expression *expr; 109 110 expr = alloc_tmp_expression(right->pos, EXPR_BINOP); 111 expr->op = op; 112 expr->left = left; 113 expr->right = right; 114 return expr; 115 } 116 117 struct expression *array_element_expression(struct expression *array, struct expression *offset) 118 { 119 struct expression *expr; 120 121 expr = binop_expression(array, '+', offset); 122 return deref_expression(expr); 123 } 124 125 struct expression *symbol_expression(struct symbol *sym) 126 { 127 struct expression *expr; 128 129 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL); 130 expr->symbol = sym; 131 expr->symbol_name = sym->ident; 132 return expr; 133 } 134 135 struct expression *compare_expression(struct expression *left, int op, struct expression *right) 136 { 137 struct expression *expr; 138 139 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE); 140 expr->op = op; 141 expr->left = left; 142 expr->right = right; 143 return expr; 144 } 145 146 struct expression *string_expression(char *str) 147 { 148 struct expression *ret; 149 struct string *string; 150 int len; 151 152 len = strlen(str) + 1; 153 string = (void *)__alloc_sname(4 + len); 154 string->length = len; 155 string->immutable = 0; 156 memcpy(string->data, str, len); 157 158 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING); 159 ret->wide = 0; 160 ret->string = string; 161 162 return ret; 163 } 164 165 static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition) 166 { 167 struct expression *ret = NULL; 168 struct token *token, *prev, *end; 169 char *alloc; 170 171 if (addition[0] == '\0') 172 return base; 173 174 alloc = alloc_string_newline(addition); 175 176 token = tokenize_buffer(alloc, strlen(alloc), &end); 177 if (!token) 178 goto free; 179 if (token_type(token) != TOKEN_STREAMBEGIN) 180 goto free; 181 token = token->next; 182 183 ret = base; 184 while (token_type(token) == TOKEN_SPECIAL && 185 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) { 186 prev = token; 187 token = token->next; 188 if (token_type(token) != TOKEN_IDENT) 189 goto free; 190 switch (prev->special) { 191 case SPECIAL_DEREFERENCE: 192 ret = deref_expression(ret); 193 ret = member_expression(ret, '*', token->ident); 194 break; 195 case '.': 196 ret = member_expression(ret, '.', token->ident); 197 break; 198 default: 199 goto free; 200 } 201 token = token->next; 202 } 203 204 if (token_type(token) != TOKEN_STREAMEND) 205 goto free; 206 207 free: 208 free_string(alloc); 209 210 return ret; 211 } 212 213 struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym) 214 { 215 struct expression *base; 216 int skip = 0; 217 struct expression *ret; 218 219 if (!name || !sym) 220 return NULL; 221 222 base = symbol_expression(sym); 223 while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-') 224 skip++; 225 226 ret = get_expression_from_base_and_str(base, name + skip); 227 if (ret) { 228 char *new = expr_to_str(ret); 229 230 /* 231 * FIXME: this sometimes changes "foo->bar.a.b->c" into 232 * "foo->bar.a.b.c". I don't know why... :( 233 * 234 */ 235 if (!new || strcmp(name, new) != 0) 236 return NULL; 237 } 238 return ret; 239 } 240 241 struct expression *gen_expression_from_key(struct expression *arg, const char *key) 242 { 243 struct expression *ret; 244 struct token *token, *prev, *end; 245 const char *p = key; 246 char buf[4095]; 247 char *alloc; 248 size_t len; 249 250 /* The idea is that we can parse either $0->foo or $->foo */ 251 if (key[0] != '$') 252 return NULL; 253 p++; 254 while (*p >= '0' && *p <= '9') 255 p++; 256 len = snprintf(buf, sizeof(buf), "%s\n", p); 257 alloc = alloc_string(buf); 258 259 token = tokenize_buffer(alloc, len, &end); 260 if (!token) 261 return NULL; 262 if (token_type(token) != TOKEN_STREAMBEGIN) 263 return NULL; 264 token = token->next; 265 266 ret = arg; 267 while (token_type(token) == TOKEN_SPECIAL && 268 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) { 269 prev = token; 270 token = token->next; 271 if (token_type(token) != TOKEN_IDENT) 272 return NULL; 273 ret = deref_expression(ret); 274 ret = member_expression(ret, 275 (prev->special == SPECIAL_DEREFERENCE) ? '*' : '.', 276 token->ident); 277 token = token->next; 278 } 279 280 if (token_type(token) != TOKEN_STREAMEND) 281 return NULL; 282 283 return ret; 284 } 285 286 void expr_set_parent_expr(struct expression *expr, struct expression *parent) 287 { 288 if (!expr) 289 return; 290 if (parent->smatch_flags & Fake) 291 return; 292 293 expr->parent = (unsigned long)parent | 0x1UL; 294 } 295 296 void expr_set_parent_stmt(struct expression *expr, struct statement *parent) 297 { 298 if (!expr) 299 return; 300 expr->parent = (unsigned long)parent; 301 } 302 303 struct expression *expr_get_parent_expr(struct expression *expr) 304 { 305 if (!expr) 306 return NULL; 307 if (!(expr->parent & 0x1UL)) 308 return NULL; 309 return (struct expression *)(expr->parent & ~0x1UL); 310 } 311 312 struct statement *expr_get_parent_stmt(struct expression *expr) 313 { 314 if (!expr) 315 return NULL; 316 if (expr->parent & 0x1UL) 317 return NULL; 318 return (struct statement *)expr->parent; 319 } 320 --- EOF ---