[llvm] Add asserts in (ThreadSafe)?RefCountedBase destructors

Added a trivial destructor in release mode and in debug mode a destructor that asserts RefCount is indeed zero.
This ensure people aren't manually (maybe accidentally) destroying these objects like in this contrived example.
```lang=c++
{
  std::unique_ptr<SomethingRefCounted> Object;
  holdIntrusiveOwnership(Object.get());
  // Object Destructor called here will assert.
}
```

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D92480
This commit is contained in:
Nathan James 2020-12-07 20:20:08 +00:00
parent 0a391060f1
commit dc361d5c2a
No known key found for this signature in database
GPG Key ID: CC007AFCDA90AA5F
2 changed files with 30 additions and 10 deletions

View File

@ -150,15 +150,9 @@ private:
};
/// A matcher that always returns true.
///
/// We only ever need one instance of this matcher, so we create a global one
/// and reuse it to reduce the overhead of the matcher and increase the chance
/// of cache hits.
class TrueMatcherImpl : public DynMatcherInterface {
public:
TrueMatcherImpl() {
Retain(); // Reference count will never become zero.
}
TrueMatcherImpl() = default;
bool dynMatches(const DynTypedNode &, ASTMatchFinder *,
BoundNodesTreeBuilder *) const override {
@ -193,8 +187,6 @@ private:
} // namespace
static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
bool ASTMatchFinder::isTraversalIgnoringImplicitNodes() const {
return getASTContext().getParentMapContext().getTraversalKind() ==
TK_IgnoreUnlessSpelledInSource;
@ -273,7 +265,12 @@ DynTypedMatcher::withTraversalKind(ast_type_traits::TraversalKind TK) {
}
DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) {
return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
// We only ever need one instance of TrueMatcherImpl, so we create a static
// instance and reuse it to reduce the overhead of the matcher and increase
// the chance of cache hits.
static const llvm::IntrusiveRefCntPtr<TrueMatcherImpl> Instance =
new TrueMatcherImpl();
return DynTypedMatcher(NodeKind, NodeKind, Instance);
}
bool DynTypedMatcher::canMatchNodesOfKind(ASTNodeKind Kind) const {

View File

@ -75,6 +75,18 @@ public:
RefCountedBase(const RefCountedBase &) {}
RefCountedBase &operator=(const RefCountedBase &) = delete;
#ifndef NDEBUG
~RefCountedBase() {
assert(RefCount == 0 &&
"Destruction occured when there are still references to this.");
}
#else
// Default the destructor in release builds, A trivial destructor may enable
// better codegen.
~RefCountedBase() = default;
#endif
public:
void Retain() const { ++RefCount; }
void Release() const {
@ -94,6 +106,17 @@ protected:
ThreadSafeRefCountedBase &
operator=(const ThreadSafeRefCountedBase &) = delete;
#ifndef NDEBUG
~ThreadSafeRefCountedBase() {
assert(RefCount == 0 &&
"Destruction occured when there are still references to this.");
}
#else
// Default the destructor in release builds, A trivial destructor may enable
// better codegen.
~ThreadSafeRefCountedBase() = default;
#endif
public:
void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }