From 221e4ff6fe5ce002bbd422ad5c25ac7eace70c72 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 7 Oct 2017 14:01:18 -0400 Subject: [PATCH] Fix `` expansion of empty `defines, bug1225. --- Changes | 2 + src/V3PreProc.cpp | 36 +++++++++++++- test_regress/t/t_preproc.out | 94 +++++++++++++++++++++++++++++++++++- test_regress/t/t_preproc.v | 77 +++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 88711eb62..a0fba546c 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix conditional slices and add related optimizations. +**** Fix `` expansion of empty `defines, bug1225. [Odd Magne Reitan] + * Verilator 3.912 2017-09-23 diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 744fb6508..c30f89763 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -205,6 +205,13 @@ private: int getFinalToken(string& buf); ProcState state() const { return m_states.top(); } + bool stateIsDefname() const { + return state()==ps_DEFNAME_UNDEF + || state()==ps_DEFNAME_DEFINE + || state()==ps_DEFNAME_IFDEF + || state()==ps_DEFNAME_IFNDEF + || state()==ps_DEFNAME_ELSIF; + } void statePush(ProcState state) { m_states.push(state); } @@ -644,7 +651,15 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) { if (iter != argValueByName.end()) { // Substitute string subst = iter->second; - out += subst; + if (subst == "") { + // Normally `` is removed later, but with no token after, we're otherwise + // stuck, so remove proceeding `` + if (out.size()>=2 && out.substr(out.size()-2) == "``") { + out = out.substr(0, out.size()-2); + } + } else { + out += subst; + } } else { out += argName; } @@ -657,6 +672,7 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) { // Don't put out the ``, we're forming an escape which will not expand further later } else { out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR + // See also removal in empty substitutes above } cp++; continue; @@ -1079,7 +1095,16 @@ int V3PreProcImp::getStateToken() { m_defRefs.pop(); VL_DANGLING(refp); if (m_defRefs.empty()) { statePop(); + if (state() == ps_JOIN) { // Handle {left}```FOO(ARG) where `FOO(ARG) might be empty + if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); + string lhs = m_joinStack.top(); m_joinStack.pop(); + out = lhs+out; + UINFO(5,"``-end-defarg Out:"<m_parenLevel = 0; } else { // Finished a defref inside a upper defref @@ -1287,7 +1312,16 @@ int V3PreProcImp::getStateToken() { //NOP: out = m_preprocp->defSubstitute(out); if (m_defRefs.empty()) { // Just output the substitution + if (state() == ps_JOIN) { // Handle {left}```FOO where `FOO might be empty + if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); + string lhs = m_joinStack.top(); m_joinStack.pop(); + out = lhs+out; + UINFO(5,"``-end-defref Out:"<