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
22 static int print_unreached
= 1;
23 static struct string_list
*turn_off_names
;
25 static int empty_statement(struct statement
*stmt
)
29 if (stmt
->type
== STMT_EXPRESSION
&& !stmt
->expression
)
34 static int is_last_stmt(struct statement
*cur_stmt
)
36 struct symbol
*fn
= get_base_type(cur_func_sym
);
37 struct statement
*stmt
;
43 stmt
= fn
->inline_stmt
;
44 if (!stmt
|| stmt
->type
!= STMT_COMPOUND
)
46 stmt
= last_ptr_list((struct ptr_list
*)stmt
->stmts
);
52 static void print_unreached_initializers(struct symbol_list
*sym_list
)
56 FOR_EACH_PTR(sym_list
, sym
) {
58 sm_msg("info: '%s' is not actually initialized (unreached code).",
59 (sym
->ident
? sym
->ident
->name
: "this variable"));
60 } END_FOR_EACH_PTR(sym
);
63 static void unreachable_stmt(struct statement
*stmt
)
69 if (!__path_is_null()) {
77 case STMT_COMPOUND
: /* after a switch before a case stmt */
82 case STMT_DECLARATION
: /* switch (x) { int a; case foo: ... */
83 print_unreached_initializers(stmt
->declaration
);
85 case STMT_RETURN
: /* gcc complains if you don't have a return statement */
86 if (is_last_stmt(stmt
))
90 /* people put extra breaks inside switch statements */
91 if (stmt
->goto_label
&& stmt
->goto_label
->type
== SYM_NODE
&&
92 strcmp(stmt
->goto_label
->ident
->name
, "break") == 0)
98 if (empty_statement(stmt
))
102 sm_msg("info: ignoring unreachable code.");
106 static int is_turn_off(char *name
)
113 FOR_EACH_PTR(turn_off_names
, tmp
) {
114 if (strcmp(tmp
, name
) == 0)
116 } END_FOR_EACH_PTR(tmp
);
121 static char *get_function_name(struct statement
*stmt
)
123 struct expression
*expr
;
125 if (stmt
->type
!= STMT_EXPRESSION
)
127 expr
= stmt
->expression
;
128 if (!expr
|| expr
->type
!= EXPR_CALL
)
130 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol_name
)
132 return expr
->fn
->symbol_name
->name
;
135 static void turn_off_unreachable(struct statement
*stmt
)
139 name
= get_macro_name(stmt
->pos
);
140 if (is_turn_off(name
)) {
145 if (stmt
->type
== STMT_IF
&&
146 known_condition_true(stmt
->if_conditional
)) {
147 name
= get_macro_name(stmt
->if_conditional
->pos
);
148 if (is_turn_off(name
))
153 name
= get_function_name(stmt
);
154 if (is_turn_off(name
))
158 static void register_turn_off_macros(void)
164 if (option_project
== PROJ_NONE
)
165 strcpy(name
, "unreachable.turn_off");
167 snprintf(name
, 256, "%s.unreachable.turn_off", option_project_str
);
169 token
= get_tokens_file(name
);
172 if (token_type(token
) != TOKEN_STREAMBEGIN
)
175 while (token_type(token
) != TOKEN_STREAMEND
) {
176 if (token_type(token
) != TOKEN_IDENT
)
178 macro
= alloc_string(show_ident(token
->ident
));
179 add_ptr_list(&turn_off_names
, macro
);
185 void check_unreachable(int id
)
189 add_hook(&unreachable_stmt
, STMT_HOOK
);
190 register_turn_off_macros();
191 add_hook(&turn_off_unreachable
, STMT_HOOK_AFTER
);