aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelina Kościelnicka <mwk@0x04.net>2021-03-30 01:15:49 +0200
committerMarcelina Kościelnicka <mwk@0x04.net>2021-03-30 02:29:26 +0200
commit0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa (patch)
tree3a42f43d13d549df7b4b1eba52e2871948de4cb8
parent1af994802ed75d5805191113f669409c3872fcf7 (diff)
downloadyosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.tar.gz
yosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.tar.bz2
yosys-0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa.zip
preproc: Fix up conditional handling.
Fixes #2710. Fixes #2711.
-rw-r--r--frontends/verilog/preproc.cc20
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;