buf_size: fix handling of unknown flexible array sizes
[smatch.git] / dissect.c
blob5f067eb4c55477ec39793c130c47b0c9371ca92e
1 /*
2 * sparse/dissect.c
4 * Started by Oleg Nesterov <oleg@redhat.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "dissect.h"
27 #define U_VOID 0x00
28 #define U_SELF ((1 << U_SHIFT) - 1)
29 #define U_MASK (U_R_VAL | U_W_VAL | U_R_AOF)
31 #define DO_LIST(l__, p__, expr__) \
32 do { \
33 typeof(l__->list[0]) p__; \
34 FOR_EACH_PTR(l__, p__) \
35 expr__; \
36 END_FOR_EACH_PTR(p__); \
37 } while (0)
39 #define DO_2_LIST(l1__,l2__, p1__,p2__, expr__) \
40 do { \
41 typeof(l1__->list[0]) p1__; \
42 typeof(l2__->list[0]) p2__; \
43 PREPARE_PTR_LIST(l1__, p1__); \
44 FOR_EACH_PTR(l2__, p2__) \
45 expr__; \
46 NEXT_PTR_LIST(p1__); \
47 END_FOR_EACH_PTR(p2__); \
48 FINISH_PTR_LIST(p1__); \
49 } while (0)
52 typedef unsigned usage_t;
54 static struct reporter *reporter;
55 static struct symbol *return_type;
57 static void do_sym_list(struct symbol_list *list);
59 static struct symbol
60 *base_type(struct symbol *sym),
61 *do_initializer(struct symbol *type, struct expression *expr),
62 *do_expression(usage_t mode, struct expression *expr),
63 *do_statement(usage_t mode, struct statement *stmt);
65 static inline int is_ptr(struct symbol *type)
67 return type->type == SYM_PTR || type->type == SYM_ARRAY;
70 static inline usage_t u_rval(usage_t mode)
72 return mode & (U_R_VAL | (U_MASK << U_SHIFT))
73 ? U_R_VAL : 0;
76 static inline usage_t u_addr(usage_t mode)
78 return mode = mode & U_MASK
79 ? U_R_AOF | (mode & U_W_AOF) : 0;
82 static usage_t u_lval(struct symbol *type)
84 int wptr = is_ptr(type) && !(type->ctype.modifiers & MOD_CONST);
85 return wptr || type == &bad_ctype
86 ? U_W_AOF | U_R_VAL : U_R_VAL;
89 static usage_t fix_mode(struct symbol *type, usage_t mode)
91 mode &= (U_SELF | (U_SELF << U_SHIFT));
93 switch (type->type) {
94 case SYM_BASETYPE:
95 if (!type->ctype.base_type)
96 break;
97 case SYM_ENUM:
98 case SYM_BITFIELD:
99 if (mode & U_MASK)
100 mode &= U_SELF;
101 default:
103 break; case SYM_FN:
104 if (mode & U_R_VAL)
105 mode |= U_R_AOF;
106 mode &= ~(U_R_VAL | U_W_AOF);
108 break; case SYM_ARRAY:
109 if (mode & (U_MASK << U_SHIFT))
110 mode >>= U_SHIFT;
111 else if (mode != U_W_VAL)
112 mode = u_addr(mode);
115 if (!(mode & U_R_AOF))
116 mode &= ~U_W_AOF;
118 return mode;
121 static inline struct symbol *no_member(struct ident *name)
123 static struct symbol sym = {
124 .type = SYM_BAD,
127 sym.ctype.base_type = &bad_ctype;
128 sym.ident = name;
130 return &sym;
133 static struct symbol *report_member(usage_t mode, struct position *pos,
134 struct symbol *type, struct symbol *mem)
136 struct symbol *ret = mem->ctype.base_type;
138 if (reporter->r_member)
139 reporter->r_member(fix_mode(ret, mode), pos, type, mem);
141 return ret;
144 static void report_implicit(usage_t mode, struct position *pos, struct symbol *type)
146 if (type->type != SYM_STRUCT && type->type != SYM_UNION)
147 return;
149 if (!reporter->r_member)
150 return;
152 if (type->ident != NULL)
153 reporter->r_member(mode, pos, type, NULL);
155 DO_LIST(type->symbol_list, mem,
156 report_implicit(mode, pos, base_type(mem)));
159 static inline struct symbol *expr_symbol(struct expression *expr)
161 struct symbol *sym = expr->symbol;
163 if (!sym) {
164 sym = lookup_symbol(expr->symbol_name, NS_SYMBOL);
166 if (!sym) {
167 sym = alloc_symbol(expr->pos, SYM_BAD);
168 bind_symbol(sym, expr->symbol_name, NS_SYMBOL);
169 sym->ctype.modifiers = MOD_EXTERN;
173 if (!sym->ctype.base_type)
174 sym->ctype.base_type = &bad_ctype;
176 return sym;
179 static struct symbol *report_symbol(usage_t mode, struct expression *expr)
181 struct symbol *sym = expr_symbol(expr);
182 struct symbol *ret = base_type(sym);
184 if (0 && ret->type == SYM_ENUM)
185 return report_member(mode, &expr->pos, ret, expr->symbol);
187 if (reporter->r_symbol)
188 reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym);
190 return ret;
193 static inline struct ident *mk_name(struct ident *root, struct ident *node)
195 char name[256];
197 snprintf(name, sizeof(name), "%.*s:%.*s",
198 root ? root->len : 0, root ? root->name : "",
199 node ? node->len : 0, node ? node->name : "");
201 return built_in_ident(name);
204 static void examine_sym_node(struct symbol *node, struct ident *root)
206 struct symbol *base;
207 struct ident *name;
209 if (node->examined)
210 return;
212 node->examined = 1;
213 name = node->ident;
215 while ((base = node->ctype.base_type) != NULL)
216 switch (base->type) {
217 case SYM_TYPEOF:
218 node->ctype.base_type =
219 do_expression(U_VOID, base->initializer);
220 break;
222 case SYM_ARRAY:
223 do_expression(U_R_VAL, base->array_size);
224 case SYM_PTR: case SYM_FN:
225 node = base;
226 break;
228 case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM:
229 if (base->evaluated)
230 return;
231 if (!base->symbol_list)
232 return;
233 base->evaluated = 1;
235 if (!base->ident && name)
236 base->ident = mk_name(root, name);
237 if (base->ident && reporter->r_symdef)
238 reporter->r_symdef(base);
239 DO_LIST(base->symbol_list, mem,
240 examine_sym_node(mem, base->ident ?: root));
241 default:
242 return;
246 static struct symbol *base_type(struct symbol *sym)
248 if (!sym)
249 return &bad_ctype;
251 if (sym->type == SYM_NODE)
252 examine_sym_node(sym, NULL);
254 return sym->ctype.base_type // builtin_fn_type
255 ?: &bad_ctype;
258 static struct symbol *__lookup_member(struct symbol *type, struct ident *name, int *p_addr)
260 struct symbol *node;
261 int addr = 0;
263 FOR_EACH_PTR(type->symbol_list, node)
264 if (!name) {
265 if (addr == *p_addr)
266 return node;
268 else if (node->ident == NULL) {
269 node = __lookup_member(node->ctype.base_type, name, NULL);
270 if (node)
271 goto found;
273 else if (node->ident == name) {
274 found:
275 if (p_addr)
276 *p_addr = addr;
277 return node;
279 addr++;
280 END_FOR_EACH_PTR(node);
282 return NULL;
285 static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *addr)
287 return __lookup_member(type, name, addr)
288 ?: no_member(name);
291 static struct expression *peek_preop(struct expression *expr, int op)
293 do {
294 if (expr->type != EXPR_PREOP)
295 break;
296 if (expr->op == op)
297 return expr->unop;
298 if (expr->op == '(')
299 expr = expr->unop;
300 else
301 break;
302 } while (expr);
304 return NULL;
307 static struct symbol *do_expression(usage_t mode, struct expression *expr)
309 struct symbol *ret = &int_ctype;
311 again:
312 if (expr) switch (expr->type) {
313 default:
314 warning(expr->pos, "bad expr->type: %d", expr->type);
316 case EXPR_TYPE: // [struct T]; Why ???
317 case EXPR_VALUE:
318 case EXPR_FVALUE:
320 break; case EXPR_LABEL:
321 ret = &label_ctype;
323 break; case EXPR_STRING:
324 ret = &string_ctype;
326 break; case EXPR_STATEMENT:
327 ret = do_statement(mode, expr->statement);
329 break; case EXPR_SIZEOF: case EXPR_ALIGNOF: case EXPR_PTRSIZEOF:
330 do_expression(U_VOID, expr->cast_expression);
332 break; case EXPR_COMMA:
333 do_expression(U_VOID, expr->left);
334 ret = do_expression(mode, expr->right);
336 break; case EXPR_CAST: case EXPR_FORCE_CAST: //case EXPR_IMPLIED_CAST:
337 ret = base_type(expr->cast_type);
338 do_initializer(ret, expr->cast_expression);
340 break; case EXPR_COMPARE: case EXPR_LOGICAL:
341 mode = u_rval(mode);
342 do_expression(mode, expr->left);
343 do_expression(mode, expr->right);
345 break; case EXPR_CONDITIONAL: //case EXPR_SELECT:
346 do_expression(expr->cond_true
347 ? U_R_VAL : U_R_VAL | mode,
348 expr->conditional);
349 ret = do_expression(mode, expr->cond_true);
350 ret = do_expression(mode, expr->cond_false);
352 break; case EXPR_CALL:
353 ret = do_expression(U_R_PTR, expr->fn);
354 if (is_ptr(ret))
355 ret = ret->ctype.base_type;
356 DO_2_LIST(ret->arguments, expr->args, arg, val,
357 do_expression(u_lval(base_type(arg)), val));
358 ret = ret->type == SYM_FN ? base_type(ret)
359 : &bad_ctype;
361 break; case EXPR_ASSIGNMENT:
362 mode |= U_W_VAL | U_R_VAL;
363 if (expr->op == '=')
364 mode &= ~U_R_VAL;
365 ret = do_expression(mode, expr->left);
366 report_implicit(mode, &expr->pos, ret);
367 mode = expr->op == '='
368 ? u_lval(ret) : U_R_VAL;
369 do_expression(mode, expr->right);
371 break; case EXPR_BINOP: {
372 struct symbol *l, *r;
373 mode |= u_rval(mode);
374 l = do_expression(mode, expr->left);
375 r = do_expression(mode, expr->right);
376 if (expr->op != '+' && expr->op != '-')
378 else if (!is_ptr_type(r))
379 ret = l;
380 else if (!is_ptr_type(l))
381 ret = r;
384 break; case EXPR_PREOP: case EXPR_POSTOP: {
385 struct expression *unop = expr->unop;
387 switch (expr->op) {
388 case SPECIAL_INCREMENT:
389 case SPECIAL_DECREMENT:
390 mode |= U_W_VAL | U_R_VAL;
391 default:
392 mode |= u_rval(mode);
393 case '(':
394 ret = do_expression(mode, unop);
396 break; case '&':
397 if ((expr = peek_preop(unop, '*')))
398 goto again;
399 ret = alloc_symbol(unop->pos, SYM_PTR);
400 ret->ctype.base_type =
401 do_expression(u_addr(mode), unop);
403 break; case '*':
404 if ((expr = peek_preop(unop, '&')))
405 goto again;
406 if (mode & (U_MASK << U_SHIFT))
407 mode |= U_R_VAL;
408 mode <<= U_SHIFT;
409 if (mode & (U_R_AOF << U_SHIFT))
410 mode |= U_R_VAL;
411 if (mode & (U_W_VAL << U_SHIFT))
412 mode |= U_W_AOF;
413 ret = do_expression(mode, unop);
414 ret = is_ptr(ret) ? base_type(ret)
415 : &bad_ctype;
419 break; case EXPR_DEREF: {
420 struct symbol *p_type;
421 usage_t p_mode;
423 p_mode = mode & U_SELF;
424 if (!(mode & U_MASK) && (mode & (U_MASK << U_SHIFT)))
425 p_mode = U_R_VAL;
426 p_type = do_expression(p_mode, expr->deref);
428 ret = report_member(mode, &expr->pos, p_type,
429 lookup_member(p_type, expr->member, NULL));
432 break; case EXPR_OFFSETOF: {
433 struct symbol *in = base_type(expr->in);
435 do {
436 if (expr->op == '.') {
437 in = report_member(U_VOID, &expr->pos, in,
438 lookup_member(in, expr->ident, NULL));
439 } else {
440 do_expression(U_R_VAL, expr->index);
441 in = in->ctype.base_type;
443 } while ((expr = expr->down));
446 break; case EXPR_SYMBOL:
447 ret = report_symbol(mode, expr);
450 return ret;
453 static void do_asm_xputs(usage_t mode, struct expression_list *xputs)
455 int nr = 0;
457 DO_LIST(xputs, expr,
458 if (++nr % 3 == 0)
459 do_expression(U_W_AOF | mode, expr));
462 static struct symbol *do_statement(usage_t mode, struct statement *stmt)
464 struct symbol *ret = &void_ctype;
466 if (stmt) switch (stmt->type) {
467 default:
468 warning(stmt->pos, "bad stmt->type: %d", stmt->type);
470 case STMT_NONE:
471 case STMT_RANGE:
472 case STMT_CONTEXT:
474 break; case STMT_DECLARATION:
475 do_sym_list(stmt->declaration);
477 break; case STMT_EXPRESSION:
478 ret = do_expression(mode, stmt->expression);
480 break; case STMT_RETURN:
481 do_expression(u_lval(return_type), stmt->expression);
483 break; case STMT_ASM:
484 do_expression(U_R_VAL, stmt->asm_string);
485 do_asm_xputs(U_W_VAL, stmt->asm_outputs);
486 do_asm_xputs(U_R_VAL, stmt->asm_inputs);
488 break; case STMT_COMPOUND: {
489 int count;
491 count = statement_list_size(stmt->stmts);
492 DO_LIST(stmt->stmts, st,
493 ret = do_statement(--count ? U_VOID : mode, st));
496 break; case STMT_ITERATOR:
497 do_sym_list(stmt->iterator_syms);
498 do_statement(U_VOID, stmt->iterator_pre_statement);
499 do_expression(U_R_VAL, stmt->iterator_pre_condition);
500 do_statement(U_VOID, stmt->iterator_post_statement);
501 do_statement(U_VOID, stmt->iterator_statement);
502 do_expression(U_R_VAL, stmt->iterator_post_condition);
504 break; case STMT_IF:
505 do_expression(U_R_VAL, stmt->if_conditional);
506 do_statement(U_VOID, stmt->if_true);
507 do_statement(U_VOID, stmt->if_false);
509 break; case STMT_SWITCH:
510 do_expression(U_R_VAL, stmt->switch_expression);
511 do_statement(U_VOID, stmt->switch_statement);
513 break; case STMT_CASE:
514 do_expression(U_R_VAL, stmt->case_expression);
515 do_expression(U_R_VAL, stmt->case_to);
516 do_statement(U_VOID, stmt->case_statement);
518 break; case STMT_GOTO:
519 do_expression(U_R_PTR, stmt->goto_expression);
521 break; case STMT_LABEL:
522 do_statement(mode, stmt->label_statement);
526 return ret;
529 static struct symbol *do_initializer(struct symbol *type, struct expression *expr)
531 struct symbol *m_type;
532 struct expression *m_expr;
533 int m_addr;
535 if (expr) switch (expr->type) {
536 default:
537 do_expression(u_lval(type), expr);
539 break; case EXPR_INDEX:
540 do_initializer(base_type(type), expr->idx_expression);
542 break; case EXPR_INITIALIZER:
543 m_addr = 0;
544 FOR_EACH_PTR(expr->expr_list, m_expr) {
545 if (type->type == SYM_ARRAY) {
546 m_type = base_type(type);
547 if (m_expr->type == EXPR_INDEX)
548 m_expr = m_expr->idx_expression;
549 } else {
550 int *m_atop = &m_addr;
552 m_type = type;
553 while (m_expr->type == EXPR_IDENTIFIER) {
554 m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
555 lookup_member(m_type, m_expr->expr_ident, m_atop));
556 m_expr = m_expr->ident_expression;
557 m_atop = NULL;
560 if (m_atop) {
561 m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
562 lookup_member(m_type, NULL, m_atop));
565 if (m_expr->type != EXPR_INITIALIZER)
566 report_implicit(U_W_VAL, &m_expr->pos, m_type);
568 do_initializer(m_type, m_expr);
569 m_addr++;
570 } END_FOR_EACH_PTR(m_expr);
573 return type;
576 static inline struct symbol *do_symbol(struct symbol *sym)
578 struct symbol *type;
580 type = base_type(sym);
582 if (reporter->r_symdef)
583 reporter->r_symdef(sym);
585 switch (type->type) {
586 default:
587 if (!sym->initializer)
588 break;
589 if (reporter->r_symbol)
590 reporter->r_symbol(U_W_VAL, &sym->pos, sym);
591 do_initializer(type, sym->initializer);
593 break; case SYM_FN:
594 do_sym_list(type->arguments);
595 return_type = base_type(type);
596 do_statement(U_VOID, sym->ctype.modifiers & MOD_INLINE
597 ? type->inline_stmt
598 : type->stmt);
601 return type;
604 static void do_sym_list(struct symbol_list *list)
606 DO_LIST(list, sym, do_symbol(sym));
609 void dissect(struct symbol_list *list, struct reporter *rep)
611 reporter = rep;
612 do_sym_list(list);