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