mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
Fix assignment of class reference to itself causing double free.
Test in next commit.
This commit is contained in:
parent
91d0f25442
commit
30a0d62436
@ -284,6 +284,8 @@ inline uint64_t vl_time_stamp64() VL_MT_SAFE {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
uint64_t VerilatedContext::time() const VL_MT_SAFE {
|
||||
// When using non-default context, fastest path is return time
|
||||
if (VL_LIKELY(m_s.m_time)) return m_s.m_time;
|
||||
@ -311,25 +313,6 @@ double vl_time_multiplier(int scale) VL_PURE;
|
||||
// Return power of 10. e.g. returns 100 if n==2
|
||||
uint64_t vl_time_pow10(int n) VL_PURE;
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
/// Evaluate statement if VL_DEBUG defined
|
||||
# define VL_DEBUG_IFDEF(stmt) \
|
||||
do { \
|
||||
stmt \
|
||||
} while (false)
|
||||
/// Evaluate statement if VL_DEBUG defined and Verilated::debug() enabled
|
||||
# define VL_DEBUG_IF(stmt) \
|
||||
do { \
|
||||
if (VL_UNLIKELY(Verilated::debug())) {stmt} \
|
||||
} while (false)
|
||||
#else
|
||||
// We intentionally do not compile the stmt to improve compile speed
|
||||
# define VL_DEBUG_IFDEF(stmt) do {} while (false)
|
||||
# define VL_DEBUG_IF(stmt) do {} while (false)
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
//=========================================================================
|
||||
// Functional macros/routines
|
||||
// These all take the form
|
||||
|
@ -39,6 +39,28 @@
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
//=========================================================================
|
||||
// Debug functions
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
/// Evaluate statement if VL_DEBUG defined
|
||||
#define VL_DEBUG_IFDEF(stmt) \
|
||||
do { stmt } while (false)
|
||||
/// Evaluate statement if VL_DEBUG defined and Verilated::debug() enabled
|
||||
#define VL_DEBUG_IF(stmt) \
|
||||
do { \
|
||||
if (VL_UNLIKELY(Verilated::debug())) { stmt } \
|
||||
} while (false)
|
||||
#else
|
||||
// We intentionally do not compile the stmt to improve compile speed
|
||||
#define VL_DEBUG_IFDEF(stmt) \
|
||||
do { \
|
||||
} while (false)
|
||||
#define VL_DEBUG_IF(stmt) \
|
||||
do { \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
//===================================================================
|
||||
// String formatters (required by below containers)
|
||||
|
||||
@ -1534,12 +1556,15 @@ class VlClass VL_NOT_FINAL : public VlDeletable {
|
||||
friend class VlClassRef; // Needed for access to the ref counter and deleter
|
||||
|
||||
// MEMBERS
|
||||
std::atomic<size_t> m_counter{0}; // Reference count for this object
|
||||
std::atomic<size_t> m_counter{1}; // Reference count for this object
|
||||
VlDeleter* m_deleterp = nullptr; // The deleter that will delete this object
|
||||
|
||||
// METHODS
|
||||
// Atomically increments the reference counter
|
||||
void refCountInc() VL_MT_SAFE { ++m_counter; }
|
||||
void refCountInc() VL_MT_SAFE {
|
||||
VL_DEBUG_IFDEF(assert(m_counter);); // If zero, we might have already deleted
|
||||
++m_counter;
|
||||
}
|
||||
// Atomically decrements the reference counter. Assuming VlClassRef semantics are sound, it
|
||||
// should never get called at m_counter == 0.
|
||||
void refCountDec() VL_MT_SAFE {
|
||||
@ -1548,8 +1573,8 @@ class VlClass VL_NOT_FINAL : public VlDeletable {
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlClass() { refCountInc(); }
|
||||
VlClass(const VlClass& copied) { refCountInc(); }
|
||||
VlClass() {}
|
||||
VlClass(const VlClass& copied) {}
|
||||
~VlClass() override = default;
|
||||
};
|
||||
|
||||
@ -1629,18 +1654,21 @@ public:
|
||||
// METHODS
|
||||
// Copy and move assignments
|
||||
VlClassRef& operator=(const VlClassRef& copied) {
|
||||
if (m_objp == copied.m_objp) return *this;
|
||||
refCountDec();
|
||||
m_objp = copied.m_objp;
|
||||
refCountInc();
|
||||
return *this;
|
||||
}
|
||||
VlClassRef& operator=(VlClassRef&& moved) {
|
||||
if (m_objp == moved.m_objp) return *this;
|
||||
refCountDec();
|
||||
m_objp = vlstd::exchange(moved.m_objp, nullptr);
|
||||
return *this;
|
||||
}
|
||||
template <typename T_OtherClass>
|
||||
VlClassRef& operator=(const VlClassRef<T_OtherClass>& copied) {
|
||||
if (m_objp == copied.m_objp) return *this;
|
||||
refCountDec();
|
||||
m_objp = copied.m_objp;
|
||||
refCountInc();
|
||||
@ -1648,6 +1676,7 @@ public:
|
||||
}
|
||||
template <typename T_OtherClass>
|
||||
VlClassRef& operator=(VlClassRef<T_OtherClass>&& moved) {
|
||||
if (m_objp == moved.m_objp) return *this;
|
||||
refCountDec();
|
||||
m_objp = vlstd::exchange(moved.m_objp, nullptr);
|
||||
return *this;
|
||||
|
Loading…
Reference in New Issue
Block a user