From 9bed7f5602e8e44d436358fbbc0070deeff98634 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Sun, 23 Aug 2026 12:22:17 +0100 Subject: [PATCH] Added shadow warnings --- amd64.c | 6 ++++++ cc.h | 2 +- i386.c | 6 ++++++ lib.c | 7 +++++++ parse.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ parse.h | 1 + 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/amd64.c b/amd64.c index 26b4360..a455731 100644 --- a/amd64.c +++ b/amd64.c @@ -5835,6 +5835,7 @@ static long add_local_symbol (const char *name, int size, int align, int is_unsi } + warn_shadow_symbol (name, scope_start_count, line, start, caret, 0); new_size = align_up_long (current_local_stack_size + size, align); /* @@ -5915,6 +5916,8 @@ static void add_static_local_symbol (const char *name, const char *label, int si } + warn_shadow_symbol (name, scope_start_count, line, start, caret, 0); + local_symbols[local_symbol_count].name = xstrdup (name); local_symbols[local_symbol_count].static_label = xstrdup (label); local_symbols[local_symbol_count].size = size; @@ -6203,6 +6206,9 @@ static void install_pending_params_as_locals (void) { report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate parameter '%s'", pending_params[i].name); } + warn_shadow_symbol (pending_params[i].name, 0, pending_params[i].decl_line, + pending_params[i].decl_start, pending_params[i].decl_start ? pending_params[i].decl_start + pending_params[i].decl_caret_offset : 0, 1); + local_symbols[local_symbol_count].name = xstrdup (pending_params[i].name); local_symbols[local_symbol_count].size = pending_params[i].size; local_symbols[local_symbol_count].align = pending_params[i].align; diff --git a/cc.h b/cc.h index 997bbda..b30e43d 100755 --- a/cc.h +++ b/cc.h @@ -24,7 +24,7 @@ #define WARN_DEFAULT (WARN_DUP_DEFINE | WARN_UNREACHABLE) #define WARN_ALL (WARN_DEFAULT | WARN_NO_RETURN | WARN_SIGNEDNESS | WARN_UNUSED | WARN_FALLTHROUGH | WARN_INITIALIZER) -#define WARN_EXTRA (WARN_ALL | WARN_CONVERSION | WARN_SHADOW | WARN_OLD_STYLE) +#define WARN_EXTRA (WARN_ALL | WARN_CONVERSION | WARN_OLD_STYLE) struct cc_state { diff --git a/i386.c b/i386.c index ad89ec5..096d5e6 100644 --- a/i386.c +++ b/i386.c @@ -5515,6 +5515,7 @@ static long add_local_symbol (const char *name, int size, int align, int is_unsi } + warn_shadow_symbol (name, scope_start_count, line, start, caret, 0); new_size = align_up_long (current_local_stack_size + size, align); /* @@ -5595,6 +5596,8 @@ static void add_static_local_symbol (const char *name, const char *label, int si } + warn_shadow_symbol (name, scope_start_count, line, start, caret, 0); + local_symbols[local_symbol_count].name = xstrdup (name); local_symbols[local_symbol_count].static_label = xstrdup (label); local_symbols[local_symbol_count].size = size; @@ -5883,6 +5886,9 @@ static void install_pending_params_as_locals (void) { report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate parameter '%s'", pending_params[i].name); } + warn_shadow_symbol (pending_params[i].name, 0, pending_params[i].decl_line, + pending_params[i].decl_start, pending_params[i].decl_start ? pending_params[i].decl_start + pending_params[i].decl_caret_offset : 0, 1); + local_symbols[local_symbol_count].name = xstrdup (pending_params[i].name); local_symbols[local_symbol_count].size = pending_params[i].size; local_symbols[local_symbol_count].align = pending_params[i].align; diff --git a/lib.c b/lib.c index 1add87c..7e79daf 100755 --- a/lib.c +++ b/lib.c @@ -572,6 +572,13 @@ void parse_args (int argc, char **argv, int optind) { } + if (strcmp (optarg, "shadow") == 0) { + + state->warn |= WARN_SHADOW; + break; + + } + report_at (program_name, 0, REPORT_ERROR, "unrecognised -W argument"); exit (EXIT_FAILURE); diff --git a/parse.c b/parse.c index 2ad1400..d7775ad 100644 --- a/parse.c +++ b/parse.c @@ -2305,6 +2305,57 @@ struct local_symbol *find_local_symbol (const char *name) { } +void warn_shadow_symbol (const char *name, int scope_start_count, int line, const char *start, const char *caret, int is_parameter) { + + const char *what = 0; + int i; + + if (!state || !(state->warn & WARN_SHADOW) || !name) { + return; + } + + if (!is_parameter) { + + if (scope_start_count < 0) { + scope_start_count = 0; + } + + if (scope_start_count > local_symbol_count) { + scope_start_count = local_symbol_count; + } + + for (i = scope_start_count - 1; i >= 0; i--) { + + if (local_symbols[i].name && strcmp (local_symbols[i].name, name) == 0) { + + what = local_symbols[i].offset > 0 ? "parameter" : "local variable"; + break; + + } + + } + + } + + if (!what && find_global_symbol (name) >= 0) { + what = "global declaration"; + } + + if (!what) { + return; + } + + if (start && caret) { + + report_line_at (get_filename (), line, REPORT_WARNING, start, caret, + "declaration of '%s' shadows a %s", name, what); + + } else { + report_at (get_filename (), line, REPORT_WARNING, "declaration of '%s' shadows a %s", name, what); + } + +} + void warn_unused_local_symbols (int start, const char *filename) { int i; diff --git a/parse.h b/parse.h index 8b52fd8..31c5a29 100644 --- a/parse.h +++ b/parse.h @@ -215,6 +215,7 @@ extern int local_symbol_count; struct local_symbol *find_local_symbol (const char *name); struct local_symbol *peek_local_symbol (const char *name); +void warn_shadow_symbol (const char *name, int scope_start_count, int line, const char *start, const char *caret, int is_parameter); void warn_unused_local_symbols (int start, const char *filename); void warn_unused_static_functions (const char *filename); -- 2.34.1