diff options
author | Jeffrey Yasskin <jyasskin@google.com> | 2009-10-22 20:23:43 +0000 |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@google.com> | 2009-10-22 20:23:43 +0000 |
commit | a84c9db467ce55e68464e6a099dcfe934b513a2a (patch) | |
tree | 7a51da6c1a08fe29ff3485b41b5a503fff641a6f | |
parent | e0a234029b1b65f21169536f4c45e83743ed3cfa (diff) |
Revert r84890, which broke the linux build.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84892 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/ProgrammersManual.html | 18 | ||||
-rw-r--r-- | include/llvm/ADT/ValueMap.h | 365 | ||||
-rw-r--r-- | include/llvm/Support/type_traits.h | 9 | ||||
-rw-r--r-- | unittests/ADT/ValueMapTest.cpp | 291 |
4 files changed, 0 insertions, 683 deletions
diff --git a/docs/ProgrammersManual.html b/docs/ProgrammersManual.html index e4e3dc29c3..68367de0bf 100644 --- a/docs/ProgrammersManual.html +++ b/docs/ProgrammersManual.html @@ -83,7 +83,6 @@ option</a></li> <li><a href="#dss_stringmap">"llvm/ADT/StringMap.h"</a></li> <li><a href="#dss_indexedmap">"llvm/ADT/IndexedMap.h"</a></li> <li><a href="#dss_densemap">"llvm/ADT/DenseMap.h"</a></li> - <li><a href="#dss_valuemap">"llvm/ADT/ValueMap.h"</a></li> <li><a href="#dss_map"><map></a></li> <li><a href="#dss_othermap">Other Map-Like Container Options</a></li> </ul></li> @@ -1493,23 +1492,6 @@ inserted into the map) that it needs internally.</p> <!-- _______________________________________________________________________ --> <div class="doc_subsubsection"> - <a name="dss_valuemap">"llvm/ADT/ValueMap.h"</a> -</div> - -<div class="doc_text"> - -<p> -ValueMap is a wrapper around a <a href="#dss_densemap">DenseMap</a> mapping -Value*s (or subclasses) to another type. When a Value is deleted or RAUW'ed, -ValueMap will update itself so the new version of the key is mapped to the same -value, just as if the key were a WeakVH. You can configure exactly how this -happens, and what else happens on these two events, by passing -a <code>Config</code> parameter to the ValueMap template.</p> - -</div> - -<!-- _______________________________________________________________________ --> -<div class="doc_subsubsection"> <a name="dss_map"><map></a> </div> diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/ADT/ValueMap.h deleted file mode 100644 index a63671b5e7..0000000000 --- a/include/llvm/ADT/ValueMap.h +++ /dev/null @@ -1,365 +0,0 @@ -//===- llvm/ADT/ValueMap.h - Safe map from Values to data -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ValueMap class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_VALUEMAP_H -#define LLVM_ADT_VALUEMAP_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/ValueHandle.h" -#include "llvm/Support/type_traits.h" -#include "llvm/System/Mutex.h" - -#include <iterator> - -namespace llvm { - -template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT> -class ValueMapCallbackVH; - -template<typename DenseMapT, typename KeyT> -class ValueMapIterator; -template<typename DenseMapT, typename KeyT> -class ValueMapConstIterator; - -template<typename KeyT> -struct ValueMapConfig { - /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's - /// false, the ValueMap will leave the original mapping in place. - enum { FollowRAUW = true }; - - // All methods will be called with a first argument of type ExtraData. The - // default implementations in this class take a templated first argument so - // that users' subclasses can use any type they want without having to - // override all the defaults. - struct ExtraData {}; - - template<typename ExtraDataT> - static void onRAUW(const ExtraDataT &Data, KeyT Old, KeyT New) {} - template<typename ExtraDataT> - static void onDeleted(const ExtraDataT &Data, KeyT Old) {} - - /// Returns a mutex that should be acquired around any changes to the map. - /// This is only acquired from the CallbackVH (and held around calls to onRAUW - /// and onDeleted) and not inside other ValueMap methods. NULL means that no - /// mutex is necessary. - template<typename ExtraDataT> - static sys::Mutex *getMutex(const ExtraDataT &Data) { return NULL; } -}; - -/// ValueMap maps Value* or any subclass to an arbitrary other -/// type. It provides the DenseMap interface. When the key values are -/// deleted or RAUWed, ValueMap relies on the Config to decide what to -/// do. Config parameters should inherit from ValueMapConfig<KeyT> to -/// get default implementations of all the methods ValueMap uses. -/// -/// By default, when a key is RAUWed from V1 to V2, the old mapping -/// V1->target is removed, and a new mapping V2->target is added. If -/// V2 already existed, its old target is overwritten. When a key is -/// deleted, its mapping is removed. You can override Config to get -/// called back on each event. -template<typename KeyT, typename ValueT, typename Config = ValueMapConfig<KeyT>, - typename ValueInfoT = DenseMapInfo<ValueT> > -class ValueMap { - friend class ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT>; - typedef ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> ValueMapCVH; - typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH>, - ValueInfoT> MapT; - typedef typename Config::ExtraData ExtraData; - MapT Map; - ExtraData Data; -public: - typedef KeyT key_type; - typedef ValueT mapped_type; - typedef std::pair<KeyT, ValueT> value_type; - - ValueMap(const ValueMap& Other) : Map(Other.Map), Data(Other.Data) {} - - explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} - explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} - - ~ValueMap() {} - - typedef ValueMapIterator<MapT, KeyT> iterator; - typedef ValueMapConstIterator<MapT, KeyT> const_iterator; - inline iterator begin() { return iterator(Map.begin()); } - inline iterator end() { return iterator(Map.end()); } - inline const_iterator begin() const { return const_iterator(Map.begin()); } - inline const_iterator end() const { return const_iterator(Map.end()); } - - bool empty() const { return Map.empty(); } - unsigned size() const { return Map.size(); } - - /// Grow the map so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { Map.resize(Size); } - - void clear() { Map.clear(); } - - /// count - Return true if the specified key is in the map. - bool count(const KeyT &Val) const { - return Map.count(Wrap(Val)); - } - - iterator find(const KeyT &Val) { - return iterator(Map.find(Wrap(Val))); - } - const_iterator find(const KeyT &Val) const { - return const_iterator(Map.find(Wrap(Val))); - } - - /// lookup - Return the entry for the specified key, or a default - /// constructed value if no such entry exists. - ValueT lookup(const KeyT &Val) const { - return Map.lookup(Wrap(Val)); - } - - // Inserts key,value pair into the map if the key isn't already in the map. - // If the key is already in the map, it returns false and doesn't update the - // value. - std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<typename MapT::iterator, bool> map_result= - Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(map_result.first), map_result.second); - } - - /// insert - Range insertion of pairs. - template<typename InputIt> - void insert(InputIt I, InputIt E) { - for (; I != E; ++I) - insert(*I); - } - - - bool erase(const KeyT &Val) { - return Map.erase(Wrap(Val)); - } - bool erase(iterator I) { - return Map.erase(I.base()); - } - - value_type& FindAndConstruct(const KeyT &Key) { - return Map.FindAndConstruct(Wrap(Key)); - } - - ValueT &operator[](const KeyT &Key) { - return Map[Wrap(Key)]; - } - - ValueMap& operator=(const ValueMap& Other) { - Map = Other.Map; - Data = Other.Data; - return *this; - } - - /// isPointerIntoBucketsArray - Return true if the specified pointer points - /// somewhere into the ValueMap's array of buckets (i.e. either to a key or - /// value in the ValueMap). - bool isPointerIntoBucketsArray(const void *Ptr) const { - return Map.isPointerIntoBucketsArray(Ptr); - } - - /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets - /// array. In conjunction with the previous method, this can be used to - /// determine whether an insertion caused the ValueMap to reallocate. - const void *getPointerIntoBucketsArray() const { - return Map.getPointerIntoBucketsArray(); - } - -private: - ValueMapCVH Wrap(KeyT key) const { - // The only way the resulting CallbackVH could try to modify *this (making - // the const_cast incorrect) is if it gets inserted into the map. But then - // this function must have been called from a non-const method, making the - // const_cast ok. - return ValueMapCVH(key, const_cast<ValueMap*>(this)); - } -}; - -template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT> -class ValueMapCallbackVH : public CallbackVH { - friend class ValueMap<KeyT, ValueT, Config, ValueInfoT>; - friend class DenseMapInfo<ValueMapCallbackVH>; - typedef ValueMap<KeyT, ValueT, Config, ValueInfoT> ValueMap; - typedef typename llvm::remove_pointer<KeyT>::type KeySansPointerT; - - ValueMap *Map; - - ValueMapCallbackVH(KeyT Key, ValueMap *Map) - : CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))), - Map(Map) {} - -public: - KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); } - - virtual void deleted() { - // Make a copy that won't get changed even when *this is destroyed. - ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); - if (M) - M->acquire(); - Config::onDeleted(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. - Copy.Map->Map.erase(Copy); // Definitely destroys *this. - if (M) - M->release(); - } - virtual void allUsesReplacedWith(Value *new_key) { - assert(isa<KeySansPointerT>(new_key) && - "Invalid RAUW on key of ValueMap<>"); - // Make a copy that won't get changed even when *this is destroyed. - ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); - if (M) - M->acquire(); - - KeyT typed_new_key = cast<KeySansPointerT>(new_key); - // Can destroy *this: - Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key); - if (Config::FollowRAUW) { - typename ValueMap::MapT::iterator I = Copy.Map->Map.find(Copy); - // I could == Copy.Map->Map.end() if the onRAUW callback already - // removed the old mapping. - if (I != Copy.Map->Map.end()) { - ValueT Target(I->second); - Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, Target)); - } - } - if (M) - M->release(); - } -}; - -template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT> -struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> > { - typedef ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> VH; - typedef DenseMapInfo<KeyT> PointerInfo; - - static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), NULL); - } - static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), NULL); - } - static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); - } - static bool isEqual(const VH &LHS, const VH &RHS) { - return LHS == RHS; - } - static bool isPod() { return false; } -}; - - -template<typename DenseMapT, typename KeyT> -class ValueMapIterator : - public std::iterator<std::forward_iterator_tag, - std::pair<KeyT, typename DenseMapT::mapped_type>, - ptrdiff_t> { - typedef typename DenseMapT::iterator BaseT; - typedef typename DenseMapT::mapped_type ValueT; - BaseT I; -public: - ValueMapIterator() : I() {} - - ValueMapIterator(BaseT I) : I(I) {} - - BaseT base() const { return I; } - - struct ValueTypeProxy { - const KeyT first; - ValueT& second; - ValueTypeProxy *operator->() { return this; } - operator std::pair<KeyT, ValueT>() const { - return std::make_pair(first, second); - } - }; - - ValueTypeProxy operator*() const { - ValueTypeProxy Result = {I->first.Unwrap(), I->second}; - return Result; - } - - ValueTypeProxy operator->() const { - return operator*(); - } - - bool operator==(const ValueMapIterator &RHS) const { - return I == RHS.I; - } - bool operator!=(const ValueMapIterator &RHS) const { - return I != RHS.I; - } - - inline ValueMapIterator& operator++() { // Preincrement - ++I; - return *this; - } - ValueMapIterator operator++(int) { // Postincrement - ValueMapIterator tmp = *this; ++*this; return tmp; - } -}; - -template<typename DenseMapT, typename KeyT> -class ValueMapConstIterator : - public std::iterator<std::forward_iterator_tag, - std::pair<KeyT, typename DenseMapT::mapped_type>, - ptrdiff_t> { - typedef typename DenseMapT::const_iterator BaseT; - typedef typename DenseMapT::mapped_type ValueT; - BaseT I; -public: - ValueMapConstIterator() : I() {} - ValueMapConstIterator(BaseT I) : I(I) {} - ValueMapConstIterator(ValueMapIterator<DenseMapT, KeyT> Other) - : I(Other.base()) {} - - BaseT base() const { return I; } - - struct ValueTypeProxy { - const KeyT first; - const ValueT& second; - ValueTypeProxy *operator->() { return this; } - operator std::pair<KeyT, ValueT>() const { - return std::make_pair(first, second); - } - }; - - ValueTypeProxy operator*() const { - ValueTypeProxy Result = {I->first.Unwrap(), I->second}; - return Result; - } - - ValueTypeProxy operator->() const { - return operator*(); - } - - bool operator==(const ValueMapConstIterator &RHS) const { - return I == RHS.I; - } - bool operator!=(const ValueMapConstIterator &RHS) const { - return I != RHS.I; - } - - inline ValueMapConstIterator& operator++() { // Preincrement - ++I; - return *this; - } - ValueMapConstIterator operator++(int) { // Postincrement - ValueMapConstIterator tmp = *this; ++*this; return tmp; - } -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index cfaae4b841..5f799b850d 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -87,15 +87,6 @@ struct is_base_of { sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0)); }; -// remove_pointer - Metafunction to turn Foo* into Foo. Defined in -// C++0x [meta.trans.ptr]. -template <typename T> struct remove_pointer { typedef T type; }; -template <typename T> struct remove_pointer<T*> { typedef T type; }; -template <typename T> struct remove_pointer<T*const> { typedef T type; }; -template <typename T> struct remove_pointer<T*volatile> { typedef T type; }; -template <typename T> struct remove_pointer<T*const volatile> { - typedef T type; }; - } #endif diff --git a/unittests/ADT/ValueMapTest.cpp b/unittests/ADT/ValueMapTest.cpp deleted file mode 100644 index 9de340c3f3..0000000000 --- a/unittests/ADT/ValueMapTest.cpp +++ /dev/null @@ -1,291 +0,0 @@ -//===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap unit tests -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/ValueMap.h" - -#include "llvm/Instructions.h" -#include "llvm/ADT/OwningPtr.h" - -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -// Test fixture -template<typename T> -class ValueMapTest : public testing::Test { -protected: - Constant *ConstantV; - OwningPtr<BitCastInst> BitcastV; - OwningPtr<BinaryOperator> AddV; - - ValueMapTest() : - ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), - BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))), - AddV(BinaryOperator::CreateAdd(ConstantV, ConstantV)) { - } -}; - -// Run everything on Value*, a subtype to make sure that casting works as -// expected, and a const subtype to make sure we cast const correctly. -typedef ::testing::Types<Value, Instruction, const Instruction> KeyTypes; -TYPED_TEST_CASE(ValueMapTest, KeyTypes); - -TYPED_TEST(ValueMapTest, Null) { - ValueMap<TypeParam*, int> VM1; - VM1[NULL] = 7; - EXPECT_EQ(7, VM1.lookup(NULL)); -} - -TYPED_TEST(ValueMapTest, FollowsValue) { - ValueMap<TypeParam*, int> VM; - VM[this->BitcastV.get()] = 7; - EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.count(this->AddV.get())); - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_EQ(7, VM.lookup(this->AddV.get())); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); - this->AddV.reset(); - EXPECT_EQ(0, VM.count(this->AddV.get())); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); - EXPECT_EQ(0U, VM.size()); -} - -TYPED_TEST(ValueMapTest, OperationsWork) { - ValueMap<TypeParam*, int> VM; - ValueMap<TypeParam*, int> VM2(16); - typename ValueMapConfig<TypeParam*>::ExtraData Data; - ValueMap<TypeParam*, int> VM3(Data, 16); - EXPECT_TRUE(VM.empty()); - - VM[this->BitcastV.get()] = 7; - - // Find: - typename ValueMap<TypeParam*, int>::iterator I = - VM.find(this->BitcastV.get()); - ASSERT_TRUE(I != VM.end()); - EXPECT_EQ(this->BitcastV.get(), I->first); - EXPECT_EQ(7, I->second); - EXPECT_TRUE(VM.find(this->AddV.get()) == VM.end()); - - // Const find: - const ValueMap<TypeParam*, int> &CVM = VM; - typename ValueMap<TypeParam*, int>::const_iterator CI = - CVM.find(this->BitcastV.get()); - ASSERT_TRUE(CI != CVM.end()); - EXPECT_EQ(this->BitcastV.get(), CI->first); - EXPECT_EQ(7, CI->second); - EXPECT_TRUE(CVM.find(this->AddV.get()) == CVM.end()); - - // Insert: - std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult1 = - VM.insert(std::make_pair(this->AddV.get(), 3)); - EXPECT_EQ(this->AddV.get(), InsertResult1.first->first); - EXPECT_EQ(3, InsertResult1.first->second); - EXPECT_TRUE(InsertResult1.second); - EXPECT_EQ(true, VM.count(this->AddV.get())); - std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult2 = - VM.insert(std::make_pair(this->AddV.get(), 5)); - EXPECT_EQ(this->AddV.get(), InsertResult2.first->first); - EXPECT_EQ(3, InsertResult2.first->second); - EXPECT_FALSE(InsertResult2.second); - - // Erase: - VM.erase(InsertResult2.first); - EXPECT_EQ(false, VM.count(this->AddV.get())); - EXPECT_EQ(true, VM.count(this->BitcastV.get())); - VM.erase(this->BitcastV.get()); - EXPECT_EQ(false, VM.count(this->BitcastV.get())); - EXPECT_EQ(0U, VM.size()); - - // Range insert: - SmallVector<std::pair<Instruction*, int>, 2> Elems; - Elems.push_back(std::make_pair(this->AddV.get(), 1)); - Elems.push_back(std::make_pair(this->BitcastV.get(), 2)); - VM.insert(Elems.begin(), Elems.end()); - EXPECT_EQ(1, VM.lookup(this->AddV.get())); - EXPECT_EQ(2, VM.lookup(this->BitcastV.get())); -} - -template<typename ExpectedType, typename VarType> -void CompileAssertHasType(VarType) { - typedef char assert[is_same<ExpectedType, VarType>::value ? 1 : -1]; -} - -TYPED_TEST(ValueMapTest, Iteration) { - ValueMap<TypeParam*, int> VM; - VM[this->BitcastV.get()] = 2; - VM[this->AddV.get()] = 3; - size_t size = 0; - for (typename ValueMap<TypeParam*, int>::iterator I = VM.begin(), E = VM.end(); - I != E; ++I) { - ++size; - std::pair<TypeParam*, int> value = *I; - CompileAssertHasType<TypeParam*>(I->first); - if (I->second == 2) { - EXPECT_EQ(this->BitcastV.get(), I->first); - I->second = 5; - } else if (I->second == 3) { - EXPECT_EQ(this->AddV.get(), I->first); - I->second = 6; - } else { - ADD_FAILURE() << "Iterated through an extra value."; - } - } - EXPECT_EQ(2U, size); - EXPECT_EQ(5, VM[this->BitcastV.get()]); - EXPECT_EQ(6, VM[this->AddV.get()]); - - size = 0; - // Cast to const ValueMap to avoid a bug in DenseMap's iterators. - const ValueMap<TypeParam*, int>& CVM = VM; - for (typename ValueMap<TypeParam*, int>::const_iterator I = CVM.begin(), - E = CVM.end(); I != E; ++I) { - ++size; - std::pair<TypeParam*, int> value = *I; - CompileAssertHasType<TypeParam*>(I->first); - if (I->second == 5) { - EXPECT_EQ(this->BitcastV.get(), I->first); - } else if (I->second == 6) { - EXPECT_EQ(this->AddV.get(), I->first); - } else { - ADD_FAILURE() << "Iterated through an extra value."; - } - } - EXPECT_EQ(2U, size); -} - -TYPED_TEST(ValueMapTest, DefaultCollisionBehavior) { - // By default, we overwrite the old value with the replaced value. - ValueMap<TypeParam*, int> VM; - VM[this->BitcastV.get()] = 7; - VM[this->AddV.get()] = 9; - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); - EXPECT_EQ(9, VM.lookup(this->AddV.get())); -} - -TYPED_TEST(ValueMapTest, ConfiguredCollisionBehavior) { - // TODO: Implement this when someone needs it. -} - -template<typename KeyT> -struct LockMutex : ValueMapConfig<KeyT> { - struct ExtraData { - sys::Mutex *M; - bool *CalledRAUW; - bool *CalledDeleted; - }; - static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) { - *Data.CalledRAUW = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; - } - static void onDeleted(const ExtraData &Data, KeyT Old) { - *Data.CalledDeleted = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; - } - static sys::Mutex *getMutex(const ExtraData &Data) { return Data.M; } -}; -TYPED_TEST(ValueMapTest, LocksMutex) { - sys::Mutex M(false); // Not recursive. - bool CalledRAUW = false, CalledDeleted = false; - typename LockMutex<TypeParam*>::ExtraData Data = - {&M, &CalledRAUW, &CalledDeleted}; - ValueMap<TypeParam*, int, LockMutex<TypeParam*> > VM(Data); - VM[this->BitcastV.get()] = 7; - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - this->AddV.reset(); - EXPECT_TRUE(CalledRAUW); - EXPECT_TRUE(CalledDeleted); -} - -template<typename KeyT> -struct NoFollow : ValueMapConfig<KeyT> { - enum { FollowRAUW = false }; -}; - -TYPED_TEST(ValueMapTest, NoFollowRAUW) { - ValueMap<TypeParam*, int, NoFollow<TypeParam*> > VM; - VM[this->BitcastV.get()] = 7; - EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.count(this->AddV.get())); - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.lookup(this->AddV.get())); - this->AddV.reset(); - EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.lookup(this->AddV.get())); - this->BitcastV.reset(); - EXPECT_EQ(0, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.lookup(this->AddV.get())); - EXPECT_EQ(0U, VM.size()); -} - -template<typename KeyT> -struct CountOps : ValueMapConfig<KeyT> { - struct ExtraData { - int *Deletions; - int *RAUWs; - }; - - static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) { - ++*Data.RAUWs; - } - static void onDeleted(const ExtraData &Data, KeyT Old) { - ++*Data.Deletions; - } -}; - -TYPED_TEST(ValueMapTest, CallsConfig) { - int Deletions = 0, RAUWs = 0; - typename CountOps<TypeParam*>::ExtraData Data = {&Deletions, &RAUWs}; - ValueMap<TypeParam*, int, CountOps<TypeParam*> > VM(Data); - VM[this->BitcastV.get()] = 7; - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_EQ(0, Deletions); - EXPECT_EQ(1, RAUWs); - this->AddV.reset(); - EXPECT_EQ(1, Deletions); - EXPECT_EQ(1, RAUWs); - this->BitcastV.reset(); - EXPECT_EQ(1, Deletions); - EXPECT_EQ(1, RAUWs); -} - -template<typename KeyT> -struct ModifyingConfig : ValueMapConfig<KeyT> { - // We'll put a pointer here back to the ValueMap this key is in, so - // that we can modify it (and clobber *this) before the ValueMap - // tries to do the same modification. In previous versions of - // ValueMap, that exploded. - typedef ValueMap<KeyT, int, ModifyingConfig<KeyT> > **ExtraData; - - static void onRAUW(ExtraData Map, KeyT Old, KeyT New) { - (*Map)->erase(Old); - } - static void onDeleted(ExtraData Map, KeyT Old) { - (*Map)->erase(Old); - } -}; -TYPED_TEST(ValueMapTest, SurvivesModificationByConfig) { - ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > *MapAddress; - ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > VM(&MapAddress); - MapAddress = &VM; - // Now the ModifyingConfig can modify the Map inside a callback. - VM[this->BitcastV.get()] = 7; - this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_FALSE(VM.count(this->BitcastV.get())); - EXPECT_FALSE(VM.count(this->AddV.get())); - VM[this->AddV.get()] = 7; - this->AddV.reset(); - EXPECT_FALSE(VM.count(this->AddV.get())); -} - -} |