Avoid emitting a dbg_value machineinstr that's not going to be inserted into entry...
[oota-llvm.git] / unittests / Support / ValueHandleTest.cpp
index d9a5515f78ed54d1fdb262cfc182a6d21b82cad5..6a6528fbddfbbe91e27468702ed43252e28c2709 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "llvm/Constants.h"
 #include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/ADT/OwningPtr.h"
 
 #include "gtest/gtest.h"
 
@@ -26,8 +28,8 @@ protected:
   std::auto_ptr<BitCastInst> BitcastV;
 
   ValueHandle() :
-    ConstantV(ConstantInt::get(Type::Int32Ty, 0)),
-    BitcastV(new BitCastInst(ConstantV, Type::Int32Ty)) {
+    ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
+    BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) {
   }
 };
 
@@ -45,8 +47,8 @@ TEST_F(ValueHandle, WeakVH_BasicOperation) {
 
   // Make sure I can call a method on the underlying Value.  It
   // doesn't matter which method.
-  EXPECT_EQ(Type::Int32Ty, WVH->getType());
-  EXPECT_EQ(Type::Int32Ty, (*WVH).getType());
+  EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType());
+  EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType());
 }
 
 TEST_F(ValueHandle, WeakVH_Comparisons) {
@@ -120,6 +122,13 @@ TEST_F(ValueHandle, AssertingVH_BasicOperation) {
   EXPECT_FALSE((*AVH).mayWriteToMemory());
 }
 
+TEST_F(ValueHandle, AssertingVH_Const) {
+  const CastInst *ConstBitcast = BitcastV.get();
+  AssertingVH<const CastInst> AVH(ConstBitcast);
+  const CastInst *implicit_to_exact_type = AVH;
+  implicit_to_exact_type = implicit_to_exact_type;  // Avoid warning.
+}
+
 TEST_F(ValueHandle, AssertingVH_Comparisons) {
   AssertingVH<Value> BitcastAVH(BitcastV.get());
   AssertingVH<Value> ConstantAVH(ConstantV);
@@ -193,8 +202,8 @@ TEST_F(ValueHandle, CallbackVH_BasicOperation) {
 
   // Make sure I can call a method on the underlying Value.  It
   // doesn't matter which method.
-  EXPECT_EQ(Type::Int32Ty, CVH->getType());
-  EXPECT_EQ(Type::Int32Ty, (*CVH).getType());
+  EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType());
+  EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType());
 }
 
 TEST_F(ValueHandle, CallbackVH_Comparisons) {
@@ -295,7 +304,7 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
 
   private:
     virtual void deleted() {
-      getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::Int32Ty));
+      getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())));
       setValPtr(NULL);
     }
     virtual void allUsesReplacedWith(Value *new_value) {
@@ -312,12 +321,92 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
   RVH = BitcastV.get();
   std::auto_ptr<BinaryOperator> BitcastUser(
     BinaryOperator::CreateAdd(RVH, 
-                              Constant::getNullValue(Type::Int32Ty)));
+                              Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))));
   EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0));
   BitcastV.reset();  // Would crash without the ValueHandler.
-  EXPECT_EQ(Constant::getNullValue(Type::Int32Ty), RVH.AURWArgument);
-  EXPECT_EQ(Constant::getNullValue(Type::Int32Ty),
+  EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument);
+  EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())),
             BitcastUser->getOperand(0));
 }
 
+TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) {
+  // When a CallbackVH modifies other ValueHandles in its callbacks,
+  // that shouldn't interfere with non-modified ValueHandles receiving
+  // their appropriate callbacks.
+  //
+  // We create the active CallbackVH in the middle of a palindromic
+  // arrangement of other VHs so that the bad behavior would be
+  // triggered in whichever order callbacks run.
+
+  class DestroyingVH : public CallbackVH {
+  public:
+    OwningPtr<WeakVH> ToClear[2];
+    DestroyingVH(Value *V) {
+      ToClear[0].reset(new WeakVH(V));
+      setValPtr(V);
+      ToClear[1].reset(new WeakVH(V));
+    }
+    virtual void deleted() {
+      ToClear[0].reset();
+      ToClear[1].reset();
+      CallbackVH::deleted();
+    }
+    virtual void allUsesReplacedWith(Value *) {
+      ToClear[0].reset();
+      ToClear[1].reset();
+    }
+  };
+
+  {
+    WeakVH ShouldBeVisited1(BitcastV.get());
+    DestroyingVH C(BitcastV.get());
+    WeakVH ShouldBeVisited2(BitcastV.get());
+
+    BitcastV->replaceAllUsesWith(ConstantV);
+    EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
+    EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
+  }
+
+  {
+    WeakVH ShouldBeVisited1(BitcastV.get());
+    DestroyingVH C(BitcastV.get());
+    WeakVH ShouldBeVisited2(BitcastV.get());
+
+    BitcastV.reset();
+    EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1));
+    EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2));
+  }
+}
+
+TEST_F(ValueHandle, AssertingVHCheckedLast) {
+  // If a CallbackVH exists to clear out a group of AssertingVHs on
+  // Value deletion, the CallbackVH should get a chance to do so
+  // before the AssertingVHs assert.
+
+  class ClearingVH : public CallbackVH {
+  public:
+    AssertingVH<Value> *ToClear[2];
+    ClearingVH(Value *V,
+               AssertingVH<Value> &A0, AssertingVH<Value> &A1)
+      : CallbackVH(V) {
+      ToClear[0] = &A0;
+      ToClear[1] = &A1;
+    }
+
+    virtual void deleted() {
+      *ToClear[0] = 0;
+      *ToClear[1] = 0;
+      CallbackVH::deleted();
+    }
+  };
+
+  AssertingVH<Value> A1, A2;
+  A1 = BitcastV.get();
+  ClearingVH C(BitcastV.get(), A1, A2);
+  A2 = BitcastV.get();
+  // C.deleted() should run first, clearing the two AssertingVHs,
+  // which should prevent them from asserting.
+  BitcastV.reset();
+}
+
 }