diff --git a/src/V3Ast.h b/src/V3Ast.h index 22f847e05..fadb606e4 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -65,20 +65,19 @@ class VFlagChildDType {}; // Used by parser.y to select constructor that sets c // (V)erilator (N)ode is: Returns true if and only if AstNode is of the given AstNode subtype, // and not nullptr. -#define VN_IS(nodep, nodetypename) (AstNode::privateIs(nodep)) +#define VN_IS(nodep, nodetypename) (AstNode::is(nodep)) // (V)erilator (N)ode cast: Similar to dynamic_cast, but more efficient, use this instead. // Cast to given type if node is of such type, otherwise returns nullptr. If 'nodep' is nullptr, // return nullptr. Pointer constness is preserved, i.e.: given a 'const AstNode*', // a 'const Ast*' is returned. -#define VN_CAST(nodep, nodetypename) \ - (AstNode::privateCast(nodep)) +#define VN_CAST(nodep, nodetypename) (AstNode::cast(nodep)) // (V)erilator (N)ode as: Assert node is of given type then cast to that type. Use this to // downcast instead of VN_CAST when you know the true type of the node. If 'nodep' is nullptr, // return nullptr. Pointer constness is preserved, i.e.: given a 'const AstNode*', a 'const // Ast*' is returned. -#define VN_AS(nodep, nodetypename) (AstNode::privateAs(nodep)) +#define VN_AS(nodep, nodetypename) (AstNode::as(nodep)) // Same as VN_AS, but only checks the type in debug builds. Type checking is less critical in node // child getters (the strongly-typed functions that wrap op*p pointers). This is because the op*p @@ -87,8 +86,7 @@ class VFlagChildDType {}; // Used by parser.y to select constructor that sets c #ifdef VL_DEBUG #define VN_DBG_AS(nodep, nodetypename) VN_AS(nodep, nodetypename) #else -#define VN_DBG_AS(nodep, nodetypename) \ - (AstNode::unsafePrivateAs(nodep)) +#define VN_DBG_AS(nodep, nodetypename) (AstNode::unsafePrivateAs(nodep)) #endif // (V)erilator (N)ode deleted: Pointer to deleted AstNode (for assertions only) @@ -2599,64 +2597,85 @@ protected: } public: - // For use via the VN_IS macro only - template - static bool privateIs(const AstNode* nodep) VL_MT_SAFE { - static_assert(!uselessCast(), "Unnecessary VN_IS, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_IS, node cannot be this type."); - return nodep && privateTypeTest(nodep); + // For use via the VN_IS macro only, or in templated code + template + static bool is(const T_Node* nodep) VL_MT_SAFE { + static_assert(std::is_base_of::value, "VN_IS called on non AstNode"); + static_assert(!uselessCast(), + "Unnecessary VN_IS, node known to have target type."); + static_assert(!impossibleCast(), + "Unnecessary VN_IS, node cannot be this type."); + return nodep && privateTypeTest(nodep); } - // For use via the VN_CAST macro only - template - static T* privateCast(AstNode* nodep) VL_MT_SAFE { - static_assert(!uselessCast(), + // For use via the VN_CAST macro only, or in templated code + template + static T_TargetType* cast(T_Node* nodep) VL_MT_SAFE { + static_assert(std::is_base_of::value, "VN_CAST called on non AstNode"); + static_assert(!uselessCast(), "Unnecessary VN_CAST, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_CAST, node cannot be this type."); - return nodep && privateTypeTest(nodep) ? reinterpret_cast(nodep) : nullptr; + static_assert(!impossibleCast(), + "Unnecessary VN_CAST, node cannot be this type."); + return nodep && privateTypeTest(nodep) + ? reinterpret_cast(nodep) + : nullptr; } - template - static const T* privateCast(const AstNode* nodep) VL_MT_SAFE { - static_assert(!uselessCast(), + template + static const T_TargetType* cast(const T_Node* nodep) VL_MT_SAFE { + static_assert(std::is_base_of::value, "VN_CAST called on non AstNode"); + static_assert(!uselessCast(), "Unnecessary VN_CAST, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_CAST, node cannot be this type."); - return nodep && privateTypeTest(nodep) ? reinterpret_cast(nodep) : nullptr; + static_assert(!impossibleCast(), + "Unnecessary VN_CAST, node cannot be this type."); + return nodep && privateTypeTest(nodep) + ? reinterpret_cast(nodep) + : nullptr; + } + + // For use via the VN_AS macro only, or in templated code + template + static T_TargetType* as(T_Node* nodep) VL_PURE { + static_assert(std::is_base_of::value, "VN_AS called on non AstNode"); + static_assert(!uselessCast(), + "Unnecessary VN_AS, node known to have target type."); + static_assert(!impossibleCast(), + "Unnecessary VN_AS, node cannot be this type."); + UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, + "AstNode is not of expected type, but instead has type '" << nodep->typeName() + << "'"); + return unsafePrivateAs(nodep); + } + template + static const T_TargetType* as(const T_Node* nodep) VL_PURE { + static_assert(std::is_base_of::value, "VN_AS called on non AstNode"); + static_assert(!uselessCast(), + "Unnecessary VN_AS, node known to have target type."); + static_assert(!impossibleCast(), + "Unnecessary VN_AS, node cannot be this type."); + UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, + "AstNode is not of expected type, but instead has type '" << nodep->typeName() + << "'"); + return unsafePrivateAs(nodep); } // For use via privateAs or the VN_DBG_AS macro only - template - static T* unsafePrivateAs(AstNode* nodep) VL_PURE { - static_assert(!uselessCast(), + template + static T_TargetType* unsafePrivateAs(T_Node* nodep) VL_PURE { + static_assert(std::is_base_of::value, "VN_DBG_AS called on non AstNode"); + static_assert(!uselessCast(), "Unnecessary VN_DBG_AS, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_DBG_AS, node cannot be this type."); - return reinterpret_cast(nodep); + static_assert(!impossibleCast(), + "Unnecessary VN_DBG_AS, node cannot be this type."); + return reinterpret_cast(nodep); } - template - static const T* unsafePrivateAs(const AstNode* nodep) VL_PURE { - static_assert(!uselessCast(), + template + static const T_TargetType* unsafePrivateAs(const T_Node* nodep) VL_PURE { + static_assert(std::is_base_of::value, "VN_DBG_AS called on non AstNode"); + static_assert(!uselessCast(), "Unnecessary VN_DBG_AS, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_DBG_AS, node cannot be this type."); - return reinterpret_cast(nodep); - } - - // For use via the VN_AS macro only - template - static T* privateAs(AstNode* nodep) VL_PURE { - static_assert(!uselessCast(), "Unnecessary VN_AS, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_AS, node cannot be this type."); - UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, - "AstNode is not of expected type, but instead has type '" << nodep->typeName() - << "'"); - return unsafePrivateAs(nodep); - } - template - static const T* privateAs(const AstNode* nodep) VL_PURE { - static_assert(!uselessCast(), "Unnecessary VN_AS, node known to have target type."); - static_assert(!impossibleCast(), "Unnecessary VN_AS, node cannot be this type."); - UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, - "AstNode is not of expected type, but instead has type '" << nodep->typeName() - << "'"); - return unsafePrivateAs(nodep); + static_assert(!impossibleCast(), + "Unnecessary VN_DBG_AS, node cannot be this type."); + return reinterpret_cast(nodep); } // Predicate that returns true if the given 'nodep' might have a descendant of type 'T_Node'.