166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap unit tests -*- C++ -*-===//
266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//
366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//                     The LLVM Compiler Infrastructure
466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//
566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file is distributed under the University of Illinois Open Source
666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// License. See LICENSE.TXT for details.
766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//
866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===//
966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/ADT/ValueMap.h"
1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Constants.h"
1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Instructions.h"
1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/LLVMContext.h"
1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/ADT/OwningPtr.h"
1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Config/config.h"
1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "gtest/gtest.h"
1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm;
2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace {
2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Test fixture
2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename T>
2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanclass ValueMapTest : public testing::Test {
2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanprotected:
2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  Constant *ConstantV;
2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  OwningPtr<BitCastInst> BitcastV;
2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  OwningPtr<BinaryOperator> AddV;
3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMapTest() :
3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))),
3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    AddV(BinaryOperator::CreateAdd(ConstantV, ConstantV)) {
3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman};
3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Run everything on Value*, a subtype to make sure that casting works as
3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// expected, and a const subtype to make sure we cast const correctly.
4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantypedef ::testing::Types<Value, Instruction, const Instruction> KeyTypes;
4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST_CASE(ValueMapTest, KeyTypes);
4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, Null) {
4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM1;
4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM1[NULL] = 7;
4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM1.lookup(NULL));
4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, FollowsValue) {
5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM;
5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->AddV.get()));
5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM.lookup(this->AddV.get()));
5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->BitcastV.get()));
5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->AddV.reset();
5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->AddV.get()));
5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->BitcastV.get()));
6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0U, VM.size());
6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, OperationsWork) {
6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM;
6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM2(16);  (void)VM2;
6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typename ValueMapConfig<TypeParam*>::ExtraData Data;
6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM3(Data, 16);  (void)VM3;
6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(VM.empty());
6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Find:
7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typename ValueMap<TypeParam*, int>::iterator I =
7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    VM.find(this->BitcastV.get());
7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ASSERT_TRUE(I != VM.end());
7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(this->BitcastV.get(), I->first);
7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, I->second);
7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(VM.find(this->AddV.get()) == VM.end());
7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Const find:
8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  const ValueMap<TypeParam*, int> &CVM = VM;
8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typename ValueMap<TypeParam*, int>::const_iterator CI =
8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    CVM.find(this->BitcastV.get());
8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ASSERT_TRUE(CI != CVM.end());
8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(this->BitcastV.get(), CI->first);
8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, CI->second);
8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(CVM.find(this->AddV.get()) == CVM.end());
8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Insert:
9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult1 =
9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    VM.insert(std::make_pair(this->AddV.get(), 3));
9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(this->AddV.get(), InsertResult1.first->first);
9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(3, InsertResult1.first->second);
9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(InsertResult1.second);
9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(true, VM.count(this->AddV.get()));
9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult2 =
9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    VM.insert(std::make_pair(this->AddV.get(), 5));
9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(this->AddV.get(), InsertResult2.first->first);
9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(3, InsertResult2.first->second);
10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_FALSE(InsertResult2.second);
10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Erase:
10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM.erase(InsertResult2.first);
10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0U, VM.count(this->AddV.get()));
10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1U, VM.count(this->BitcastV.get()));
10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM.erase(this->BitcastV.get());
10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0U, VM.count(this->BitcastV.get()));
10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0U, VM.size());
10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Range insert:
11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  SmallVector<std::pair<Instruction*, int>, 2> Elems;
11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  Elems.push_back(std::make_pair(this->AddV.get(), 1));
11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  Elems.push_back(std::make_pair(this->BitcastV.get(), 2));
11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM.insert(Elems.begin(), Elems.end());
11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, VM.lookup(this->AddV.get()));
11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(2, VM.lookup(this->BitcastV.get()));
11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename ExpectedType, typename VarType>
12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid CompileAssertHasType(VarType) {
12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typedef char assert[is_same<ExpectedType, VarType>::value ? 1 : -1];
12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
12366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
12466b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, Iteration) {
12566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM;
12666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 2;
12766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->AddV.get()] = 3;
12866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  size_t size = 0;
12966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  for (typename ValueMap<TypeParam*, int>::iterator I = VM.begin(), E = VM.end();
13066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman       I != E; ++I) {
13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    ++size;
13266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    std::pair<TypeParam*, int> value = *I; (void)value;
13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    CompileAssertHasType<TypeParam*>(I->first);
13466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    if (I->second == 2) {
13566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      EXPECT_EQ(this->BitcastV.get(), I->first);
13666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      I->second = 5;
13766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    } else if (I->second == 3) {
13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      EXPECT_EQ(this->AddV.get(), I->first);
13966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      I->second = 6;
14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    } else {
14166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      ADD_FAILURE() << "Iterated through an extra value.";
14266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    }
14366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
14466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(2U, size);
14566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(5, VM[this->BitcastV.get()]);
14666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(6, VM[this->AddV.get()]);
14766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
14866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  size = 0;
14966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
15066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  const ValueMap<TypeParam*, int>& CVM = VM;
15166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  for (typename ValueMap<TypeParam*, int>::const_iterator I = CVM.begin(),
15266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman         E = CVM.end(); I != E; ++I) {
15366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    ++size;
15466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    std::pair<TypeParam*, int> value = *I;  (void)value;
15566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    CompileAssertHasType<TypeParam*>(I->first);
15666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    if (I->second == 5) {
15766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      EXPECT_EQ(this->BitcastV.get(), I->first);
15866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    } else if (I->second == 6) {
15966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      EXPECT_EQ(this->AddV.get(), I->first);
16066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    } else {
16166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman      ADD_FAILURE() << "Iterated through an extra value.";
16266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    }
16366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
16466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(2U, size);
16566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
16666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
16766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, DefaultCollisionBehavior) {
16866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // By default, we overwrite the old value with the replaced value.
16966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int> VM;
17066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
17166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->AddV.get()] = 9;
17266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
17366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->BitcastV.get()));
17466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(9, VM.lookup(this->AddV.get()));
17566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
17666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
17766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, ConfiguredCollisionBehavior) {
17866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // TODO: Implement this when someone needs it.
17966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
18066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
18166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename KeyT>
18266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstruct LockMutex : ValueMapConfig<KeyT> {
18366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  struct ExtraData {
18466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    sys::Mutex *M;
18566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    bool *CalledRAUW;
18666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    bool *CalledDeleted;
18766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  };
18866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
18966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    *Data.CalledRAUW = true;
19066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked.";
19166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
19266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onDelete(const ExtraData &Data, KeyT Old) {
19366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    *Data.CalledDeleted = true;
19466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked.";
19566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
19666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static sys::Mutex *getMutex(const ExtraData &Data) { return Data.M; }
19766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman};
19866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#if ENABLE_THREADS
19966b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, LocksMutex) {
20066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  sys::Mutex M(false);  // Not recursive.
20166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  bool CalledRAUW = false, CalledDeleted = false;
20266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typename LockMutex<TypeParam*>::ExtraData Data =
20366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    {&M, &CalledRAUW, &CalledDeleted};
20466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int, LockMutex<TypeParam*> > VM(Data);
20566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
20666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
20766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->AddV.reset();
20866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(CalledRAUW);
20966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_TRUE(CalledDeleted);
21066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
21166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#endif
21266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
21366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename KeyT>
21466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstruct NoFollow : ValueMapConfig<KeyT> {
21566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  enum { FollowRAUW = false };
21666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman};
21766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
21866b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, NoFollowRAUW) {
21966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int, NoFollow<TypeParam*> > VM;
22066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
22166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
22266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.count(this->AddV.get()));
22366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
22466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
22566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
22666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->AddV.reset();
22766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
22866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
22966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV.reset();
23066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.lookup(this->BitcastV.get()));
23166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
23266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0U, VM.size());
23366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
23466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
23566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename KeyT>
23666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstruct CountOps : ValueMapConfig<KeyT> {
23766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  struct ExtraData {
23866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    int *Deletions;
23966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    int *RAUWs;
24066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  };
24166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
24266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
24366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    ++*Data.RAUWs;
24466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
24566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onDelete(const ExtraData &Data, KeyT Old) {
24666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    ++*Data.Deletions;
24766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
24866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman};
24966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
25066b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, CallsConfig) {
25166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  int Deletions = 0, RAUWs = 0;
25266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typename CountOps<TypeParam*>::ExtraData Data = {&Deletions, &RAUWs};
25366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int, CountOps<TypeParam*> > VM(Data);
25466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
25566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
25666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(0, Deletions);
25766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, RAUWs);
25866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->AddV.reset();
25966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, Deletions);
26066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, RAUWs);
26166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV.reset();
26266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, Deletions);
26366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_EQ(1, RAUWs);
26466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
26566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
26666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename KeyT>
26766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstruct ModifyingConfig : ValueMapConfig<KeyT> {
26866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // We'll put a pointer here back to the ValueMap this key is in, so
26966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // that we can modify it (and clobber *this) before the ValueMap
27066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // tries to do the same modification.  In previous versions of
27166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // ValueMap, that exploded.
27266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  typedef ValueMap<KeyT, int, ModifyingConfig<KeyT> > **ExtraData;
27366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
27466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onRAUW(ExtraData Map, KeyT Old, KeyT New) {
27566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    (*Map)->erase(Old);
27666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
27766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  static void onDelete(ExtraData Map, KeyT Old) {
27866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman    (*Map)->erase(Old);
27966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  }
28066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman};
28166b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanTYPED_TEST(ValueMapTest, SurvivesModificationByConfig) {
28266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > *MapAddress;
28366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > VM(&MapAddress);
28466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  MapAddress = &VM;
28566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  // Now the ModifyingConfig can modify the Map inside a callback.
28666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->BitcastV.get()] = 7;
28766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->BitcastV->replaceAllUsesWith(this->AddV.get());
28866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_FALSE(VM.count(this->BitcastV.get()));
28966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_FALSE(VM.count(this->AddV.get()));
29066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  VM[this->AddV.get()] = 7;
29166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  this->AddV.reset();
29266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman  EXPECT_FALSE(VM.count(this->AddV.get()));
29366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
29466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
29566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}
296