unreachable: move it out of smatch_flow.c and smatch_states.c
[smatch.git] / check_unreachable.c
blob693b3a21f05a418ae22042263dfc5e781f6fa110
1 /*
2 * Copyright (C) 2014 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include "smatch.h"
20 static int my_id;
22 static int empty_statement(struct statement *stmt)
24 if (!stmt)
25 return 0;
26 if (stmt->type == STMT_EXPRESSION && !stmt->expression)
27 return 1;
28 return 0;
31 static int is_last_stmt(struct statement *cur_stmt)
33 struct symbol *fn = get_base_type(cur_func_sym);
34 struct statement *stmt;
36 if (!fn)
37 return 0;
38 stmt = fn->stmt;
39 if (!stmt)
40 stmt = fn->inline_stmt;
41 if (!stmt || stmt->type != STMT_COMPOUND)
42 return 0;
43 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
44 if (stmt == cur_stmt)
45 return 1;
46 return 0;
49 static void print_unreached_initializers(struct symbol_list *sym_list)
51 struct symbol *sym;
53 FOR_EACH_PTR(sym_list, sym) {
54 if (sym->initializer)
55 sm_msg("info: '%s' is not actually initialized (unreached code).",
56 (sym->ident ? sym->ident->name : "this variable"));
57 } END_FOR_EACH_PTR(sym);
60 static void print_unreached(struct statement *stmt)
62 static int print = 1;
64 if (__inline_fn)
65 return;
67 if (!__path_is_null()) {
68 print = 1;
69 return;
71 if (!print)
72 return;
74 switch (stmt->type) {
75 case STMT_COMPOUND: /* after a switch before a case stmt */
76 case STMT_RANGE:
77 case STMT_CASE:
78 case STMT_LABEL:
79 return;
80 case STMT_DECLARATION: /* switch (x) { int a; case foo: ... */
81 print_unreached_initializers(stmt->declaration);
82 return;
83 case STMT_RETURN: /* gcc complains if you don't have a return statement */
84 if (is_last_stmt(stmt))
85 return;
86 break;
87 case STMT_GOTO:
88 /* people put extra breaks inside switch statements */
89 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE &&
90 strcmp(stmt->goto_label->ident->name, "break") == 0)
91 return;
92 break;
93 default:
94 break;
96 if (empty_statement(stmt))
97 return;
98 if (!option_spammy)
99 return;
100 sm_msg("info: ignoring unreachable code.");
101 print = 0;
104 void check_unreachable(int id)
106 my_id = id;
108 add_hook(&print_unreached, STMT_HOOK);