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