From: Michael Beck Date: Sat, 15 Dec 2007 02:49:56 +0000 (+0000) Subject: - implemented -Wunused-label X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=78cc65b14fc5c53a16368fe5975c70c83e969b19;p=cparser - implemented -Wunused-label [r18759] --- diff --git a/ast_t.h b/ast_t.h index 89a9f59..7efa194 100644 --- a/ast_t.h +++ b/ast_t.h @@ -397,6 +397,7 @@ struct declaration_t { decl_modifiers_t modifiers; unsigned int address_taken : 1; unsigned int is_inline : 1; + unsigned int used : 1; /**< Set if the declaration is used. */ type_t *type; symbol_t *symbol; source_position_t source_position; @@ -482,8 +483,8 @@ struct switch_statement_t { struct goto_statement_t { statement_base_t statement; - declaration_t *label; - goto_statement_t *next; /**< link all goto statements in a function */ + declaration_t *label; /**< The destination label. */ + goto_statement_t *next; /**< links all goto statements of a function */ }; struct case_label_statement_t { @@ -494,9 +495,10 @@ struct case_label_statement_t { }; struct label_statement_t { - statement_base_t statement; - declaration_t *label; - statement_t *label_statement; + statement_base_t statement; + declaration_t *label; + statement_t *label_statement; + label_statement_t *next; /**< links all label statements of a function */ }; struct expression_statement_t { diff --git a/parser.c b/parser.c index f95d1af..c769d34 100644 --- a/parser.c +++ b/parser.c @@ -52,6 +52,8 @@ static switch_statement_t *current_switch = NULL; static statement_t *current_loop = NULL; static goto_statement_t *goto_first = NULL; static goto_statement_t *goto_last = NULL; +static label_statement_t *label_first = NULL; +static label_statement_t *label_last = NULL; static struct obstack temp_obst; /** The current source position. */ @@ -2713,27 +2715,49 @@ static void parse_kr_declaration_list(declaration_t *declaration) /** * Check if all labels are defined in the current function. + * Check if all labels are used in the current function. */ -static void check_for_missing_labels(void) +static void check_labels(void) { bool first_err = true; for (const goto_statement_t *goto_statement = goto_first; - goto_statement != NULL; - goto_statement = goto_statement->next) { - const declaration_t *label = goto_statement->label; - - if (label->source_position.input_name == NULL) { - if (first_err) { - first_err = false; - diagnosticf("%s: In function '%Y':\n", - current_function->source_position.input_name, - current_function->symbol); - } - errorf(goto_statement->statement.source_position, - "label '%Y' used but not defined", label->symbol); + goto_statement != NULL; + goto_statement = goto_statement->next) { + declaration_t *label = goto_statement->label; + + label->used = true; + if (label->source_position.input_name == NULL) { + if (first_err) { + first_err = false; + diagnosticf("%s: In function '%Y':\n", + current_function->source_position.input_name, + current_function->symbol); + } + errorf(goto_statement->statement.source_position, + "label '%Y' used but not defined", label->symbol); } } goto_first = goto_last = NULL; + + if (warning.unused_label) { + for (const label_statement_t *label_statement = label_first; + label_statement != NULL; + label_statement = label_statement->next) { + const declaration_t *label = label_statement->label; + + if (! label->used) { + if (first_err) { + first_err = false; + diagnosticf("%s: In function '%Y':\n", + current_function->source_position.input_name, + current_function->symbol); + } + warningf(label_statement->statement.source_position, + "label '%Y' defined but not used", label->symbol); + } + } + } + label_first = label_last = NULL; } static void parse_external_declaration(void) @@ -2827,7 +2851,7 @@ static void parse_external_declaration(void) current_function = declaration; declaration->init.statement = parse_compound_statement(); - check_for_missing_labels(); + check_labels(); assert(current_function == declaration); current_function = old_current_function; @@ -5105,6 +5129,13 @@ static statement_t *parse_label_statement(void) } } + /* remember the labels's in a list for later checking */ + if (label_last == NULL) { + label_first = label_last = label_statement; + } else { + label_last->next = label_statement; + } + return (statement_t*) label_statement; } diff --git a/warning.c b/warning.c index f39e16c..63cbeac 100644 --- a/warning.c +++ b/warning.c @@ -36,6 +36,7 @@ void set_warning_opt(const char *const opt) OPT("strict-prototypes", strict_prototypes) OPT("switch-default", switch_default) OPT("unknown-pragmas", unknown_pragmas) + OPT("unused-label", unused_label) #if 0 OPTX("unused") { SET(unused_function) diff --git a/warning.h b/warning.h index 6ebcd40..c251a70 100644 --- a/warning.h +++ b/warning.h @@ -73,7 +73,9 @@ typedef struct warning_t { #if 0 // TODO bool unreachable_code:1; /**< Warn if the compiler detects that code will never be executed */ bool unused_function:1; /**< Warn whenever a static function is declared but not defined or a non-inline static function is unused */ +#endif bool unused_label:1; /**< Warn whenever a label is declared but not used */ +#if 0 // TODO bool unused_parameter:1; /**< Warn whenever a function parameter is unused aside from its declaration */ bool unused_variable:1; /**< Warn whenever a local variable or non-constant static variable is unused aside from its declaration */ #endif