diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 51612ec29..f5ce7c0c7 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -74,7 +74,7 @@ public: // Called by operator new on any node - only if VL_LEAK_CHECKS if (debug()>=9) cout<<"-nodeNew: "<second & FLAG_ALLOCATED)) { + if (iter !=s_nodes.end() && (iter->second & FLAG_ALLOCATED)) { nodep->v3fatalSrc("Newing AstNode object that is already allocated"); } if (iter == s_nodes.end()) { @@ -117,8 +117,18 @@ public: iter->second |= or_flags; } } + static bool isAllocated(const AstNode* nodep) { + // Some generic node has a pointer to this node. Is it allocated? + // Use this when might not be in tree; otherwise use okIfLinkedTo(). +#ifdef VL_LEAK_CHECKS + NodeMap::iterator iter = s_nodes.find(nodep); + if (iter == s_nodes.end()) return false; + if (!(iter->second & FLAG_ALLOCATED)) return false; +#endif + return true; + } static bool okIfLinkedTo(const AstNode* nodep) { - // Someone has a pointer to this node. Is it kosher? + // Some node in tree has a pointer to this node. Is it kosher? NodeMap::iterator iter = s_nodes.find(nodep); if (iter == s_nodes.end()) return false; #ifdef VL_LEAK_CHECKS @@ -155,6 +165,11 @@ public: // Use only AstNode::dump instead of the virtual one, as there // may be varp() and other cross links that are bad. if (v3Global.opt.debugCheck()) { + // When get this message, find what forgot to delete the + // node by running GDB, where for node "" use: + // watch AstNode::s_editCntGbl==#### + // run + // bt std::cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": "); AstNode* rawp = const_cast (static_cast(it->first)); @@ -295,3 +310,6 @@ void V3Broken::addNewed(AstNode* nodep) { void V3Broken::deleted(AstNode* nodep) { BrokenTable::deleted(nodep); } +bool V3Broken::isAllocated(AstNode* nodep) { + return BrokenTable::isAllocated(nodep); +} diff --git a/src/V3Broken.h b/src/V3Broken.h index 3d4c8351f..62797126b 100644 --- a/src/V3Broken.h +++ b/src/V3Broken.h @@ -34,6 +34,7 @@ public: static void brokenAll(AstNetlist* nodep); static void addNewed(AstNode* nodep); static void deleted(AstNode* nodep); + static bool isAllocated(AstNode* nodep); }; #endif // Guard diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 5ed24f1e4..e8ddb47c7 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1540,6 +1540,7 @@ private: fromp->dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); } + nodep->deleteTree(); VL_DANGLING(nodep); } } m_selp = NULL; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index d289af6d6..f394ceed9 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -189,44 +189,48 @@ private: bool simulateTree(AstNode *nodep, const V3Number *loopValue, AstNode *dtypep, V3Number &outNum) { - AstNode* clone = nodep->cloneTree(true); - if (!clone) { + AstNode* clonep = nodep->cloneTree(true); + if (!clonep) { nodep->v3fatalSrc("Failed to clone tree"); return false; } if (loopValue) { m_varValuep = new AstConst(nodep->fileline(), *loopValue); // Iteration requires a back, so put under temporary node - AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", clone); + AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", clonep); m_varModeReplace = true; iterateAndNextNull(tempp->stmtsp()); m_varModeReplace = false; - clone = tempp->stmtsp()->unlinkFrBackWithNext(); + clonep = tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); tempp = NULL; pushDeletep(m_varValuep); m_varValuep = NULL; } SimulateVisitor simvis; - simvis.mainParamEmulate(clone); + simvis.mainParamEmulate(clonep); if (!simvis.optimizable()) { UINFO(3, "Unable to simulate" << endl); if (debug()>=9) nodep->dumpTree(cout, "- _simtree: "); + clonep->deleteTree(); VL_DANGLING(clonep); return false; } // Fetch the result - V3Number* res = simvis.fetchNumberNull(clone); + V3Number* res = simvis.fetchNumberNull(clonep); if (!res) { UINFO(3, "No number returned from simulation" << endl); + clonep->deleteTree(); VL_DANGLING(clonep); return false; } // Patch up datatype if (dtypep) { - AstConst new_con (clone->fileline(), *res); + AstConst new_con (clonep->fileline(), *res); new_con.dtypeFrom(dtypep); outNum = new_con.num(); + clonep->deleteTree(); VL_DANGLING(clonep); return true; } outNum = *res; + clonep->deleteTree(); VL_DANGLING(clonep); return true; }