From 4c4fdb5dfef68a45fc9dc4c4557ac41089a09ce9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 13 May 2025 22:26:15 -0400 Subject: [PATCH] Internals: Refactor some JSON and error code --- src/V3Ast.cpp | 2 +- src/V3Error.cpp | 20 +++++---------- src/V3Error.h | 10 ++++++++ src/V3File.h | 63 ++++++++++++++++++++++------------------------ src/V3FileLine.cpp | 1 + src/V3Graph.cpp | 5 +--- src/V3Width.cpp | 9 +++---- 7 files changed, 53 insertions(+), 57 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index c630c96fc..f83f60fd0 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -1461,7 +1461,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const VL_RELEASE(V3Error::s(). nsstr << '\n'; nsstr << "-node: "; const_cast(this)->dump(nsstr); - nsstr << endl; + nsstr << '\n'; } m_fileline->v3errorEnd(nsstr, instanceStrExtra); } diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 1587c8b79..7a190c349 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -50,7 +50,7 @@ V3ErrorCode::V3ErrorCode(const char* msgp) { } string V3ErrorCode::url() const { - if (m_e < V3ErrorCode::EC_FIRST_NAMED) { + if (!isNamed()) { return "https://verilator.org/verilator_doc.html"s + "?v=" + PACKAGE_VERSION_NUMBER_STRING; } else { return "https://verilator.org/warn/"s + ascii() + "?v=" + PACKAGE_VERSION_NUMBER_STRING; @@ -64,7 +64,7 @@ string V3ErrorCode::url() const { bool V3ErrorGuarded::isError(V3ErrorCode code, bool supp) VL_REQUIRES(m_mutex) { if (code.hardError()) return true; if (supp) return false; - if (code == V3ErrorCode::USERINFO || code == V3ErrorCode::EC_INFO) return false; + if (code.severityInfo()) return false; if (pretendError(code)) return true; return false; } @@ -74,9 +74,7 @@ string V3ErrorGuarded::msgPrefix() VL_REQUIRES(m_mutex) { const bool supp = m_errorSuppressed; if (supp) { return "-arning-suppressed: "; - } else if (code == V3ErrorCode::USERINFO) { - return "-Info: "; - } else if (code == V3ErrorCode::EC_INFO) { + } else if (code.severityInfo()) { return "-Info: "; } else if (code == V3ErrorCode::EC_FATAL) { return "%Error: "; @@ -208,8 +206,7 @@ void V3ErrorGuarded::v3errorEndGuts(std::ostringstream& sstr, const string& extr ) { std::cerr << msg; } - if (!m_errorSuppressed - && !(m_errorCode == V3ErrorCode::EC_INFO || m_errorCode == V3ErrorCode::USERINFO)) { + if (!m_errorSuppressed && !m_errorCode.severityInfo()) { const bool anError = isError(m_errorCode, m_errorSuppressed); if (m_errorCode != V3ErrorCode::EC_FATALMANY // Not verbose on final too-many-errors error && !m_describedEachWarn[m_errorCode]) { @@ -217,11 +214,7 @@ void V3ErrorGuarded::v3errorEndGuts(std::ostringstream& sstr, const string& extr if (m_errorCode >= V3ErrorCode::EC_FIRST_NAMED) { std::cerr << warnMoreSpaces() << "... For " << (anError ? "error" : "warning") << " description see " << m_errorCode.url() << endl; - } else if (m_errCount >= 1 - && (m_errorCode == V3ErrorCode::EC_FATAL - || m_errorCode == V3ErrorCode::EC_FATALMANY - || m_errorCode == V3ErrorCode::EC_FATALSRC) - && !m_tellInternal) { + } else if (m_errCount >= 1 && m_errorCode.severityFatal() && !m_tellInternal) { m_tellInternal = true; std::cerr << warnMoreSpaces() << "... This fatal error may be caused by the earlier error(s);" @@ -250,8 +243,7 @@ void V3ErrorGuarded::v3errorEndGuts(std::ostringstream& sstr, const string& extr } else { incWarnings(); } - if (m_errorCode == V3ErrorCode::EC_FATAL || m_errorCode == V3ErrorCode::EC_FATALMANY - || m_errorCode == V3ErrorCode::EC_FATALSRC) { + if (m_errorCode.severityFatal()) { static bool inFatal = false; if (!inFatal) { inFatal = true; diff --git a/src/V3Error.h b/src/V3Error.h index 445c302f5..f9132b491 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -234,6 +234,15 @@ public: bool hardError() const VL_MT_SAFE { return (m_e != EC_INFO && m_e < V3ErrorCode::EC_FIRST_WARN); } + // Warning is fatal error, don't continue + bool severityFatal() const VL_MT_SAFE { + return m_e == V3ErrorCode::EC_FATAL || m_e == V3ErrorCode::EC_FATALMANY + || m_e == V3ErrorCode::EC_FATALSRC; + } + // Warning is -Info informational + bool severityInfo() const VL_MT_SAFE { + return m_e == V3ErrorCode::USERINFO || m_e == V3ErrorCode::EC_INFO; + } // Warnings we'll present to the user as errors // Later -Werror- options may make more of these. bool pretendError() const VL_MT_SAFE { @@ -279,6 +288,7 @@ public: if (m_e == LITENDIAN) return V3ErrorCode{ASCRANGE}; return V3ErrorCode{EC_MIN}; // Not renamed; see isRenamed() } + bool isNamed() const { return m_e >= EC_FIRST_NAMED; } bool isRenamed() const { return renamedTo() != V3ErrorCode{EC_MIN}; } bool isUnder(V3ErrorCode other) { // backwards compatibility inheritance-like warnings diff --git a/src/V3File.h b/src/V3File.h index 3a28ef92e..1470ec4eb 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -296,7 +296,10 @@ public: : V3OutFile{filename, V3OutFormatter::LA_JSON} { begin(); } - ~V3OutJsonFile() override { end(); } + ~V3OutJsonFile() override { + end(); + puts("\n"); + } virtual void putsHeader() {} void puts(const char* strg) { putsNoTracking(strg); } void puts(const string& strg) { putsNoTracking(strg); } @@ -317,43 +320,25 @@ public: return *this; } + // Put a named value + V3OutJsonFile& put(const std::string& name, const char* valuep) { + return putNamed(name, std::string{valuep}, true); + } V3OutJsonFile& put(const std::string& name, const std::string& value) { - comma(); - puts(m_prefix + "\"" + name + "\": \"" + value + "\""); - m_empty = false; - return *this; + return putNamed(name, value, true); } V3OutJsonFile& put(const std::string& name, bool value) { - comma(); - puts(m_prefix + "\"" + name + "\": " + (value ? "true" : "false")); - m_empty = false; - return *this; + return putNamed(name, value ? "true" : "false", false); } V3OutJsonFile& put(const std::string& name, int value) { - comma(); - puts(m_prefix + "\"" + name + "\": " + std::to_string(value)); - m_empty = false; - return *this; - } - V3OutJsonFile& put(const std::string& value) { - comma(); - puts(m_prefix + "\"" + value + "\""); - m_empty = false; - return *this; - } - V3OutJsonFile& put(bool value) { - comma(); - puts(m_prefix + (value ? "true" : "false")); - m_empty = false; - return *this; - } - V3OutJsonFile& put(int value) { - comma(); - puts(m_prefix + std::to_string(value)); - m_empty = false; - return *this; + return putNamed(name, std::to_string(value), false); } + // Put unnamed value + V3OutJsonFile& put(const std::string& value) { return putNamed("", value, true); } + V3OutJsonFile& put(bool value) { return putNamed("", value ? "true" : "false", false); } + V3OutJsonFile& put(int value) { return putNamed("", std::to_string(value), false); } + template V3OutJsonFile& putList(const std::string& name, const T& list) { if (list.empty()) return *this; @@ -363,9 +348,9 @@ public: } V3OutJsonFile& end() { - assert(m_prefix.length() >= strlen(INDENT)); + UASSERT(m_prefix.length() >= strlen(INDENT), "prefix underflow"); m_prefix.erase(m_prefix.end() - strlen(INDENT), m_prefix.end()); - assert(!m_scope.empty()); + UASSERT(!m_scope.empty(), "end() without begin()"); puts("\n" + m_prefix + m_scope.top()); m_scope.pop(); return *this; @@ -381,6 +366,18 @@ private: if (!m_empty) puts(",\n"); m_empty = true; } + V3OutJsonFile& putNamed(const std::string& name, const std::string& value, bool quoted) { + comma(); + const string valueQ + = quoted ? "\""s + V3OutFormatter::quoteNameControls(value) + "\"" : value; + if (name.empty()) { + puts(m_prefix + valueQ); + } else { + puts(m_prefix + "\"" + name + "\": " + valueQ); + } + m_empty = false; + return *this; + } }; class V3OutMkFile final : public V3OutFile { diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 94509087c..72daf9d05 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -524,6 +524,7 @@ string FileLine::warnContextParent() const VL_REQUIRES(V3Error::s().m_mutex) { } return result; } + #ifdef VL_LEAK_CHECKS std::unordered_set fileLineLeakChecks; diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index de1d19ca9..6b7b79dd9 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -108,10 +108,7 @@ template V3GraphEdge* V3GraphVertex::findConnectingEdgep(V3Gr void V3GraphVertex::v3errorEnd(std::ostringstream& str) const VL_RELEASE(V3Error::s().m_mutex) { std::ostringstream nsstr; nsstr << str.str(); - if (debug()) { - nsstr << endl; - nsstr << "-vertex: " << this << endl; - } + if (debug()) nsstr << "\n-vertex: " << this << '\n'; if (FileLine* const flp = fileline()) { flp->v3errorEnd(nsstr); } else { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9f7e85728..9e307391c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -108,11 +108,10 @@ std::ostream& operator<<(std::ostream& str, const Determ& rhs) { } #define v3widthWarn(lhs, rhs, msg) \ - v3errorEnd( \ - v3errorBuildMessage(V3Error::v3errorPrep((lhs) < (rhs) ? V3ErrorCode::WIDTHTRUNC \ - : (lhs) > (rhs) ? V3ErrorCode::WIDTHEXPAND \ - : V3ErrorCode::WIDTH), \ - msg)) + v3warnCode(((lhs) < (rhs) ? V3ErrorCode::WIDTHTRUNC \ + : (lhs) > (rhs) ? V3ErrorCode::WIDTHEXPAND \ + : V3ErrorCode::WIDTH), \ + msg) //###################################################################### // Width state, as a visitor of each AstNode