From 6b6790fc501dde4bc5d14c5b97a1a061584a2191 Mon Sep 17 00:00:00 2001 From: Krzysztof Bieganski Date: Mon, 29 Aug 2022 15:26:00 +0200 Subject: [PATCH] Preserve return type of `AstNode::addNext` via templating (#3597) No functional change intended. Signed-off-by: Krzysztof Bieganski --- src/V3Ast.cpp | 8 +++++--- src/V3Ast.h | 35 ++++++++++++++++++++++++++--------- src/V3AstInlines.h | 9 ++++++++- src/V3Const.cpp | 2 +- src/V3ParseGrammar.cpp | 4 ++-- src/V3Slice.cpp | 9 +++++---- src/verilog.y | 4 ++-- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 213ddd3fb..2f1467f03 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -213,7 +213,7 @@ string AstNode::prettyTypeName() const { // Insertion inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, - bool next){ + bool next) { #ifdef VL_DEBUG // Called on all major tree changers. // Only for use for those really nasty bugs relating to internals @@ -234,7 +234,8 @@ inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, i #endif } -AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { +template <> +AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { // Add to m_nextp, returns this UDEBUGONLY(UASSERT_OBJ(newp, nodep, "Null item passed to addNext");); debugTreeChange(nodep, "-addNextThs: ", __LINE__, false); @@ -272,7 +273,8 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { return nodep; } -AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) { +template <> +AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) { if (!newp) return nodep; return addNext(nodep, newp); } diff --git a/src/V3Ast.h b/src/V3Ast.h index b05c43318..9e50846cd 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1759,16 +1759,27 @@ public: // METHODS - Tree modifications // Returns nodep, adds newp to end of nodep's list - static AstNode* addNext(AstNode* nodep, AstNode* newp); - // Returns nodep, adds newp (maybe nullptr) to end of nodep's list - static AstNode* addNextNull(AstNode* nodep, AstNode* newp); - inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); } - inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); } - void addNextHere(AstNode* newp); // Insert newp at this->nextp - void addPrev(AstNode* newp) { - replaceWith(newp); - newp->addNext(this); + template + static T_NodeResult* addNext(T_NodeResult* nodep, T_NodeNext* newp) { + static_assert(std::is_base_of::value, + "'T_NodeResult' must be a subtype of AstNode"); + static_assert(std::is_base_of::value, + "'T_NodeNext' must be a subtype of 'T_NodeResult'"); + return static_cast(addNext(nodep, newp)); } + // Returns nodep, adds newp (maybe nullptr) to end of nodep's list + template + static T_NodeResult* addNextNull(T_NodeResult* nodep, T_NodeNext* newp) { + static_assert(std::is_base_of::value, + "'T_NodeResult' must be a subtype of AstNode"); + static_assert(std::is_base_of::value, + "'T_NodeNext' must be a subtype of 'T_NodeResult'"); + return static_cast(addNextNull(nodep, newp)); + } + inline AstNode* addNext(AstNode* newp); + inline AstNode* addNextNull(AstNode* newp); + void addNextHere(AstNode* newp); // Insert newp at this->nextp + inline void addPrev(AstNode* newp); void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node AstNode* unlinkFrBack(VNRelinker* linkerp @@ -2056,6 +2067,12 @@ public: } }; +// Forward declarations of specializations defined in V3Ast.cpp +template <> +AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp); +template <> +AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp); + // Specialisations of privateTypeTest #include "V3Ast__gen_impl.h" // From ./astgen diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 6d8e93b35..9ad974a69 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -23,7 +23,14 @@ #endif //###################################################################### -// Inline ACCESSORS +// Inline METHODS + +inline AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } +inline AstNode* AstNode::addNextNull(AstNode* newp) { return addNextNull(this, newp); } +inline void AstNode::addPrev(AstNode* newp) { + replaceWith(newp); + newp->addNext(this); +} inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index fb90cf866..096510af1 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2079,7 +2079,7 @@ private: AstSel* const sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1); // Make new assigns of same flavor as old one //*** Not cloneTree; just one node. - AstNode* newp = nullptr; + AstNodeAssign* newp = nullptr; if (!need_temp) { AstNodeAssign* const asn1ap = VN_AS(nodep->cloneType(lc1p, sel1p), NodeAssign); AstNodeAssign* const asn2ap = VN_AS(nodep->cloneType(lc2p, sel2p), NodeAssign); diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 38bae0374..8e95d13c8 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -67,10 +67,10 @@ void V3ParseImp::parserClear() { //====================================================================== // V3ParseGrammar functions requiring bison state -AstNode* V3ParseGrammar::argWrapList(AstNode* nodep) { +AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) { // Convert list of expressions to list of arguments if (!nodep) return nullptr; - AstNode* outp = nullptr; + AstArg* outp = nullptr; AstBegin* const tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep); while (nodep) { AstNode* const nextp = nodep->nextp(); diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 94a70fe99..b143373f2 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -139,12 +139,13 @@ class SliceVisitor final : public VNVisitor { // Left and right could have different msb/lsbs/endianness, but #elements is common // and all variables are realigned to start at zero // Assign of a little endian'ed slice to a big endian one must reverse the elements - AstNode* newlistp = nullptr; + AstNodeAssign* newlistp = nullptr; const int elements = arrayp->rangep()->elementsConst(); for (int offset = 0; offset < elements; ++offset) { - AstNode* const newp = nodep->cloneType // AstNodeAssign - (cloneAndSel(nodep->lhsp(), elements, offset), - cloneAndSel(nodep->rhsp(), elements, offset)); + AstNodeAssign* const newp + = VN_AS(nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, offset), + cloneAndSel(nodep->rhsp(), elements, offset)), + NodeAssign); if (debug() >= 9) newp->dumpTree(cout, "-new "); newlistp = AstNode::addNextNull(newlistp, newp); } diff --git a/src/verilog.y b/src/verilog.y index 907ca05d2..3d77c680b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -91,7 +91,7 @@ public: } // METHODS - AstNode* argWrapList(AstNode* nodep); + AstArg* argWrapList(AstNode* nodep); bool allTracingOn(FileLine* fl) { return v3Global.opt.trace() && m_tracingParse && fl->tracingOn(); } @@ -5103,7 +5103,7 @@ idArrayedForeach: // IEEE: id + select (under foreach expression) | idArrayed '[' expr ',' loop_variables ']' { $3 = AstNode::addNextNull($3, $5); $$ = new AstSelLoopVars($2, $1, $3); } | idArrayed '[' ',' loop_variables ']' - { $4 = AstNode::addNextNull(new AstEmpty{$3}, $4); $$ = new AstSelLoopVars($2, $1, $4); } + { $4 = AstNode::addNextNull(static_cast(new AstEmpty{$3}), $4); $$ = new AstSelLoopVars($2, $1, $4); } ; // VarRef without any dots or vectorizaion