diff --git a/Documentation/usage/command_line_flags.rst b/Documentation/usage/command_line_flags.rst index 8f7f531b3..fb3f7c7bc 100644 --- a/Documentation/usage/command_line_flags.rst +++ b/Documentation/usage/command_line_flags.rst @@ -131,6 +131,18 @@ These flags affect the general behavior of the compiler. containing an unsized constant number, and unsized constant numbers are not truncated to integer width. + * strict-declaration/no-strict-declaration + + * strict-net-var-declaration/no-strict-net-var-declaration + + * strict-parameter-declaration/no-strict-parameter-declaration + + The standards require that nets, variables, and parameters must be + declared lexically before they are used. Using -gno-strict-declaration + will allow using a data object before declaration, with a warning. The + warning can be suppressed with -Wno-declaration-after-use. The option + can be applied for nets and variables and for parameters separately. + * shared-loop-index/no-shared-loop-index Enable or disable the exclusion of for-loop control variables from @@ -260,6 +272,7 @@ These flags affect the general behavior of the compiler. -Wanachronisms -Wimplicit -Wimplicit-dimensions + -Wdeclaration-after-use -Wmacro-replacement -Wportbind -Wselect-range @@ -288,6 +301,15 @@ These flags affect the general behavior of the compiler. This flag is supported in release 10.1 or master branch snapshots after 2016-02-06. + * declaration-after-use + + This enables warnings for declarations after use, when those are not + flagged as errors (enabled by default). Use no-declaration-after-use + to disable this. + + This flag was added in version 14.0 or later (and is in the master branch + as of 2026-03-21). + * macro-redefinition This enables warnings when a macro is redefined, even if the macro text diff --git a/compiler.h b/compiler.h index 307589aad..01893d18b 100644 --- a/compiler.h +++ b/compiler.h @@ -1,7 +1,7 @@ #ifndef IVL_compiler_H #define IVL_compiler_H /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -104,6 +104,9 @@ extern bool warn_sens_entire_arr; /* Warn about level-appropriate anachronisms. */ extern bool warn_anachronisms; +/* Warn about declaration after use (unless flaged as errors). */ +extern bool warn_decl_after_use; + /* Warn about nets that are references but not driven. */ extern bool warn_floating_nets; @@ -210,6 +213,20 @@ extern bool gn_strict_expr_width_flag; loop. */ extern bool gn_shared_loop_index_flag; +/* If this flag is true (default), then parameters must be declared before + use. `-gno-strict[-parameter]-declaration` allows to use parameters before + declaration, as prior to version 13. + A warning is emited with -Wdeclaration-after-use (default). + */ +extern bool gn_strict_parameter_declaration; + +/* If this flag is true (default), then nets and variablesmust be declared + before use. `-gno-strict[-net-var]-declaration` allows to use nets and + variables before declaration, as prior to version 13. + A warning is emited with -Wdeclaration-after-use (default). + */ +extern bool gn_strict_net_var_declaration; + static inline bool gn_system_verilog(void) { if (generation_flag >= GN_VER2005_SV) diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index be62ec10b..21dbf72dc 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -124,7 +124,7 @@ to disable extended types if compiling code that clashes with the few new keywords used to implement the type system. .TP 8 .B -gio-range-error\fI|\fP-gno-io-range-error -The standards requires that a vectored port have matching ranges for its +The standards require that a vectored port have matching ranges for its port declaration as well as any net/register declaration. It was common practice in the past to only specify the range for the net/register declaration and some tools still allow this. By default any mismatch is @@ -150,6 +150,17 @@ parameter assignment is evaluated as a lossless expression, as is any expression containing an unsized constant number, and unsized constant numbers are not truncated to integer width. .TP 8 +.B -gstrict-declaration\fI|\fP-gno-strict-declaration +.TP 8 +.B -gstrict-net-var-declaration\fI|\fP-gno-strict-net-var-declaration +.TP 8 +.B -gstrict-parameter-declaration\fI|\fP-gno-strict-parameter-declaration +The standards require that nets, variables, and parameters are declared +lexically before they are used. Using \fB\-gno\-strict\-declaration\fP +will allow using a data object before declaration, with a warning. The +warning can be suppressed with -Wno-declaration-after-use. The option +can be applied for nets and variables and for parameters separately. +.TP 8 .B -gshared-loop-index\fI|\fP-gno-shared-loop-index Enable (default) or disable the exclusion of for-loop control variables from implicit event_expression lists. When enabled, if a for-loop control @@ -367,6 +378,11 @@ This enables warnings for creation of implicit declarations. For example, if a scalar wire X is used but not declared in the Verilog source, this will print a warning at its first use. +.TP 8 +.B declaration-after-use +This enables warnings for declarations after use, when +those are not flagged as errors (default). + .TP 8 .B macro-redefinition\fI | \fPmacro-replacement This enables preprocessor warnings when a macro is being redefined. diff --git a/driver/main.c b/driver/main.c index 352ab9f45..a1d22b0ea 100644 --- a/driver/main.c +++ b/driver/main.c @@ -134,6 +134,8 @@ const char*gen_strict_ca_eval = "no-strict-ca-eval"; const char*gen_strict_expr_width = "no-strict-expr-width"; const char*gen_shared_loop_index = "shared-loop-index"; const char*gen_verilog_ams = "no-verilog-ams"; +const char*gen_strict_net_var_declaration = "strict-net-var-declaration"; +const char*gen_strict_parameter_declaration = "strict-parameter-declaration"; /* Boolean: true means use a default include dir, false means don't */ int gen_std_include = 1; @@ -142,7 +144,7 @@ int gen_std_include = 1; of the include list. */ int gen_relative_include = 0; -char warning_flags[17] = "n"; +char warning_flags[18] = "nu"; int separate_compilation_flag = 0; @@ -527,6 +529,7 @@ static void process_warning_switch(const char*name) { if (strcmp(name,"all") == 0) { process_warning_switch("anachronisms"); + process_warning_switch("declaration-after-use"); process_warning_switch("implicit"); process_warning_switch("implicit-dimensions"); process_warning_switch("macro-replacement"); @@ -537,6 +540,9 @@ static void process_warning_switch(const char*name) } else if (strcmp(name,"anachronisms") == 0) { if (! strchr(warning_flags, 'n')) strcat(warning_flags, "n"); + } else if (strcmp(name,"declaration-after-use") == 0) { + if (! strchr(warning_flags, 'u')) + strcat(warning_flags, "u"); } else if (strcmp(name,"floating-nets") == 0) { if (! strchr(warning_flags, 'f')) strcat(warning_flags, "f"); @@ -578,6 +584,12 @@ static void process_warning_switch(const char*name) cp[0] = cp[1]; cp += 1; } + } else if (strcmp(name,"no-declaration-after-use") == 0) { + char*cp = strchr(warning_flags, 'u'); + if (cp) while (*cp) { + cp[0] = cp[1]; + cp += 1; + } } else if (strcmp(name,"no-floating-nets") == 0) { char*cp = strchr(warning_flags, 'f'); if (cp) while (*cp) { @@ -815,6 +827,26 @@ static int process_generation(const char*name) else if (strcmp(name,"no-verilog-ams") == 0) gen_verilog_ams = "no-verilog-ams"; + else if (strcmp(name,"strict-declaration") == 0) { + gen_strict_net_var_declaration = "strict-net-var-declaration"; + gen_strict_parameter_declaration = "strict-parameter-declaration"; + } + else if (strcmp(name,"no-strict-declaration") == 0) { + gen_strict_net_var_declaration = "no-strict-net-var-declaration"; + gen_strict_parameter_declaration = "no-strict-parameter-declaration"; + } + else if (strcmp(name,"strict-net-var-declaration") == 0) + gen_strict_net_var_declaration = "strict-net-var-declaration"; + + else if (strcmp(name,"no-strict-net-var-declaration") == 0) + gen_strict_net_var_declaration = "no-strict-net-var-declaration"; + + else if (strcmp(name,"strict-parameter-declaration") == 0) + gen_strict_parameter_declaration = "strict-parameter-declaration"; + + else if (strcmp(name,"no-strict-parameter-declaration") == 0) + gen_strict_parameter_declaration = "no-strict-parameter-declaration"; + else { fprintf(stderr, "Unknown/Unsupported Language generation " "%s\n\n", name); @@ -837,7 +869,9 @@ static int process_generation(const char*name) " io-range-error | no-io-range-error\n" " strict-ca-eval | no-strict-ca-eval\n" " strict-expr-width | no-strict-expr-width\n" - " shared-loop-index | no-shared-loop-index\n"); + " shared-loop-index | no-shared-loop-index\n" + " strict-declaration | no-strict-declaration\n" + " [no-]strict-[net-var|parameter]-declaration\n"); return 1; } @@ -1385,6 +1419,8 @@ int main(int argc, char **argv) fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width); fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index); fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams); + fprintf(iconfig_file, "generation:%s\n", gen_strict_net_var_declaration); + fprintf(iconfig_file, "generation:%s\n", gen_strict_parameter_declaration); fprintf(iconfig_file, "generation:%s\n", gen_icarus); fprintf(iconfig_file, "warnings:%s\n", warning_flags); fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false"); diff --git a/ivtest/gold/decl_before_use1_warn-iverilog-stderr.gold b/ivtest/gold/decl_before_use1_warn-iverilog-stderr.gold new file mode 100644 index 000000000..5cc4b93e4 --- /dev/null +++ b/ivtest/gold/decl_before_use1_warn-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/decl_before_use1.v:4: warning: net/variable `v` used before declaration. +ivltests/decl_before_use1.v:9: : the net/variable is declared here. diff --git a/ivtest/gold/decl_before_use1_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use1_warn-vvp-stdout.gold new file mode 100644 index 000000000..1eccf69bf --- /dev/null +++ b/ivtest/gold/decl_before_use1_warn-vvp-stdout.gold @@ -0,0 +1,2 @@ +1 +used before declaration diff --git a/ivtest/gold/decl_before_use2_warn-iverilog-stderr.gold b/ivtest/gold/decl_before_use2_warn-iverilog-stderr.gold new file mode 100644 index 000000000..f1ef2cc14 --- /dev/null +++ b/ivtest/gold/decl_before_use2_warn-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/decl_before_use2.v:3: warning: net/variable `w` used before declaration. +ivltests/decl_before_use2.v:10: : the net/variable is declared here. diff --git a/ivtest/gold/decl_before_use2_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use2_warn-vvp-stdout.gold new file mode 100644 index 000000000..6ad2d0448 --- /dev/null +++ b/ivtest/gold/decl_before_use2_warn-vvp-stdout.gold @@ -0,0 +1,2 @@ +00000001 +used before declaration diff --git a/ivtest/gold/decl_before_use3_warn-iverilog-stderr.gold b/ivtest/gold/decl_before_use3_warn-iverilog-stderr.gold new file mode 100644 index 000000000..113671293 --- /dev/null +++ b/ivtest/gold/decl_before_use3_warn-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/decl_before_use3.v:4: warning: event `e` used before declaration. +ivltests/decl_before_use3.v:8: : the event is declared here. diff --git a/ivtest/gold/decl_before_use3_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use3_warn-vvp-stdout.gold new file mode 100644 index 000000000..983403b7d --- /dev/null +++ b/ivtest/gold/decl_before_use3_warn-vvp-stdout.gold @@ -0,0 +1 @@ +used before declaration diff --git a/ivtest/gold/decl_before_use4_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use4_warn-vvp-stdout.gold new file mode 100644 index 000000000..983403b7d --- /dev/null +++ b/ivtest/gold/decl_before_use4_warn-vvp-stdout.gold @@ -0,0 +1 @@ +used before declaration diff --git a/ivtest/gold/decl_before_use5_warn-iverilog-stderr.gold b/ivtest/gold/decl_before_use5_warn-iverilog-stderr.gold new file mode 100644 index 000000000..8bf2623ff --- /dev/null +++ b/ivtest/gold/decl_before_use5_warn-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/decl_before_use5.v:4: warning: parameter `w` used before declaration. +ivltests/decl_before_use5.v:8: : the parameter is declared here. diff --git a/ivtest/gold/decl_before_use5_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use5_warn-vvp-stdout.gold new file mode 100644 index 000000000..6519eec97 --- /dev/null +++ b/ivtest/gold/decl_before_use5_warn-vvp-stdout.gold @@ -0,0 +1,2 @@ +10101010 +used before declaration diff --git a/ivtest/gold/decl_before_use6_warn-vvp-stdout.gold b/ivtest/gold/decl_before_use6_warn-vvp-stdout.gold new file mode 100644 index 000000000..0664d0861 --- /dev/null +++ b/ivtest/gold/decl_before_use6_warn-vvp-stdout.gold @@ -0,0 +1,2 @@ +10 +FAILED diff --git a/ivtest/gold/pr1909940.gold b/ivtest/gold/pr1909940.gold new file mode 100644 index 000000000..4da14bfe4 --- /dev/null +++ b/ivtest/gold/pr1909940.gold @@ -0,0 +1,3 @@ +./ivltests/pr1909940.v:4: warning: net/variable `in` used before declaration. +./ivltests/pr1909940.v:5: : the net/variable is declared here. +PASSED diff --git a/ivtest/gold/pr1909940b.gold b/ivtest/gold/pr1909940b.gold new file mode 100644 index 000000000..7d10aac17 --- /dev/null +++ b/ivtest/gold/pr1909940b.gold @@ -0,0 +1,3 @@ +./ivltests/pr1909940b.v:4: warning: net/variable `in` used before declaration. +./ivltests/pr1909940b.v:5: : the net/variable is declared here. +PASSED diff --git a/ivtest/ivltests/decl_before_use1.v b/ivtest/ivltests/decl_before_use1.v index 8f338b72a..8fae1af7f 100644 --- a/ivtest/ivltests/decl_before_use1.v +++ b/ivtest/ivltests/decl_before_use1.v @@ -3,7 +3,7 @@ module test(); initial begin v = 1; $display("%b", v); - $display("FAILED"); + $display("used before declaration"); end reg v; diff --git a/ivtest/ivltests/decl_before_use2.v b/ivtest/ivltests/decl_before_use2.v index 3eeb619c3..d40c97a1a 100644 --- a/ivtest/ivltests/decl_before_use2.v +++ b/ivtest/ivltests/decl_before_use2.v @@ -4,7 +4,7 @@ assign w = 1; initial begin $display("%b", w); - $display("FAILED"); + $display("used before declaration"); end wire [7:0] w; diff --git a/ivtest/ivltests/decl_before_use3.v b/ivtest/ivltests/decl_before_use3.v index 8fed35387..57f925957 100644 --- a/ivtest/ivltests/decl_before_use3.v +++ b/ivtest/ivltests/decl_before_use3.v @@ -2,7 +2,7 @@ module test(); initial begin ->e; - $display("FAILED"); + $display("used before declaration"); end event e; diff --git a/ivtest/ivltests/decl_before_use4.v b/ivtest/ivltests/decl_before_use4.v index 8daa94218..41e69deb9 100644 --- a/ivtest/ivltests/decl_before_use4.v +++ b/ivtest/ivltests/decl_before_use4.v @@ -2,7 +2,7 @@ module test(); initial begin @(e); - $display("FAILED"); + $display("used before declaration"); end event e; diff --git a/ivtest/ivltests/decl_before_use5.v b/ivtest/ivltests/decl_before_use5.v index cb92f23a0..d7931b0f7 100644 --- a/ivtest/ivltests/decl_before_use5.v +++ b/ivtest/ivltests/decl_before_use5.v @@ -2,7 +2,7 @@ module test(); initial begin $display("%b", w); - $display("FAILED"); + $display("used before declaration"); end localparam w = 8'hAA; diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 6a0323cb8..9309d3afa 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -1126,8 +1126,8 @@ pr1903324 normal ivltests pr1903343 normal ivltests gold=pr1903343.gold pr1903520 normal ivltests pr1907192 normal ivltests -pr1909940 CE ivltests -pr1909940b CE ivltests +pr1909940 normal,-gno-strict-declaration ivltests gold=pr1909940.gold +pr1909940b normal,-gno-strict-declaration ivltests gold=pr1909940b.gold pr1912843 normal ivltests pr1913918a normal ivltests pr1913918b normal ivltests diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 49a0917df..13a548189 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -97,6 +97,12 @@ decl_before_use3 vvp_tests/decl_before_use3.json decl_before_use4 vvp_tests/decl_before_use4.json decl_before_use5 vvp_tests/decl_before_use5.json decl_before_use6 vvp_tests/decl_before_use6.json +decl_before_use1_warn vvp_tests/decl_before_use1_warn.json +decl_before_use2_warn vvp_tests/decl_before_use2_warn.json +decl_before_use3_warn vvp_tests/decl_before_use3_warn.json +decl_before_use4_warn vvp_tests/decl_before_use4_warn.json +decl_before_use5_warn vvp_tests/decl_before_use5_warn.json +decl_before_use6_warn vvp_tests/decl_before_use6_warn.json delayed_sfunc vvp_tests/delayed_sfunc.json dffsynth vvp_tests/dffsynth.json dffsynth-S vvp_tests/dffsynth-S.json diff --git a/ivtest/vvp_tests/decl_before_use1_warn.json b/ivtest/vvp_tests/decl_before_use1_warn.json new file mode 100644 index 000000000..cf5df77cb --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use1_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use1.v", + "iverilog-args" : [ "-gno-strict-net-var-declaration" ], + "gold" : "decl_before_use1_warn" +} diff --git a/ivtest/vvp_tests/decl_before_use2_warn.json b/ivtest/vvp_tests/decl_before_use2_warn.json new file mode 100644 index 000000000..1fdf6c86d --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use2_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use2.v", + "iverilog-args" : [ "-gno-strict-declaration" ], + "gold" : "decl_before_use2_warn" +} diff --git a/ivtest/vvp_tests/decl_before_use3_warn.json b/ivtest/vvp_tests/decl_before_use3_warn.json new file mode 100644 index 000000000..f2507fe6b --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use3_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use3.v", + "iverilog-args" : [ "-gno-strict-net-var-declaration" ], + "gold" : "decl_before_use3_warn" +} diff --git a/ivtest/vvp_tests/decl_before_use4_warn.json b/ivtest/vvp_tests/decl_before_use4_warn.json new file mode 100644 index 000000000..26af6b94d --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use4_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use4.v", + "iverilog-args" : [ "-gno-strict-declaration", "-Wno-declaration-after-use" ], + "gold" : "decl_before_use4_warn" +} diff --git a/ivtest/vvp_tests/decl_before_use5_warn.json b/ivtest/vvp_tests/decl_before_use5_warn.json new file mode 100644 index 000000000..4568e78bd --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use5_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use5.v", + "iverilog-args" : [ "-gno-strict-parameter-declaration" ], + "gold" : "decl_before_use5_warn" +} diff --git a/ivtest/vvp_tests/decl_before_use6_warn.json b/ivtest/vvp_tests/decl_before_use6_warn.json new file mode 100644 index 000000000..5324bb9a3 --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use6_warn.json @@ -0,0 +1,7 @@ + +{ + "type" : "normal", + "source" : "decl_before_use6.v", + "iverilog-args" : [ "-gno-strict-declaration", "-Wno-declaration-after-use" ], + "gold" : "decl_before_use6_warn" +} diff --git a/main.cc b/main.cc index 99c080e0a..a1f5ef1db 100644 --- a/main.cc +++ b/main.cc @@ -117,6 +117,8 @@ bool gn_strict_ca_eval_flag = false; bool gn_strict_expr_width_flag = false; bool gn_shared_loop_index_flag = true; bool gn_verilog_ams_flag = false; +bool gn_strict_parameter_declaration = true; +bool gn_strict_net_var_declaration = true; /* * For some generations we allow a system function to be called @@ -172,6 +174,7 @@ bool warn_ob_select = false; bool warn_sens_entire_vec = false; bool warn_sens_entire_arr = false; bool warn_anachronisms = false; +bool warn_decl_after_use = false; bool warn_floating_nets = false; /* @@ -386,6 +389,18 @@ static void process_generation_flag(const char*gen) } else if (strcmp(gen,"no-shared-loop-index") == 0) { gn_shared_loop_index_flag = false; + } else if (strcmp(gen,"strict-parameter-declaration") == 0) { + gn_strict_parameter_declaration = true; + + } else if (strcmp(gen,"no-strict-parameter-declaration") == 0) { + gn_strict_parameter_declaration = false; + + } else if (strcmp(gen,"strict-net-var-declaration") == 0) { + gn_strict_net_var_declaration = true; + + } else if (strcmp(gen,"no-strict-net-var-declaration") == 0) { + gn_strict_net_var_declaration = false; + } else { } } @@ -760,6 +775,9 @@ static void read_iconfig_file(const char*ipath) case 'n': warn_anachronisms = true; break; + case 'u': + warn_decl_after_use = true; + break; default: break; } diff --git a/net_scope.cc b/net_scope.cc index 1efc464e6..d90b49b82 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2026 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it @@ -462,6 +462,14 @@ unsigned NetScope::get_parameter_lexical_pos(perm_string key) const return 0; } +void NetScope::set_parameter_lexical_pos(perm_string key, unsigned lexical_pos) +{ + map::iterator idx; + + idx = parameters.find(key); + if (idx != parameters.end()) idx->second.lexical_pos = lexical_pos; +} + void NetScope::print_type(ostream&stream) const { switch (type_) { diff --git a/netlist.h b/netlist.h index 57b69959c..d1eb80764 100644 --- a/netlist.h +++ b/netlist.h @@ -1274,6 +1274,7 @@ class NetScope : public Definitions, public Attrib { LineInfo get_parameter_line_info(perm_string name) const; unsigned get_parameter_lexical_pos(perm_string name) const; + void set_parameter_lexical_pos(perm_string name, unsigned lexical_pos); /* Module instance arrays are collected here for access during the multiple elaboration passes. */ diff --git a/symbol_search.cc b/symbol_search.cc index be8580018..61a28d4ec 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2026 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -164,12 +164,22 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } if (NetNet*net = scope->find_signal(path_tail.name)) { - if (prefix_scope || (net->lexical_pos() <= lexical_pos)) { + bool decl_after_use = !prefix_scope && !(net->lexical_pos() <= lexical_pos); + if (!gn_strict_net_var_declaration || !decl_after_use) { path.push_back(path_tail); res->scope = scope; res->net = net; res->type = net->net_type(); res->path_head = path; + if (warn_decl_after_use && decl_after_use) { + cerr << li->get_fileline() + << ": warning: net/variable `" << path_tail.name + << "` used before declaration." << endl; + cerr << net->get_fileline() + << ": : the net/variable is declared here." << endl; + // suppress further warnings for this net + net->lexical_pos(lexical_pos); + } return true; } else if (!res->decl_after_use) { res->decl_after_use = net; @@ -177,11 +187,21 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } if (NetEvent*eve = scope->find_event(path_tail.name)) { - if (prefix_scope || (eve->lexical_pos() <= lexical_pos)) { + bool decl_after_use = !prefix_scope && !(eve->lexical_pos() <= lexical_pos); + if (!gn_strict_net_var_declaration || !decl_after_use) { path.push_back(path_tail); res->scope = scope; res->eve = eve; res->path_head = path; + if (warn_decl_after_use && decl_after_use) { + cerr << li->get_fileline() + << ": warning: event `" << path_tail.name + << "` used before declaration." << endl; + cerr << eve->get_fileline() + << ": : the event is declared here." << endl; + // suppress further warnings for this event + eve->lexical_pos(lexical_pos); + } return true; } else if (!res->decl_after_use) { res->decl_after_use = eve; @@ -189,11 +209,22 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->type)) { - if (prefix_scope || (scope->get_parameter_lexical_pos(path_tail.name) <= lexical_pos)) { + bool decl_after_use = !prefix_scope + && !(scope->get_parameter_lexical_pos(path_tail.name) <= lexical_pos); + if (!gn_strict_parameter_declaration || !decl_after_use) { path.push_back(path_tail); res->scope = scope; res->par_val = par; res->path_head = path; + if (warn_decl_after_use && decl_after_use) { + cerr << li->get_fileline() + << ": warning: parameter `" << path_tail.name + << "` used before declaration." << endl; + cerr << par->get_fileline() + << ": : the parameter is declared here." << endl; + // suppress further warnings for this parameter + scope->set_parameter_lexical_pos(path_tail.name, lexical_pos); + } return true; } else if (!res->decl_after_use) { res->decl_after_use = par;