return create_invalid_statement();
}
+static statement_t *parse_label_inner_statement(char const *const label, bool const eat_empty_stmt)
+{
+ statement_t *inner_stmt;
+ switch (token.type) {
+ case '}':
+ errorf(HERE, "%s at end of compound statement", label);
+ inner_stmt = create_invalid_statement();
+ break;
+
+ case ';':
+ if (eat_empty_stmt) {
+ /* Eat an empty statement here, to avoid the warning about an empty
+ * statement after a label. label:; is commonly used to have a label
+ * before a closing brace. */
+ inner_stmt = create_empty_statement();
+ next_token();
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ inner_stmt = parse_statement();
+ if (inner_stmt->kind == STATEMENT_DECLARATION) {
+ errorf(&inner_stmt->base.source_position, "declaration after %s", label);
+ }
+ break;
+ }
+ return inner_stmt;
+}
+
/**
* Parse a case statement.
*/
errorf(pos, "case label not within a switch statement");
}
- statement_t *const inner_stmt = parse_statement();
- statement->case_label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after case label");
- }
+ statement->case_label.statement = parse_label_inner_statement("case label", false);
POP_PARENT;
return statement;
"'default' label not within a switch statement");
}
- statement_t *const inner_stmt = parse_statement();
- statement->case_label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after default label");
- }
+ statement->case_label.statement = parse_label_inner_statement("default label", false);
POP_PARENT;
return statement;
eat(':');
- if (token.type == '}') {
- errorf(HERE, "label at end of compound statement");
- statement->label.statement = create_invalid_statement();
- } else if (token.type == ';') {
- /* Eat an empty statement here, to avoid the warning about an empty
- * statement after a label. label:; is commonly used to have a label
- * before a closing brace. */
- statement->label.statement = create_empty_statement();
- next_token();
- } else {
- statement_t *const inner_stmt = parse_statement();
- statement->label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after label");
- }
- }
+ statement->label.statement = parse_label_inner_statement("label", true);
/* remember the labels in a list for later checking */
*label_anchor = &statement->label;