diff options
author | Marcelina Kościelnicka <mwk@0x04.net> | 2021-03-30 01:15:49 +0200 |
---|---|---|
committer | Marcelina Kościelnicka <mwk@0x04.net> | 2021-03-30 02:29:26 +0200 |
commit | 0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa (patch) | |
tree | 3a42f43d13d549df7b4b1eba52e2871948de4cb8 /frontends | |
parent | 1af994802ed75d5805191113f669409c3872fcf7 (diff) | |
download | yosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.tar.gz yosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.tar.bz2 yosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.zip |
preproc: Fix up conditional handling.
Fixes #2710.
Fixes #2711.
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/verilog/preproc.cc | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 84966e501..568224da2 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -726,8 +726,16 @@ frontend_verilog_preproc(std::istream &f, defines.merge(global_defines_cache); std::vector<std::string> filename_stack; + // We are inside pass_level levels of satisfied ifdefs, and then within + // fail_level levels of unsatisfied ifdefs. The unsatisfied ones are + // always within satisfied ones — even if some condition within is true, + // the parent condition failing renders it moot. int ifdef_fail_level = 0; int ifdef_pass_level = 0; + // For the outermost unsatisfied ifdef, true iff that ifdef already + // had a satisfied branch, and further elsif/else branches should be + // considered unsatisfied even if the condition is true. + // Meaningless if ifdef_fail_level == 0. bool ifdef_already_satisfied = false; output_code.clear(); @@ -745,7 +753,7 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level > 0) ifdef_fail_level--; else if (ifdef_pass_level > 0) - ifdef_already_satisfied = --ifdef_pass_level; + ifdef_pass_level--; else log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); continue; @@ -755,8 +763,9 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level == 0) { if (ifdef_pass_level == 0) log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); - log_assert(ifdef_already_satisfied); + ifdef_pass_level--; ifdef_fail_level = 1; + ifdef_already_satisfied = true; } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) { ifdef_fail_level = 0; ifdef_pass_level++; @@ -771,8 +780,9 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level == 0) { if (ifdef_pass_level == 0) log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); - log_assert(ifdef_already_satisfied); + ifdef_pass_level--; ifdef_fail_level = 1; + ifdef_already_satisfied = true; } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) { ifdef_fail_level = 0; ifdef_pass_level++; @@ -931,6 +941,10 @@ frontend_verilog_preproc(std::istream &f, output_code.push_back(tok); } + if (ifdef_fail_level > 0 || ifdef_pass_level > 0) { + log_error("Unterminated preprocessor conditional!\n"); + } + std::string output; for (auto &str : output_code) output += str; |