diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 34c4e2088..e84452d7b 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1215,12 +1215,16 @@ void AstRange::dump(std::ostream& str) const { } void AstRefDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); - if (defp()) { + if (typedefp() || subDTypep()) { static bool s_recursing = false; if (!s_recursing) { // Prevent infinite dump if circular typedefs s_recursing = true; str << " -> "; - defp()->dump(str); + if (typedefp()) { + typedefp()->dump(str); + } else if (subDTypep()) { + subDTypep()->dump(str); + } s_recursing = false; } } else { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 32bdcf4e1..7282fd67c 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1094,25 +1094,24 @@ public: class AstRefDType : public AstNodeDType { private: + // Pre-Width must reference the Typeref, not what it points to, as some child + // types like AstBracketArrayType will disappear and can't lose the handle + AstTypedef* m_typedefp; // referenced type + // Post-width typedefs are removed and point to type directly AstNodeDType* m_refDTypep; // data type pointed to, BELOW the AstTypedef string m_name; // Name of an AstTypedef AstNodeModule* m_packagep; // Package hierarchy public: AstRefDType(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) + , m_typedefp(NULL) , m_refDTypep(NULL) , m_name(name) , m_packagep(NULL) {} - AstRefDType(FileLine* fl, AstNodeDType* defp) - : ASTGEN_SUPER(fl) - , m_refDTypep(defp) - , m_packagep(NULL) { - dtypeFrom(defp->dtypep()); - widthFromSub(subDTypep()); - } class FlagTypeOfExpr {}; // type(expr) for parser only AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) : ASTGEN_SUPER(fl) + , m_typedefp(NULL) , m_refDTypep(NULL) , m_packagep(NULL) { setOp2p(typeofp); @@ -1120,47 +1119,53 @@ public: ASTNODE_NODE_FUNCS(RefDType) // METHODS virtual const char* broken() const { + BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists()); BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); return NULL; } virtual void cloneRelink() { + if (m_typedefp && m_typedefp->clonep()) { m_typedefp = m_typedefp->clonep(); } if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } virtual bool same(const AstNode* samep) const { const AstRefDType* asamep = static_cast(samep); - return (m_refDTypep == asamep->m_refDTypep && m_name == asamep->m_name - && m_packagep == asamep->m_packagep); + return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep + && m_name == asamep->m_name && m_packagep == asamep->m_packagep); } virtual bool similarDType(AstNodeDType* samep) const { return skipRefp()->similarDType(samep->skipRefp()); } - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep), V3Hash(m_packagep)); } + virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_typedefp), V3Hash(m_packagep)); } virtual void dump(std::ostream& str = std::cout) const; virtual string name() const { return m_name; } virtual string prettyDTypeName() const { return subDTypep() ? subDTypep()->name() : prettyName(); } virtual AstBasicDType* basicp() const { return subDTypep() ? subDTypep()->basicp() : NULL; } + AstNodeDType* subDTypep() const { + if (typedefp()) return typedefp()->subDTypep(); + return refDTypep(); // Maybe NULL + } virtual AstNodeDType* skipRefp() const { // Skip past both the Ref and the Typedef - if (defp()) { - return defp()->skipRefp(); + if (subDTypep()) { + return subDTypep()->skipRefp(); } else { v3fatalSrc("Typedef not linked"); return NULL; } } virtual AstNodeDType* skipRefToConstp() const { - if (defp()) { - return defp()->skipRefToConstp(); + if (subDTypep()) { + return subDTypep()->skipRefToConstp(); } else { v3fatalSrc("Typedef not linked"); return NULL; } } virtual AstNodeDType* skipRefToEnump() const { - if (defp()) { - return defp()->skipRefToEnump(); + if (subDTypep()) { + return subDTypep()->skipRefToEnump(); } else { v3fatalSrc("Typedef not linked"); return NULL; @@ -1170,15 +1175,13 @@ public: virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); } void name(const string& flag) { m_name = flag; } // op1 = Range of variable - AstNodeDType* dtypeSkipRefp() const { return defp()->skipRefp(); } - AstNodeDType* defp() const { - return m_refDTypep; - } // Code backward compatibility name for refDTypep + AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } + AstTypedef* typedefp() const { return m_typedefp; } + void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } AstNodeDType* refDTypep() const { return m_refDTypep; } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return refDTypep(); } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep; } AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } AstNode* typeofp() const { return op2p(); } diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 0cf64c20a..4db5965f7 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -197,6 +197,8 @@ private: iterateChildren(nodep); checkDType(nodep); checkAll(nodep); + UASSERT_OBJ(!(m_elimCells && nodep->typedefp()), nodep, + "RefDType should point to data type before typedefs removed"); if (nodep->packagep()) { if (m_elimCells) { nodep->packagep(NULL); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 9996f11fb..9856c8b3b 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2674,7 +2674,7 @@ private: checkNoDot(nodep); } if (nodep->typeofp()) { // Really is a typeof not a reference - } else if (!nodep->defp()) { + } else if (!nodep->typedefp() && !nodep->subDTypep()) { VSymEnt* foundp; if (nodep->packagep()) { foundp = m_statep->getNodeSym(nodep->packagep())->findIdFlat(nodep->name()); @@ -2682,7 +2682,7 @@ private: foundp = m_curSymp->findIdFallback(nodep->name()); } if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : NULL) { - nodep->refDTypep(defp->subDTypep()); + nodep->typedefp(defp); nodep->packagep(foundp->packagep()); } else if (AstParamTypeDType* defp = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : NULL) { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index c1224d3a9..98d5e0fb4 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1437,18 +1437,21 @@ private: // Type comes from expression's type userIterateAndNext(nodep->typeofp(), WidthVP(SELF, BOTH).p()); AstNode* typeofp = nodep->typeofp(); + nodep->typedefp(NULL); nodep->refDTypep(typeofp->dtypep()); VL_DO_DANGLING(typeofp->unlinkFrBack()->deleteTree(), typeofp); // We had to use AstRefDType for this construct as pointers to this type // in type table are still correct (which they wouldn't be if we replaced the node) } userIterateChildren(nodep, NULL); - if (nodep->subDTypep()) nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); + if (nodep->subDTypep()) { + nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); + nodep->typedefp(NULL); // Note until line above subDTypep() may have followed this + } // Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp()); // But might be recursive, so instead manually recurse into the referenced type - UASSERT_OBJ(nodep->defp(), nodep, "Unlinked"); - nodep->dtypeFrom(nodep->defp()); - userIterate(nodep->defp(), NULL); + UASSERT_OBJ(nodep->subDTypep(), nodep, "Unlinked"); + nodep->dtypeFrom(nodep->subDTypep()); nodep->widthFromSub(nodep->subDTypep()); UINFO(4, "dtWidthed " << nodep << endl); nodep->doingWidth(false);