From 0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 30 Mar 2021 01:15:49 +0200 Subject: [PATCH] preproc: Fix up conditional handling. Fixes #2710. Fixes #2711. --- frontends/verilog/preproc.cc | 20 +++++++++++++++++--- 1 file 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 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;