Skip to content

Commit

Permalink
Enable implicit fall-through errors
Browse files Browse the repository at this point in the history
  • Loading branch information
amomchilov committed Dec 18, 2024
1 parent 88aae15 commit 2389d0c
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ FUZZ_OUTPUT_DIR = $(CURDIR)/fuzz/output
SOEXT ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')

CPPFLAGS := -Iinclude $(CPPFLAGS)
CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden $(CFLAGS)
CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(CFLAGS)
CC ?= cc
AR ?= ar
WASI_SDK_PATH := /opt/wasi-sdk
Expand Down
12 changes: 12 additions & 0 deletions include/prism/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,16 @@
#define PRISM_UNLIKELY(x) (x)
#endif

/**
* We use -Wimplicit-fallthrough to guard against against fallthrough between cases of a switch.
* Use explicitly PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional.
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L // C23 or later
#define PRISM_FALLTHROUGH [[fallthrough]];
#elif defined(__GNUC__) || defined(__clang__)
#define PRISM_FALLTHROUGH __attribute__((fallthrough));
#elif defined(_MSC_VER)
#define PRISM_FALLTHROUGH __fallthrough;
#endif

#endif
53 changes: 27 additions & 26 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -9110,7 +9110,7 @@ lex_global_variable(pm_parser_t *parser) {
case '-':
parser->current.end++;
allow_multiple = false;
/* fallthrough */
PRISM_FALLTHROUGH
default: {
size_t width;

Expand Down Expand Up @@ -10046,8 +10046,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags));
return;
}
PRISM_FALLTHROUGH
}
/* fallthrough */
default: {
if (parser->current.end < parser->end) {
escape_write_escape_encoded(parser, buffer);
Expand Down Expand Up @@ -10750,7 +10750,7 @@ parser_lex(pm_parser_t *parser) {

lexed_comment = true;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\r':
case '\n': {
parser->semantic_token_seen = semantic_token_seen & 0x1;
Expand Down Expand Up @@ -10792,7 +10792,7 @@ parser_lex(pm_parser_t *parser) {
parser->current.type = PM_TOKEN_NEWLINE;
return;
}
/* fallthrough */
PRISM_FALLTHROUGH
case PM_IGNORED_NEWLINE_ALL:
if (!lexed_comment) parser_lex_ignored_newline(parser);
lexed_comment = false;
Expand Down Expand Up @@ -11807,7 +11807,7 @@ parser_lex(pm_parser_t *parser) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, "escaped carriage return");
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
default:
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, "backslash");
break;
Expand Down Expand Up @@ -12004,7 +12004,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
pm_token_buffer_push_byte(&token_buffer, '\n');

Expand Down Expand Up @@ -12191,7 +12191,7 @@ parser_lex(pm_parser_t *parser) {
pm_regexp_token_buffer_escape(parser, &token_buffer);
token_buffer.base.cursor = breakpoint;

/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
// If we've hit a newline, then we need to track that in
// the list of newlines.
Expand Down Expand Up @@ -12233,7 +12233,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer.base, '\r');
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
if (parser->heredoc_end) {
// ... if we are on the same line as a heredoc,
Expand Down Expand Up @@ -12441,7 +12441,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_escape(parser, &token_buffer);
token_buffer.cursor = breakpoint;

/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
// When we hit a newline, we need to flush any potential
// heredocs. Note that this has to happen after we check
Expand Down Expand Up @@ -12486,7 +12486,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
if (!lex_mode->as.string.interpolation) {
pm_token_buffer_push_byte(&token_buffer, '\\');
Expand Down Expand Up @@ -12694,7 +12694,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_escape(parser, &token_buffer);
token_buffer.cursor = breakpoint;

/* fallthrough */
PRISM_FALLTHROUGH
case '\n': {
if (parser->heredoc_end != NULL && (parser->heredoc_end > breakpoint)) {
parser_flush_heredoc_end(parser);
Expand Down Expand Up @@ -12794,7 +12794,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
pm_token_buffer_push_byte(&token_buffer, '\\');
pm_token_buffer_push_byte(&token_buffer, '\n');
Expand All @@ -12814,7 +12814,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
/* fallthrough */
PRISM_FALLTHROUGH
case '\n':
// If we are in a tilde here, we should
// break out of the loop and return the
Expand Down Expand Up @@ -13536,7 +13536,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
return (pm_node_t *) pm_index_target_node_create(parser, call);
}
}
/* fallthrough */
PRISM_FALLTHROUGH
default:
// In this case we have a node that we don't know how to convert
// into a target. We need to treat it as an error. For now, we'll
Expand Down Expand Up @@ -13618,7 +13618,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, target, PM_ERR_WRITE_TARGET_READONLY);
/* fallthrough */
PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value);
pm_node_destroy(parser, target);
Expand Down Expand Up @@ -13760,7 +13760,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
// is no way for us to attach it to the tree at this point.
pm_node_destroy(parser, value);
}
/* fallthrough */
PRISM_FALLTHROUGH
default:
// In this case we have a node that we don't know how to convert into a
// target. We need to treat it as an error. For now, we'll mark it as an
Expand Down Expand Up @@ -14280,7 +14280,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
}
}
}
/* fallthrough */
PRISM_FALLTHROUGH
default: {
if (argument == NULL) {
argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, true, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1));
Expand Down Expand Up @@ -16168,7 +16168,7 @@ parse_operator_symbol_name(const pm_token_t *name) {
case PM_TOKEN_TILDE:
case PM_TOKEN_BANG:
if (name->end[-1] == '@') return name->end - 1;
/* fallthrough */
PRISM_FALLTHROUGH
default:
return name->end;
}
Expand Down Expand Up @@ -17140,7 +17140,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
break;
}
}
/* fallthrough */
PRISM_FALLTHROUGH
default: {
// If we get anything else, then this is an error. For this we'll
// create a missing node for the value and create an assoc node for
Expand Down Expand Up @@ -17636,7 +17636,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
break;
}
}
/* fallthrough */
PRISM_FALLTHROUGH
default:
node = parse_pattern_primitives(parser, captures, NULL, diag_id, (uint16_t) (depth + 1));
break;
Expand Down Expand Up @@ -18766,7 +18766,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
}
}
/* fallthrough */
PRISM_FALLTHROUGH
default:
return (pm_node_t *) pm_alias_method_node_create(parser, &keyword, new_name, old_name);
}
Expand Down Expand Up @@ -19294,7 +19294,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_TOKEN_CLASS_VARIABLE:
case PM_TOKEN_GLOBAL_VARIABLE:
valid_name = false;
/* fallthrough */
PRISM_FALLTHROUGH
case PM_TOKEN_CONSTANT:
case PM_TOKEN_KEYWORD_NIL:
case PM_TOKEN_KEYWORD_SELF:
Expand Down Expand Up @@ -20964,7 +20964,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_parser_local_add_location(parser, call_node->message_loc.start, call_node->message_loc.end, 0);
}
}
/* fallthrough */
PRISM_FALLTHROUGH
case PM_CASE_WRITABLE: {
parser_lex(parser);
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
Expand Down Expand Up @@ -21010,7 +21010,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
/* fallthrough */
PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);

Expand Down Expand Up @@ -21128,7 +21128,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
/* fallthrough */
PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);

Expand Down Expand Up @@ -21256,7 +21256,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
/* fallthrough */
PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);

Expand Down Expand Up @@ -21893,6 +21893,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
if (pm_symbol_node_label_p(node)) {
return node;
}
break;
default:
break;
}
Expand Down
5 changes: 2 additions & 3 deletions src/regexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,7 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser, uint16_t depth) {
// If we hit a -, then we're done parsing options.
if (*parser->cursor != '-') break;

// Otherwise, fallthrough to the - case.
/* fallthrough */
PRISM_FALLTHROUGH
case '-':
parser->cursor++;
while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ':' && *parser->cursor != ')') {
Expand Down Expand Up @@ -712,7 +711,7 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) {
if (!pm_regexp_char_find(parser, '\n')) parser->cursor = parser->end;
return true;
}
/* fallthrough */
PRISM_FALLTHROUGH
default: {
size_t width;
if (!parser->encoding_changed) {
Expand Down

0 comments on commit 2389d0c

Please sign in to comment.