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;
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 {
};
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 {
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. */
/**
* 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)
current_function = declaration;
declaration->init.statement = parse_compound_statement();
- check_for_missing_labels();
+ check_labels();
assert(current_function == declaration);
current_function = old_current_function;
}
}
+ /* 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;
}