From: Benjamin Kramer Date: Fri, 13 Oct 2017 20:37:52 +0000 (+0000) Subject: [SmallPtrSet] Add iterator epoch tracking. X-Git-Tag: android-x86-7.1-r4~9770 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=937b560bd5d67d62c4264f789f1066693d33e1ef;p=android-x86%2Fexternal-llvm.git [SmallPtrSet] Add iterator epoch tracking. This will detect invalid iterators when ABI breaking checks are enabled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315746 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 87283729cb4..78ea613af69 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -15,6 +15,7 @@ #ifndef LLVM_ADT_SMALLPTRSET_H #define LLVM_ADT_SMALLPTRSET_H +#include "llvm/ADT/EpochTracker.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ReverseIteration.h" #include "llvm/Support/type_traits.h" @@ -46,7 +47,7 @@ namespace llvm { /// (-2), to allow deletion. The hash table is resized when the table is 3/4 or /// more. When this happens, the table is doubled in size. /// -class SmallPtrSetImplBase { +class SmallPtrSetImplBase : public DebugEpochBase { friend class SmallPtrSetIteratorImpl; protected: @@ -92,6 +93,7 @@ public: size_type size() const { return NumNonEmpty - NumTombstones; } void clear() { + incrementEpoch(); // If the capacity of the array is huge, and the # elements used is small, // shrink the array. if (!isSmall()) { @@ -138,12 +140,14 @@ protected: if (LastTombstone != nullptr) { *LastTombstone = Ptr; --NumTombstones; + incrementEpoch(); return std::make_pair(LastTombstone, true); } // Nope, there isn't. If we stay small, just 'pushback' now. if (NumNonEmpty < CurArraySize) { SmallArray[NumNonEmpty++] = Ptr; + incrementEpoch(); return std::make_pair(SmallArray + (NumNonEmpty - 1), true); } // Otherwise, hit the big set case, which will call grow. @@ -259,8 +263,9 @@ protected: }; /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. -template -class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { +template +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl, + DebugEpochBase::HandleBase { using PtrTraits = PointerLikeTypeTraits; public: @@ -270,12 +275,14 @@ public: using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; - explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) - : SmallPtrSetIteratorImpl(BP, E) {} + explicit SmallPtrSetIterator(const void *const *BP, const void *const *E, + const DebugEpochBase &Epoch) + : SmallPtrSetIteratorImpl(BP, E), DebugEpochBase::HandleBase(&Epoch) {} // Most methods provided by baseclass. const PtrTy operator*() const { + assert(isHandleInSync() && "invalid iterator access!"); if (shouldReverseIterate()) { assert(Bucket > End); return PtrTraits::getFromVoidPointer(const_cast(Bucket[-1])); @@ -285,6 +292,7 @@ public: } inline SmallPtrSetIterator& operator++() { // Preincrement + assert(isHandleInSync() && "invalid iterator access!"); if (shouldReverseIterate()) { --Bucket; RetreatIfNotValid(); @@ -397,8 +405,8 @@ private: /// Create an iterator that dereferences to same place as the given pointer. iterator makeIterator(const void *const *P) const { if (shouldReverseIterate()) - return iterator(P == EndPointer() ? CurArray : P + 1, CurArray); - return iterator(P, EndPointer()); + return iterator(P == EndPointer() ? CurArray : P + 1, CurArray, *this); + return iterator(P, EndPointer(), *this); } }; diff --git a/lib/Support/SmallPtrSet.cpp b/lib/Support/SmallPtrSet.cpp index 47e960e243c..119bb871d4c 100644 --- a/lib/Support/SmallPtrSet.cpp +++ b/lib/Support/SmallPtrSet.cpp @@ -61,6 +61,7 @@ SmallPtrSetImplBase::insert_imp_big(const void *Ptr) { else ++NumNonEmpty; // Track density. *Bucket = Ptr; + incrementEpoch(); return std::make_pair(Bucket, true); }