states: rename unreachable() to is_unreachable()
[smatch.git] / dissect.c
blob9419c5931fbbf6946b4692044c8193733ea2c888
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 struct symbol *dissect_ctx;
56 static struct reporter *reporter;
58 static void do_sym_list(struct symbol_list *list);
60 static struct symbol
61 *base_type(struct symbol *sym),
62 *do_initializer(struct symbol *type, struct expression *expr),
63 *do_expression(usage_t mode, struct expression *expr),
64 *do_statement(usage_t mode, struct statement *stmt);
66 static inline int is_ptr(struct symbol *type)
68 return type->type == SYM_PTR || type->type == SYM_ARRAY;
71 static inline usage_t u_rval(usage_t mode)
73 return mode & (U_R_VAL | (U_MASK << U_SHIFT))
74 ? U_R_VAL : 0;
77 static inline usage_t u_addr(usage_t mode)
79 return mode = mode & U_MASK
80 ? U_R_AOF | (mode & U_W_AOF) : 0;
83 static usage_t u_lval(struct symbol *type)
85 int wptr = is_ptr(type) && !(type->ctype.modifiers & MOD_CONST);
86 return wptr || type == &bad_ctype
87 ? U_W_AOF | U_R_VAL : U_R_VAL;
90 static usage_t fix_mode(struct symbol *type, usage_t mode)
92 mode &= (U_SELF | (U_SELF << U_SHIFT));
94 switch (type->type) {
95 case SYM_BASETYPE:
96 if (!type->ctype.base_type)
97 break;
98 case SYM_ENUM:
99 case SYM_BITFIELD:
100 if (mode & U_MASK)
101 mode &= U_SELF;
102 default:
104 break; case SYM_FN:
105 if (mode & U_R_VAL)
106 mode |= U_R_AOF;
107 mode &= ~(U_R_VAL | U_W_AOF);
109 break; case SYM_ARRAY:
110 if (mode & (U_MASK << U_SHIFT))
111 mode >>= U_SHIFT;
112 else if (mode != U_W_VAL)
113 mode = u_addr(mode);
116 if (!(mode & U_R_AOF))
117 mode &= ~U_W_AOF;
119 return mode;
122 static struct symbol *report_member(usage_t mode, struct position *pos,
123 struct symbol *type, struct symbol *mem)
125 struct symbol *ret = mem->ctype.base_type;
127 if (mem->ident || mem->type == SYM_BAD)
128 reporter->r_member(fix_mode(ret, mode), pos, type, mem);
130 return ret;
133 static void report_implicit(usage_t mode, struct position *pos, struct symbol *type)
135 if (type->type != SYM_STRUCT && type->type != SYM_UNION)
136 return;
138 if (type->ident != NULL)
139 reporter->r_member(mode, pos, type, NULL);
141 DO_LIST(type->symbol_list, mem,
142 report_implicit(mode, pos, base_type(mem)));
145 static inline struct symbol *expr_symbol(struct expression *expr)
147 struct symbol *sym = expr->symbol;
149 if (!sym) {
150 sym = lookup_symbol(expr->symbol_name, NS_SYMBOL);
152 if (!sym) {
153 sym = alloc_symbol(expr->pos, SYM_BAD);
154 bind_symbol(sym, expr->symbol_name, NS_SYMBOL);
155 sym->kind = expr->op ?: 'v'; /* see EXPR_CALL */
159 if (!sym->ctype.base_type)
160 sym->ctype.base_type = &bad_ctype;
162 return sym;
165 static struct symbol *report_symbol(usage_t mode, struct expression *expr)
167 struct symbol *sym = expr_symbol(expr);
168 struct symbol *ret = base_type(sym);
170 if (0 && ret->type == SYM_ENUM)
171 return report_member(mode, &expr->pos, ret, expr->symbol);
173 reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym);
175 return ret;
178 static bool deanon(struct symbol *base, struct ident *node, struct symbol *parent)
180 struct ident *pi = parent ? parent->ident : NULL;
181 char name[256];
183 if (!node) {
184 base->ident = pi;
185 return false;
188 snprintf(name, sizeof(name), "%.*s:%.*s",
189 pi ? pi->len : 0, pi ? pi->name : NULL, node->len, node->name);
191 base->ident = built_in_ident(name);
192 return true;
195 static void report_memdef(struct symbol *sym, struct symbol *mem)
197 mem->kind = 'm';
198 if (sym && mem->ident)
199 reporter->r_memdef(sym, mem);
202 static void examine_sym_node(struct symbol *node, struct symbol *parent)
204 struct ident *name = node->ident;
205 struct symbol *base, *dctx;
207 if (node->visited)
208 return;
209 node->visited = 1;
210 node->kind = 'v';
212 while ((base = node->ctype.base_type) != NULL)
213 switch (base->type) {
214 case SYM_TYPEOF:
215 case SYM_TYPEOF_UNQUAL:
216 node->ctype.base_type =
217 do_expression(U_VOID, base->initializer);
218 break;
220 case SYM_ARRAY:
221 do_expression(U_R_VAL, base->array_size);
222 case SYM_PTR:
223 node = base;
224 break;
226 case SYM_FN:
227 node->kind = 'f';
228 node = base;
229 break;
231 case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM:
232 if (base->inspected)
233 return;
234 base->inspected = 1;
235 base->kind = 's';
237 if (!base->symbol_list)
238 return;
240 dctx = dissect_ctx;
241 if (toplevel(base->scope))
242 dissect_ctx = NULL;
244 if (base->ident || deanon(base, name, parent))
245 reporter->r_symdef(base);
247 if (base->ident)
248 parent = base;
249 DO_LIST(base->symbol_list, mem,
250 examine_sym_node(mem, parent);
251 report_memdef(parent, mem));
252 dissect_ctx = dctx;
253 default:
254 return;
258 static struct symbol *base_type(struct symbol *sym)
260 if (!sym)
261 return &bad_ctype;
263 if (sym->type == SYM_NODE)
264 examine_sym_node(sym, NULL);
266 return sym->ctype.base_type // builtin_fn_type
267 ?: &bad_ctype;
270 static struct symbol *__lookup_member(struct symbol *type, struct ident *name, int *p_addr)
272 struct symbol *node;
273 int addr = 0;
275 FOR_EACH_PTR(type->symbol_list, node)
276 if (!name) {
277 if (addr == *p_addr)
278 return node;
280 else if (node->ident == NULL) {
281 node = __lookup_member(node->ctype.base_type, name, NULL);
282 if (node)
283 goto found;
285 else if (node->ident == name) {
286 found:
287 if (p_addr)
288 *p_addr = addr;
289 return node;
291 addr++;
292 END_FOR_EACH_PTR(node);
294 return NULL;
297 static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *addr)
299 struct symbol *mem = __lookup_member(type, name, addr);
301 if (!mem) {
302 static struct symbol bad_member = {
303 .type = SYM_BAD,
304 .ctype.base_type = &bad_ctype,
305 .kind = 'm',
308 if (!type->symbol_list)
309 type->scope = file_scope;
311 mem = &bad_member;
312 mem->ident = name;
315 return mem;
318 static struct expression *peek_preop(struct expression *expr, int op)
320 do {
321 if (expr->type != EXPR_PREOP)
322 break;
323 if (expr->op == op)
324 return expr->unop;
325 if (expr->op == '(')
326 expr = expr->unop;
327 else
328 break;
329 } while (expr);
331 return NULL;
334 static struct symbol *do_expression(usage_t mode, struct expression *expr)
336 struct symbol *ret = &int_ctype;
338 again:
339 if (expr) switch (expr->type) {
340 default:
341 warning(expr->pos, "bad expr->type: %d", expr->type);
343 case EXPR_TYPE: // [struct T]; Why ???
344 case EXPR_VALUE:
345 case EXPR_FVALUE:
347 break; case EXPR_LABEL:
348 ret = &label_ctype;
350 break; case EXPR_STRING:
351 ret = &string_ctype;
353 break; case EXPR_STATEMENT:
354 ret = do_statement(mode, expr->statement);
356 break; case EXPR_SIZEOF: case EXPR_ALIGNOF: case EXPR_PTRSIZEOF:
357 do_expression(U_VOID, expr->cast_expression);
359 break; case EXPR_COMMA:
360 do_expression(U_VOID, expr->left);
361 ret = do_expression(mode, expr->right);
363 break; case EXPR_CAST: case EXPR_FORCE_CAST: //case EXPR_IMPLIED_CAST:
364 ret = base_type(expr->cast_type);
365 do_initializer(ret, expr->cast_expression);
367 break; case EXPR_COMPARE: case EXPR_LOGICAL:
368 mode = u_rval(mode);
369 do_expression(mode, expr->left);
370 do_expression(mode, expr->right);
372 break; case EXPR_CONDITIONAL: //case EXPR_SELECT:
373 do_expression(expr->cond_true
374 ? U_R_VAL : U_R_VAL | mode,
375 expr->conditional);
376 ret = do_expression(mode, expr->cond_true);
377 ret = do_expression(mode, expr->cond_false);
379 break; case EXPR_CALL:
380 if (expr->fn->type == EXPR_SYMBOL)
381 expr->fn->op = 'f'; /* for expr_symbol() */
382 ret = do_expression(U_R_PTR, expr->fn);
383 if (is_ptr(ret))
384 ret = ret->ctype.base_type;
385 DO_2_LIST(ret->arguments, expr->args, arg, val,
386 do_expression(u_lval(base_type(arg)), val));
387 ret = ret->type == SYM_FN ? base_type(ret)
388 : &bad_ctype;
390 break; case EXPR_ASSIGNMENT:
391 mode |= U_W_VAL | U_R_VAL;
392 if (expr->op == '=')
393 mode &= ~U_R_VAL;
394 ret = do_expression(mode, expr->left);
395 report_implicit(mode, &expr->pos, ret);
396 mode = expr->op == '='
397 ? u_lval(ret) : U_R_VAL;
398 do_expression(mode, expr->right);
400 break; case EXPR_BINOP: {
401 struct symbol *l, *r;
402 mode |= u_rval(mode);
403 l = do_expression(mode, expr->left);
404 r = do_expression(mode, expr->right);
405 if (expr->op != '+' && expr->op != '-')
407 else if (!is_ptr_type(r))
408 ret = l;
409 else if (!is_ptr_type(l))
410 ret = r;
413 break; case EXPR_PREOP: case EXPR_POSTOP: {
414 struct expression *unop = expr->unop;
416 switch (expr->op) {
417 case SPECIAL_INCREMENT:
418 case SPECIAL_DECREMENT:
419 mode |= U_W_VAL | U_R_VAL;
420 default:
421 mode |= u_rval(mode);
422 case '(':
423 ret = do_expression(mode, unop);
425 break; case '&':
426 if ((expr = peek_preop(unop, '*')))
427 goto again;
428 ret = alloc_symbol(unop->pos, SYM_PTR);
429 ret->ctype.base_type =
430 do_expression(u_addr(mode), unop);
432 break; case '*':
433 if ((expr = peek_preop(unop, '&')))
434 goto again;
435 if (mode & (U_MASK << U_SHIFT))
436 mode |= U_R_VAL;
437 mode <<= U_SHIFT;
438 if (mode & (U_R_AOF << U_SHIFT))
439 mode |= U_R_VAL;
440 if (mode & (U_W_VAL << U_SHIFT))
441 mode |= U_W_AOF;
442 ret = do_expression(mode, unop);
443 ret = is_ptr(ret) ? base_type(ret)
444 : &bad_ctype;
448 break; case EXPR_DEREF: {
449 struct symbol *p_type;
450 usage_t p_mode;
452 p_mode = mode & U_SELF;
453 if (!(mode & U_MASK) && (mode & (U_MASK << U_SHIFT)))
454 p_mode = U_R_VAL;
455 p_type = do_expression(p_mode, expr->deref);
457 ret = report_member(mode, &expr->pos, p_type,
458 lookup_member(p_type, expr->member, NULL));
461 break; case EXPR_OFFSETOF: {
462 struct symbol *in = base_type(expr->in);
464 do {
465 if (expr->op == '.') {
466 in = report_member(U_VOID, &expr->pos, in,
467 lookup_member(in, expr->ident, NULL));
468 } else {
469 do_expression(U_R_VAL, expr->index);
470 in = in->ctype.base_type;
472 } while ((expr = expr->down));
475 break; case EXPR_GENERIC: {
476 struct type_expression *map;
478 do_expression(U_VOID, expr->control);
480 for (map = expr->map; map; map = map->next)
481 ret = do_expression(mode, map->expr);
482 if (expr->def)
483 ret = do_expression(mode, expr->def);
486 break; case EXPR_SYMBOL:
487 ret = report_symbol(mode, expr);
490 return ret;
493 static void do_asm_xputs(usage_t mode, struct asm_operand_list *xputs)
495 DO_LIST(xputs, op, do_expression(U_W_AOF | mode, op->expr));
498 static struct symbol *do_statement(usage_t mode, struct statement *stmt)
500 struct symbol *ret = &void_ctype;
502 if (stmt) switch (stmt->type) {
503 default:
504 warning(stmt->pos, "bad stmt->type: %d", stmt->type);
506 case STMT_NONE:
507 case STMT_RANGE:
508 case STMT_CONTEXT:
510 break; case STMT_DECLARATION:
511 do_sym_list(stmt->declaration);
513 break; case STMT_EXPRESSION:
514 ret = do_expression(mode, stmt->expression);
516 break; case STMT_RETURN: {
517 struct symbol *type = dissect_ctx->ctype.base_type;
518 do_expression(u_lval(base_type(type)), stmt->expression);
521 break; case STMT_ASM:
522 do_expression(U_R_VAL, stmt->asm_string);
523 do_asm_xputs(U_W_VAL, stmt->asm_outputs);
524 do_asm_xputs(U_R_VAL, stmt->asm_inputs);
526 break; case STMT_COMPOUND: {
527 int count;
529 count = statement_list_size(stmt->stmts);
530 DO_LIST(stmt->stmts, st,
531 ret = do_statement(--count ? U_VOID : mode, st));
534 break; case STMT_ITERATOR:
535 do_sym_list(stmt->iterator_syms);
536 do_statement(U_VOID, stmt->iterator_pre_statement);
537 do_expression(U_R_VAL, stmt->iterator_pre_condition);
538 do_statement(U_VOID, stmt->iterator_post_statement);
539 do_statement(U_VOID, stmt->iterator_statement);
540 do_expression(U_R_VAL, stmt->iterator_post_condition);
542 break; case STMT_IF:
543 do_expression(U_R_VAL, stmt->if_conditional);
544 do_statement(U_VOID, stmt->if_true);
545 do_statement(U_VOID, stmt->if_false);
547 break; case STMT_SWITCH:
548 do_expression(U_R_VAL, stmt->switch_expression);
549 do_statement(U_VOID, stmt->switch_statement);
551 break; case STMT_CASE:
552 do_expression(U_R_VAL, stmt->case_expression);
553 do_expression(U_R_VAL, stmt->case_to);
554 do_statement(U_VOID, stmt->case_statement);
556 break; case STMT_GOTO:
557 do_expression(U_R_PTR, stmt->goto_expression);
559 break; case STMT_LABEL:
560 do_statement(mode, stmt->label_statement);
564 return ret;
567 static struct symbol *do_initializer(struct symbol *type, struct expression *expr)
569 struct symbol *m_type;
570 struct expression *m_expr;
571 int m_addr;
573 if (expr) switch (expr->type) {
574 default:
575 do_expression(u_lval(type), expr);
577 break; case EXPR_INDEX:
578 do_initializer(base_type(type), expr->idx_expression);
580 break; case EXPR_INITIALIZER:
581 m_addr = 0;
582 FOR_EACH_PTR(expr->expr_list, m_expr) {
583 if (type->type == SYM_ARRAY) {
584 m_type = base_type(type);
585 if (m_expr->type == EXPR_INDEX)
586 m_expr = m_expr->idx_expression;
587 } else {
588 int *m_atop = &m_addr;
590 m_type = type;
591 while (m_expr->type == EXPR_IDENTIFIER) {
592 m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
593 lookup_member(m_type, m_expr->expr_ident, m_atop));
594 m_expr = m_expr->ident_expression;
595 m_atop = NULL;
598 if (m_atop) {
599 m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
600 lookup_member(m_type, NULL, m_atop));
603 if (m_expr->type != EXPR_INITIALIZER)
604 report_implicit(U_W_VAL, &m_expr->pos, m_type);
606 do_initializer(m_type, m_expr);
607 m_addr++;
608 } END_FOR_EACH_PTR(m_expr);
611 return type;
614 static inline bool is_macro(struct symbol *sym)
616 return (sym->namespace == NS_MACRO || sym->namespace == NS_UNDEF);
619 static inline bool is_typedef(struct symbol *sym)
621 return (sym->namespace == NS_TYPEDEF);
624 static inline struct symbol *do_symbol(struct symbol *sym)
626 struct symbol *type = base_type(sym);
627 struct symbol *dctx = dissect_ctx;
628 struct statement *stmt;
630 reporter->r_symdef(sym);
632 switch (type->type) {
633 default:
634 if (!sym->initializer)
635 break;
636 reporter->r_symbol(U_W_VAL, &sym->pos, sym);
637 if (!dctx)
638 dissect_ctx = sym;
639 do_initializer(type, sym->initializer);
640 dissect_ctx = dctx;
642 break; case SYM_FN:
643 stmt = sym->ctype.modifiers & MOD_INLINE
644 ? type->inline_stmt : type->stmt;
645 if (!stmt)
646 break;
648 if (dctx)
649 sparse_error(dctx->pos, "dissect_ctx change %s -> %s",
650 show_ident(dctx->ident), show_ident(sym->ident));
652 dissect_ctx = sym;
653 do_sym_list(type->arguments);
654 do_statement(U_VOID, stmt);
655 dissect_ctx = dctx;
658 return type;
661 static void do_sym_list(struct symbol_list *list)
663 DO_LIST(list, sym, do_symbol(sym));
666 static inline bool valid_namespace(enum namespace ns)
668 return (ns == NS_TYPEDEF || ns == NS_MACRO || ns == NS_UNDEF || ns == NS_STRUCT || ns == NS_SYMBOL);
671 static void do_file(char *file)
673 struct symbol_list *res = sparse_keep_tokens(file);
675 if (!dissect_show_all_symbols) {
676 do_sym_list(res);
677 goto end;
680 DO_LIST(file_scope->symbols, sym,
681 if (input_streams[sym->pos.stream].fd != -1 && valid_namespace(sym->namespace)) {
682 if (is_typedef(sym)) {
683 sym->kind = 't';
684 reporter->r_symdef(sym);
685 continue;
688 if (is_macro(sym)) {
689 sym->kind = 'd';
690 reporter->r_symdef(sym);
691 continue;
694 if (sym->type == SYM_STRUCT || sym->type == SYM_UNION) {
695 sym->ctype.base_type = sym;
696 examine_sym_node(sym, NULL);
697 continue;
700 do_symbol(sym);
704 DO_LIST(global_scope->symbols, sym,
705 if (input_streams[sym->pos.stream].fd != -1 && valid_namespace(sym->namespace)) {
706 do_symbol(sym);
710 end:
711 /* Drop the tokens for this file after parsing */
712 clear_token_alloc();
715 void dissect(struct reporter *rep, struct string_list *filelist)
717 reporter = rep;
719 DO_LIST(filelist, file, do_file(file));