Home | History | Annotate | Download | only in Support
      1 //===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle tests --------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Support/ValueHandle.h"
     11 #include "llvm/ADT/OwningPtr.h"
     12 #include "llvm/IR/Constants.h"
     13 #include "llvm/IR/Instructions.h"
     14 #include "llvm/IR/LLVMContext.h"
     15 #include "gtest/gtest.h"
     16 #include <memory>
     17 
     18 using namespace llvm;
     19 
     20 namespace {
     21 
     22 class ValueHandle : public testing::Test {
     23 protected:
     24   Constant *ConstantV;
     25   std::auto_ptr<BitCastInst> BitcastV;
     26 
     27   ValueHandle() :
     28     ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
     29     BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) {
     30   }
     31 };
     32 
     33 class ConcreteCallbackVH : public CallbackVH {
     34 public:
     35   ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
     36 };
     37 
     38 TEST_F(ValueHandle, WeakVH_BasicOperation) {
     39   WeakVH WVH(BitcastV.get());
     40   EXPECT_EQ(BitcastV.get(), WVH);
     41   WVH = ConstantV;
     42   EXPECT_EQ(ConstantV, WVH);
     43 
     44   // Make sure I can call a method on the underlying Value.  It
     45   // doesn't matter which method.
     46   EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType());
     47   EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType());
     48 }
     49 
     50 TEST_F(ValueHandle, WeakVH_Comparisons) {
     51   WeakVH BitcastWVH(BitcastV.get());
     52   WeakVH ConstantWVH(ConstantV);
     53 
     54   EXPECT_TRUE(BitcastWVH == BitcastWVH);
     55   EXPECT_TRUE(BitcastV.get() == BitcastWVH);
     56   EXPECT_TRUE(BitcastWVH == BitcastV.get());
     57   EXPECT_FALSE(BitcastWVH == ConstantWVH);
     58 
     59   EXPECT_TRUE(BitcastWVH != ConstantWVH);
     60   EXPECT_TRUE(BitcastV.get() != ConstantWVH);
     61   EXPECT_TRUE(BitcastWVH != ConstantV);
     62   EXPECT_FALSE(BitcastWVH != BitcastWVH);
     63 
     64   // Cast to Value* so comparisons work.
     65   Value *BV = BitcastV.get();
     66   Value *CV = ConstantV;
     67   EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH);
     68   EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH);
     69   EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH);
     70   EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH);
     71 
     72   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH);
     73   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH);
     74   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH);
     75   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH);
     76 
     77   EXPECT_EQ(BV < CV, BitcastWVH < ConstantV);
     78   EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV);
     79   EXPECT_EQ(BV > CV, BitcastWVH > ConstantV);
     80   EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV);
     81 }
     82 
     83 TEST_F(ValueHandle, WeakVH_FollowsRAUW) {
     84   WeakVH WVH(BitcastV.get());
     85   WeakVH WVH_Copy(WVH);
     86   WeakVH WVH_Recreated(BitcastV.get());
     87   BitcastV->replaceAllUsesWith(ConstantV);
     88   EXPECT_EQ(ConstantV, WVH);
     89   EXPECT_EQ(ConstantV, WVH_Copy);
     90   EXPECT_EQ(ConstantV, WVH_Recreated);
     91 }
     92 
     93 TEST_F(ValueHandle, WeakVH_NullOnDeletion) {
     94   WeakVH WVH(BitcastV.get());
     95   WeakVH WVH_Copy(WVH);
     96   WeakVH WVH_Recreated(BitcastV.get());
     97   BitcastV.reset();
     98   Value *null_value = NULL;
     99   EXPECT_EQ(null_value, WVH);
    100   EXPECT_EQ(null_value, WVH_Copy);
    101   EXPECT_EQ(null_value, WVH_Recreated);
    102 }
    103 
    104 
    105 TEST_F(ValueHandle, AssertingVH_BasicOperation) {
    106   AssertingVH<CastInst> AVH(BitcastV.get());
    107   CastInst *implicit_to_exact_type = AVH;
    108   (void)implicit_to_exact_type;  // Avoid warning.
    109 
    110   AssertingVH<Value> GenericAVH(BitcastV.get());
    111   EXPECT_EQ(BitcastV.get(), GenericAVH);
    112   GenericAVH = ConstantV;
    113   EXPECT_EQ(ConstantV, GenericAVH);
    114 
    115   // Make sure I can call a method on the underlying CastInst.  It
    116   // doesn't matter which method.
    117   EXPECT_FALSE(AVH->mayWriteToMemory());
    118   EXPECT_FALSE((*AVH).mayWriteToMemory());
    119 }
    120 
    121 TEST_F(ValueHandle, AssertingVH_Const) {
    122   const CastInst *ConstBitcast = BitcastV.get();
    123   AssertingVH<const CastInst> AVH(ConstBitcast);
    124   const CastInst *implicit_to_exact_type = AVH;
    125   (void)implicit_to_exact_type;  // Avoid warning.
    126 }
    127 
    128 TEST_F(ValueHandle, AssertingVH_Comparisons) {
    129   AssertingVH<Value> BitcastAVH(BitcastV.get());
    130   AssertingVH<Value> ConstantAVH(ConstantV);
    131 
    132   EXPECT_TRUE(BitcastAVH == BitcastAVH);
    133   EXPECT_TRUE(BitcastV.get() == BitcastAVH);
    134   EXPECT_TRUE(BitcastAVH == BitcastV.get());
    135   EXPECT_FALSE(BitcastAVH == ConstantAVH);
    136 
    137   EXPECT_TRUE(BitcastAVH != ConstantAVH);
    138   EXPECT_TRUE(BitcastV.get() != ConstantAVH);
    139   EXPECT_TRUE(BitcastAVH != ConstantV);
    140   EXPECT_FALSE(BitcastAVH != BitcastAVH);
    141 
    142   // Cast to Value* so comparisons work.
    143   Value *BV = BitcastV.get();
    144   Value *CV = ConstantV;
    145   EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH);
    146   EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH);
    147   EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH);
    148   EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH);
    149 
    150   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH);
    151   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH);
    152   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH);
    153   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH);
    154 
    155   EXPECT_EQ(BV < CV, BitcastAVH < ConstantV);
    156   EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV);
    157   EXPECT_EQ(BV > CV, BitcastAVH > ConstantV);
    158   EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV);
    159 }
    160 
    161 TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) {
    162   AssertingVH<Value> AVH(BitcastV.get());
    163   BitcastV->replaceAllUsesWith(ConstantV);
    164   EXPECT_EQ(BitcastV.get(), AVH);
    165 }
    166 
    167 #ifdef NDEBUG
    168 
    169 TEST_F(ValueHandle, AssertingVH_ReducesToPointer) {
    170   EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>));
    171 }
    172 
    173 #else  // !NDEBUG
    174 
    175 #ifdef GTEST_HAS_DEATH_TEST
    176 
    177 TEST_F(ValueHandle, AssertingVH_Asserts) {
    178   AssertingVH<Value> AVH(BitcastV.get());
    179   EXPECT_DEATH({BitcastV.reset();},
    180                "An asserting value handle still pointed to this value!");
    181   AssertingVH<Value> Copy(AVH);
    182   AVH = NULL;
    183   EXPECT_DEATH({BitcastV.reset();},
    184                "An asserting value handle still pointed to this value!");
    185   Copy = NULL;
    186   BitcastV.reset();
    187 }
    188 
    189 #endif  // GTEST_HAS_DEATH_TEST
    190 
    191 #endif  // NDEBUG
    192 
    193 TEST_F(ValueHandle, CallbackVH_BasicOperation) {
    194   ConcreteCallbackVH CVH(BitcastV.get());
    195   EXPECT_EQ(BitcastV.get(), CVH);
    196   CVH = ConstantV;
    197   EXPECT_EQ(ConstantV, CVH);
    198 
    199   // Make sure I can call a method on the underlying Value.  It
    200   // doesn't matter which method.
    201   EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType());
    202   EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType());
    203 }
    204 
    205 TEST_F(ValueHandle, CallbackVH_Comparisons) {
    206   ConcreteCallbackVH BitcastCVH(BitcastV.get());
    207   ConcreteCallbackVH ConstantCVH(ConstantV);
    208 
    209   EXPECT_TRUE(BitcastCVH == BitcastCVH);
    210   EXPECT_TRUE(BitcastV.get() == BitcastCVH);
    211   EXPECT_TRUE(BitcastCVH == BitcastV.get());
    212   EXPECT_FALSE(BitcastCVH == ConstantCVH);
    213 
    214   EXPECT_TRUE(BitcastCVH != ConstantCVH);
    215   EXPECT_TRUE(BitcastV.get() != ConstantCVH);
    216   EXPECT_TRUE(BitcastCVH != ConstantV);
    217   EXPECT_FALSE(BitcastCVH != BitcastCVH);
    218 
    219   // Cast to Value* so comparisons work.
    220   Value *BV = BitcastV.get();
    221   Value *CV = ConstantV;
    222   EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH);
    223   EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH);
    224   EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH);
    225   EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH);
    226 
    227   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH);
    228   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH);
    229   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH);
    230   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH);
    231 
    232   EXPECT_EQ(BV < CV, BitcastCVH < ConstantV);
    233   EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV);
    234   EXPECT_EQ(BV > CV, BitcastCVH > ConstantV);
    235   EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV);
    236 }
    237 
    238 TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) {
    239   class RecordingVH : public CallbackVH {
    240   public:
    241     int DeletedCalls;
    242     int AURWCalls;
    243 
    244     RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
    245     RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {}
    246 
    247   private:
    248     virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); }
    249     virtual void allUsesReplacedWith(Value *) { AURWCalls++; }
    250   };
    251 
    252   RecordingVH RVH;
    253   RVH = BitcastV.get();
    254   EXPECT_EQ(0, RVH.DeletedCalls);
    255   EXPECT_EQ(0, RVH.AURWCalls);
    256   BitcastV.reset();
    257   EXPECT_EQ(1, RVH.DeletedCalls);
    258   EXPECT_EQ(0, RVH.AURWCalls);
    259 }
    260 
    261 TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) {
    262   class RecordingVH : public CallbackVH {
    263   public:
    264     int DeletedCalls;
    265     Value *AURWArgument;
    266 
    267     RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {}
    268     RecordingVH(Value *V)
    269       : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {}
    270 
    271   private:
    272     virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); }
    273     virtual void allUsesReplacedWith(Value *new_value) {
    274       EXPECT_EQ(NULL, AURWArgument);
    275       AURWArgument = new_value;
    276     }
    277   };
    278 
    279   RecordingVH RVH;
    280   RVH = BitcastV.get();
    281   EXPECT_EQ(0, RVH.DeletedCalls);
    282   EXPECT_EQ(NULL, RVH.AURWArgument);
    283   BitcastV->replaceAllUsesWith(ConstantV);
    284   EXPECT_EQ(0, RVH.DeletedCalls);
    285   EXPECT_EQ(ConstantV, RVH.AURWArgument);
    286 }
    287 
    288 TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
    289   class RecoveringVH : public CallbackVH {
    290   public:
    291     int DeletedCalls;
    292     Value *AURWArgument;
    293     LLVMContext *Context;
    294 
    295     RecoveringVH() : DeletedCalls(0), AURWArgument(NULL),
    296                      Context(&getGlobalContext()) {}
    297     RecoveringVH(Value *V)
    298       : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL),
    299         Context(&getGlobalContext()) {}
    300 
    301   private:
    302     virtual void deleted() {
    303       getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())));
    304       setValPtr(NULL);
    305     }
    306     virtual void allUsesReplacedWith(Value *new_value) {
    307       ASSERT_TRUE(NULL != getValPtr());
    308       EXPECT_EQ(1U, getValPtr()->getNumUses());
    309       EXPECT_EQ(NULL, AURWArgument);
    310       AURWArgument = new_value;
    311     }
    312   };
    313 
    314   // Normally, if a value has uses, deleting it will crash.  However, we can use
    315   // a CallbackVH to remove the uses before the check for no uses.
    316   RecoveringVH RVH;
    317   RVH = BitcastV.get();
    318   std::auto_ptr<BinaryOperator> BitcastUser(
    319     BinaryOperator::CreateAdd(RVH,
    320                               Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))));
    321   EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0));
    322   BitcastV.reset();  // Would crash without the ValueHandler.
    323   EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument);
    324   EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())),
    325             BitcastUser->getOperand(0));
    326 }
    327 
    328 TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) {
    329   // When a CallbackVH modifies other ValueHandles in its callbacks,
    330   // that shouldn't interfere with non-modified ValueHandles receiving
    331   // their appropriate callbacks.
    332   //
    333   // We create the active CallbackVH in the middle of a palindromic
    334   // arrangement of other VHs so that the bad behavior would be
    335   // triggered in whichever order callbacks run.
    336 
    337   class DestroyingVH : public CallbackVH {
    338   public:
    339     OwningPtr<WeakVH> ToClear[2];
    340     DestroyingVH(Value *V) {
    341       ToClear[0].reset(new WeakVH(V));
    342       setValPtr(V);
    343       ToClear[1].reset(new WeakVH(V));
    344     }
    345     virtual void deleted() {
    346       ToClear[0].reset();
    347       ToClear[1].reset();
    348       CallbackVH::deleted();
    349     }
    350     virtual void allUsesReplacedWith(Value *) {
    351       ToClear[0].reset();
    352       ToClear[1].reset();
    353     }
    354   };
    355 
    356   {
    357     WeakVH ShouldBeVisited1(BitcastV.get());
    358     DestroyingVH C(BitcastV.get());
    359     WeakVH ShouldBeVisited2(BitcastV.get());
    360 
    361     BitcastV->replaceAllUsesWith(ConstantV);
    362     EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
    363     EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
    364   }
    365 
    366   {
    367     WeakVH ShouldBeVisited1(BitcastV.get());
    368     DestroyingVH C(BitcastV.get());
    369     WeakVH ShouldBeVisited2(BitcastV.get());
    370 
    371     BitcastV.reset();
    372     EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1));
    373     EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2));
    374   }
    375 }
    376 
    377 TEST_F(ValueHandle, AssertingVHCheckedLast) {
    378   // If a CallbackVH exists to clear out a group of AssertingVHs on
    379   // Value deletion, the CallbackVH should get a chance to do so
    380   // before the AssertingVHs assert.
    381 
    382   class ClearingVH : public CallbackVH {
    383   public:
    384     AssertingVH<Value> *ToClear[2];
    385     ClearingVH(Value *V,
    386                AssertingVH<Value> &A0, AssertingVH<Value> &A1)
    387       : CallbackVH(V) {
    388       ToClear[0] = &A0;
    389       ToClear[1] = &A1;
    390     }
    391 
    392     virtual void deleted() {
    393       *ToClear[0] = 0;
    394       *ToClear[1] = 0;
    395       CallbackVH::deleted();
    396     }
    397   };
    398 
    399   AssertingVH<Value> A1, A2;
    400   A1 = BitcastV.get();
    401   ClearingVH C(BitcastV.get(), A1, A2);
    402   A2 = BitcastV.get();
    403   // C.deleted() should run first, clearing the two AssertingVHs,
    404   // which should prevent them from asserting.
    405   BitcastV.reset();
    406 }
    407 
    408 }
    409