1 //===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/IR/ValueHandle.h"
11 #include "llvm/IR/Constants.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "gtest/gtest.h"
21 class ValueHandle
: public testing::Test
{
25 std::unique_ptr
<BitCastInst
> BitcastV
;
28 : ConstantV(ConstantInt::get(Type::getInt32Ty(Context
), 0)),
29 BitcastV(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
))) {}
32 class ConcreteCallbackVH final
: public CallbackVH
{
34 ConcreteCallbackVH(Value
*V
) : CallbackVH(V
) {}
37 TEST_F(ValueHandle
, WeakVH_BasicOperation
) {
38 WeakVH
WVH(BitcastV
.get());
39 EXPECT_EQ(BitcastV
.get(), WVH
);
41 EXPECT_EQ(ConstantV
, WVH
);
43 // Make sure I can call a method on the underlying Value. It
44 // doesn't matter which method.
45 EXPECT_EQ(Type::getInt32Ty(Context
), WVH
->getType());
46 EXPECT_EQ(Type::getInt32Ty(Context
), (*WVH
).getType());
49 BitcastV
->replaceAllUsesWith(ConstantV
);
50 EXPECT_EQ(WVH
, BitcastV
.get());
52 EXPECT_EQ(WVH
, nullptr);
55 TEST_F(ValueHandle
, WeakTrackingVH_BasicOperation
) {
56 WeakTrackingVH
WVH(BitcastV
.get());
57 EXPECT_EQ(BitcastV
.get(), WVH
);
59 EXPECT_EQ(ConstantV
, WVH
);
61 // Make sure I can call a method on the underlying Value. It
62 // doesn't matter which method.
63 EXPECT_EQ(Type::getInt32Ty(Context
), WVH
->getType());
64 EXPECT_EQ(Type::getInt32Ty(Context
), (*WVH
).getType());
67 TEST_F(ValueHandle
, WeakTrackingVH_Comparisons
) {
68 WeakTrackingVH
BitcastWVH(BitcastV
.get());
69 WeakTrackingVH
ConstantWVH(ConstantV
);
71 EXPECT_TRUE(BitcastWVH
== BitcastWVH
);
72 EXPECT_TRUE(BitcastV
.get() == BitcastWVH
);
73 EXPECT_TRUE(BitcastWVH
== BitcastV
.get());
74 EXPECT_FALSE(BitcastWVH
== ConstantWVH
);
76 EXPECT_TRUE(BitcastWVH
!= ConstantWVH
);
77 EXPECT_TRUE(BitcastV
.get() != ConstantWVH
);
78 EXPECT_TRUE(BitcastWVH
!= ConstantV
);
79 EXPECT_FALSE(BitcastWVH
!= BitcastWVH
);
81 // Cast to Value* so comparisons work.
82 Value
*BV
= BitcastV
.get();
83 Value
*CV
= ConstantV
;
84 EXPECT_EQ(BV
< CV
, BitcastWVH
< ConstantWVH
);
85 EXPECT_EQ(BV
<= CV
, BitcastWVH
<= ConstantWVH
);
86 EXPECT_EQ(BV
> CV
, BitcastWVH
> ConstantWVH
);
87 EXPECT_EQ(BV
>= CV
, BitcastWVH
>= ConstantWVH
);
89 EXPECT_EQ(BV
< CV
, BitcastV
.get() < ConstantWVH
);
90 EXPECT_EQ(BV
<= CV
, BitcastV
.get() <= ConstantWVH
);
91 EXPECT_EQ(BV
> CV
, BitcastV
.get() > ConstantWVH
);
92 EXPECT_EQ(BV
>= CV
, BitcastV
.get() >= ConstantWVH
);
94 EXPECT_EQ(BV
< CV
, BitcastWVH
< ConstantV
);
95 EXPECT_EQ(BV
<= CV
, BitcastWVH
<= ConstantV
);
96 EXPECT_EQ(BV
> CV
, BitcastWVH
> ConstantV
);
97 EXPECT_EQ(BV
>= CV
, BitcastWVH
>= ConstantV
);
100 TEST_F(ValueHandle
, WeakTrackingVH_FollowsRAUW
) {
101 WeakTrackingVH
WVH(BitcastV
.get());
102 WeakTrackingVH
WVH_Copy(WVH
);
103 WeakTrackingVH
WVH_Recreated(BitcastV
.get());
104 BitcastV
->replaceAllUsesWith(ConstantV
);
105 EXPECT_EQ(ConstantV
, WVH
);
106 EXPECT_EQ(ConstantV
, WVH_Copy
);
107 EXPECT_EQ(ConstantV
, WVH_Recreated
);
110 TEST_F(ValueHandle
, WeakTrackingVH_NullOnDeletion
) {
111 WeakTrackingVH
WVH(BitcastV
.get());
112 WeakTrackingVH
WVH_Copy(WVH
);
113 WeakTrackingVH
WVH_Recreated(BitcastV
.get());
115 Value
*null_value
= nullptr;
116 EXPECT_EQ(null_value
, WVH
);
117 EXPECT_EQ(null_value
, WVH_Copy
);
118 EXPECT_EQ(null_value
, WVH_Recreated
);
122 TEST_F(ValueHandle
, AssertingVH_BasicOperation
) {
123 AssertingVH
<CastInst
> AVH(BitcastV
.get());
124 CastInst
*implicit_to_exact_type
= AVH
;
125 (void)implicit_to_exact_type
; // Avoid warning.
127 AssertingVH
<Value
> GenericAVH(BitcastV
.get());
128 EXPECT_EQ(BitcastV
.get(), GenericAVH
);
129 GenericAVH
= ConstantV
;
130 EXPECT_EQ(ConstantV
, GenericAVH
);
132 // Make sure I can call a method on the underlying CastInst. It
133 // doesn't matter which method.
134 EXPECT_FALSE(AVH
->mayWriteToMemory());
135 EXPECT_FALSE((*AVH
).mayWriteToMemory());
138 TEST_F(ValueHandle
, AssertingVH_Const
) {
139 const CastInst
*ConstBitcast
= BitcastV
.get();
140 AssertingVH
<const CastInst
> AVH(ConstBitcast
);
141 const CastInst
*implicit_to_exact_type
= AVH
;
142 (void)implicit_to_exact_type
; // Avoid warning.
145 TEST_F(ValueHandle
, AssertingVH_Comparisons
) {
146 AssertingVH
<Value
> BitcastAVH(BitcastV
.get());
147 AssertingVH
<Value
> ConstantAVH(ConstantV
);
149 EXPECT_TRUE(BitcastAVH
== BitcastAVH
);
150 EXPECT_TRUE(BitcastV
.get() == BitcastAVH
);
151 EXPECT_TRUE(BitcastAVH
== BitcastV
.get());
152 EXPECT_FALSE(BitcastAVH
== ConstantAVH
);
154 EXPECT_TRUE(BitcastAVH
!= ConstantAVH
);
155 EXPECT_TRUE(BitcastV
.get() != ConstantAVH
);
156 EXPECT_TRUE(BitcastAVH
!= ConstantV
);
157 EXPECT_FALSE(BitcastAVH
!= BitcastAVH
);
159 // Cast to Value* so comparisons work.
160 Value
*BV
= BitcastV
.get();
161 Value
*CV
= ConstantV
;
162 EXPECT_EQ(BV
< CV
, BitcastAVH
< ConstantAVH
);
163 EXPECT_EQ(BV
<= CV
, BitcastAVH
<= ConstantAVH
);
164 EXPECT_EQ(BV
> CV
, BitcastAVH
> ConstantAVH
);
165 EXPECT_EQ(BV
>= CV
, BitcastAVH
>= ConstantAVH
);
167 EXPECT_EQ(BV
< CV
, BitcastV
.get() < ConstantAVH
);
168 EXPECT_EQ(BV
<= CV
, BitcastV
.get() <= ConstantAVH
);
169 EXPECT_EQ(BV
> CV
, BitcastV
.get() > ConstantAVH
);
170 EXPECT_EQ(BV
>= CV
, BitcastV
.get() >= ConstantAVH
);
172 EXPECT_EQ(BV
< CV
, BitcastAVH
< ConstantV
);
173 EXPECT_EQ(BV
<= CV
, BitcastAVH
<= ConstantV
);
174 EXPECT_EQ(BV
> CV
, BitcastAVH
> ConstantV
);
175 EXPECT_EQ(BV
>= CV
, BitcastAVH
>= ConstantV
);
178 TEST_F(ValueHandle
, AssertingVH_DoesNotFollowRAUW
) {
179 AssertingVH
<Value
> AVH(BitcastV
.get());
180 BitcastV
->replaceAllUsesWith(ConstantV
);
181 EXPECT_EQ(BitcastV
.get(), AVH
);
186 TEST_F(ValueHandle
, AssertingVH_ReducesToPointer
) {
187 EXPECT_EQ(sizeof(CastInst
*), sizeof(AssertingVH
<CastInst
>));
192 #ifdef GTEST_HAS_DEATH_TEST
194 TEST_F(ValueHandle
, AssertingVH_Asserts
) {
195 AssertingVH
<Value
> AVH(BitcastV
.get());
196 EXPECT_DEATH({BitcastV
.reset();},
197 "An asserting value handle still pointed to this value!");
198 AssertingVH
<Value
> Copy(AVH
);
200 EXPECT_DEATH({BitcastV
.reset();},
201 "An asserting value handle still pointed to this value!");
206 #endif // GTEST_HAS_DEATH_TEST
210 TEST_F(ValueHandle
, CallbackVH_BasicOperation
) {
211 ConcreteCallbackVH
CVH(BitcastV
.get());
212 EXPECT_EQ(BitcastV
.get(), CVH
);
214 EXPECT_EQ(ConstantV
, CVH
);
216 // Make sure I can call a method on the underlying Value. It
217 // doesn't matter which method.
218 EXPECT_EQ(Type::getInt32Ty(Context
), CVH
->getType());
219 EXPECT_EQ(Type::getInt32Ty(Context
), (*CVH
).getType());
222 TEST_F(ValueHandle
, CallbackVH_Comparisons
) {
223 ConcreteCallbackVH
BitcastCVH(BitcastV
.get());
224 ConcreteCallbackVH
ConstantCVH(ConstantV
);
226 EXPECT_TRUE(BitcastCVH
== BitcastCVH
);
227 EXPECT_TRUE(BitcastV
.get() == BitcastCVH
);
228 EXPECT_TRUE(BitcastCVH
== BitcastV
.get());
229 EXPECT_FALSE(BitcastCVH
== ConstantCVH
);
231 EXPECT_TRUE(BitcastCVH
!= ConstantCVH
);
232 EXPECT_TRUE(BitcastV
.get() != ConstantCVH
);
233 EXPECT_TRUE(BitcastCVH
!= ConstantV
);
234 EXPECT_FALSE(BitcastCVH
!= BitcastCVH
);
236 // Cast to Value* so comparisons work.
237 Value
*BV
= BitcastV
.get();
238 Value
*CV
= ConstantV
;
239 EXPECT_EQ(BV
< CV
, BitcastCVH
< ConstantCVH
);
240 EXPECT_EQ(BV
<= CV
, BitcastCVH
<= ConstantCVH
);
241 EXPECT_EQ(BV
> CV
, BitcastCVH
> ConstantCVH
);
242 EXPECT_EQ(BV
>= CV
, BitcastCVH
>= ConstantCVH
);
244 EXPECT_EQ(BV
< CV
, BitcastV
.get() < ConstantCVH
);
245 EXPECT_EQ(BV
<= CV
, BitcastV
.get() <= ConstantCVH
);
246 EXPECT_EQ(BV
> CV
, BitcastV
.get() > ConstantCVH
);
247 EXPECT_EQ(BV
>= CV
, BitcastV
.get() >= ConstantCVH
);
249 EXPECT_EQ(BV
< CV
, BitcastCVH
< ConstantV
);
250 EXPECT_EQ(BV
<= CV
, BitcastCVH
<= ConstantV
);
251 EXPECT_EQ(BV
> CV
, BitcastCVH
> ConstantV
);
252 EXPECT_EQ(BV
>= CV
, BitcastCVH
>= ConstantV
);
255 TEST_F(ValueHandle
, CallbackVH_CallbackOnDeletion
) {
256 class RecordingVH final
: public CallbackVH
{
261 RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
262 RecordingVH(Value
*V
) : CallbackVH(V
), DeletedCalls(0), AURWCalls(0) {}
265 void deleted() override
{
267 CallbackVH::deleted();
269 void allUsesReplacedWith(Value
*) override
{ AURWCalls
++; }
273 RVH
= BitcastV
.get();
274 EXPECT_EQ(0, RVH
.DeletedCalls
);
275 EXPECT_EQ(0, RVH
.AURWCalls
);
277 EXPECT_EQ(1, RVH
.DeletedCalls
);
278 EXPECT_EQ(0, RVH
.AURWCalls
);
281 TEST_F(ValueHandle
, CallbackVH_CallbackOnRAUW
) {
282 class RecordingVH final
: public CallbackVH
{
287 RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {}
288 RecordingVH(Value
*V
)
289 : CallbackVH(V
), DeletedCalls(0), AURWArgument(nullptr) {}
292 void deleted() override
{
294 CallbackVH::deleted();
296 void allUsesReplacedWith(Value
*new_value
) override
{
297 EXPECT_EQ(nullptr, AURWArgument
);
298 AURWArgument
= new_value
;
303 RVH
= BitcastV
.get();
304 EXPECT_EQ(0, RVH
.DeletedCalls
);
305 EXPECT_EQ(nullptr, RVH
.AURWArgument
);
306 BitcastV
->replaceAllUsesWith(ConstantV
);
307 EXPECT_EQ(0, RVH
.DeletedCalls
);
308 EXPECT_EQ(ConstantV
, RVH
.AURWArgument
);
311 TEST_F(ValueHandle
, CallbackVH_DeletionCanRAUW
) {
312 class RecoveringVH final
: public CallbackVH
{
316 LLVMContext
*Context
;
318 RecoveringVH(LLVMContext
&TheContext
)
319 : DeletedCalls(0), AURWArgument(nullptr), Context(&TheContext
) {}
321 RecoveringVH(LLVMContext
&TheContext
, Value
*V
)
322 : CallbackVH(V
), DeletedCalls(0), AURWArgument(nullptr),
323 Context(&TheContext
) {}
326 void deleted() override
{
327 getValPtr()->replaceAllUsesWith(
328 Constant::getNullValue(Type::getInt32Ty(*Context
)));
331 void allUsesReplacedWith(Value
*new_value
) override
{
332 ASSERT_TRUE(nullptr != getValPtr());
333 EXPECT_EQ(1U, getValPtr()->getNumUses());
334 EXPECT_EQ(nullptr, AURWArgument
);
335 AURWArgument
= new_value
;
339 // Normally, if a value has uses, deleting it will crash. However, we can use
340 // a CallbackVH to remove the uses before the check for no uses.
341 RecoveringVH
RVH(Context
);
342 RVH
= RecoveringVH(Context
, BitcastV
.get());
343 std::unique_ptr
<BinaryOperator
> BitcastUser(BinaryOperator::CreateAdd(
344 RVH
, Constant::getNullValue(Type::getInt32Ty(Context
))));
345 EXPECT_EQ(BitcastV
.get(), BitcastUser
->getOperand(0));
346 BitcastV
.reset(); // Would crash without the ValueHandler.
347 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context
)),
349 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context
)),
350 BitcastUser
->getOperand(0));
353 TEST_F(ValueHandle
, DestroyingOtherVHOnSameValueDoesntBreakIteration
) {
354 // When a CallbackVH modifies other ValueHandles in its callbacks,
355 // that shouldn't interfere with non-modified ValueHandles receiving
356 // their appropriate callbacks.
358 // We create the active CallbackVH in the middle of a palindromic
359 // arrangement of other VHs so that the bad behavior would be
360 // triggered in whichever order callbacks run.
362 class DestroyingVH final
: public CallbackVH
{
364 std::unique_ptr
<WeakTrackingVH
> ToClear
[2];
365 DestroyingVH(Value
*V
) {
366 ToClear
[0].reset(new WeakTrackingVH(V
));
368 ToClear
[1].reset(new WeakTrackingVH(V
));
370 void deleted() override
{
373 CallbackVH::deleted();
375 void allUsesReplacedWith(Value
*) override
{
382 WeakTrackingVH
ShouldBeVisited1(BitcastV
.get());
383 DestroyingVH
C(BitcastV
.get());
384 WeakTrackingVH
ShouldBeVisited2(BitcastV
.get());
386 BitcastV
->replaceAllUsesWith(ConstantV
);
387 EXPECT_EQ(ConstantV
, static_cast<Value
*>(ShouldBeVisited1
));
388 EXPECT_EQ(ConstantV
, static_cast<Value
*>(ShouldBeVisited2
));
392 WeakTrackingVH
ShouldBeVisited1(BitcastV
.get());
393 DestroyingVH
C(BitcastV
.get());
394 WeakTrackingVH
ShouldBeVisited2(BitcastV
.get());
397 EXPECT_EQ(nullptr, static_cast<Value
*>(ShouldBeVisited1
));
398 EXPECT_EQ(nullptr, static_cast<Value
*>(ShouldBeVisited2
));
402 TEST_F(ValueHandle
, AssertingVHCheckedLast
) {
403 // If a CallbackVH exists to clear out a group of AssertingVHs on
404 // Value deletion, the CallbackVH should get a chance to do so
405 // before the AssertingVHs assert.
407 class ClearingVH final
: public CallbackVH
{
409 AssertingVH
<Value
> *ToClear
[2];
411 AssertingVH
<Value
> &A0
, AssertingVH
<Value
> &A1
)
417 void deleted() override
{
418 *ToClear
[0] = nullptr;
419 *ToClear
[1] = nullptr;
420 CallbackVH::deleted();
424 AssertingVH
<Value
> A1
, A2
;
426 ClearingVH
C(BitcastV
.get(), A1
, A2
);
428 // C.deleted() should run first, clearing the two AssertingVHs,
429 // which should prevent them from asserting.
433 TEST_F(ValueHandle
, PoisoningVH_BasicOperation
) {
434 PoisoningVH
<CastInst
> VH(BitcastV
.get());
435 CastInst
*implicit_to_exact_type
= VH
;
436 (void)implicit_to_exact_type
; // Avoid warning.
438 PoisoningVH
<Value
> GenericVH(BitcastV
.get());
439 EXPECT_EQ(BitcastV
.get(), GenericVH
);
440 GenericVH
= ConstantV
;
441 EXPECT_EQ(ConstantV
, GenericVH
);
443 // Make sure I can call a method on the underlying CastInst. It
444 // doesn't matter which method.
445 EXPECT_FALSE(VH
->mayWriteToMemory());
446 EXPECT_FALSE((*VH
).mayWriteToMemory());
449 TEST_F(ValueHandle
, PoisoningVH_Const
) {
450 const CastInst
*ConstBitcast
= BitcastV
.get();
451 PoisoningVH
<const CastInst
> VH(ConstBitcast
);
452 const CastInst
*implicit_to_exact_type
= VH
;
453 (void)implicit_to_exact_type
; // Avoid warning.
456 TEST_F(ValueHandle
, PoisoningVH_Comparisons
) {
457 PoisoningVH
<Value
> BitcastVH(BitcastV
.get());
458 PoisoningVH
<Value
> ConstantVH(ConstantV
);
460 EXPECT_TRUE(BitcastVH
== BitcastVH
);
461 EXPECT_TRUE(BitcastV
.get() == BitcastVH
);
462 EXPECT_TRUE(BitcastVH
== BitcastV
.get());
463 EXPECT_FALSE(BitcastVH
== ConstantVH
);
465 EXPECT_TRUE(BitcastVH
!= ConstantVH
);
466 EXPECT_TRUE(BitcastV
.get() != ConstantVH
);
467 EXPECT_TRUE(BitcastVH
!= ConstantV
);
468 EXPECT_FALSE(BitcastVH
!= BitcastVH
);
470 // Cast to Value* so comparisons work.
471 Value
*BV
= BitcastV
.get();
472 Value
*CV
= ConstantV
;
473 EXPECT_EQ(BV
< CV
, BitcastVH
< ConstantVH
);
474 EXPECT_EQ(BV
<= CV
, BitcastVH
<= ConstantVH
);
475 EXPECT_EQ(BV
> CV
, BitcastVH
> ConstantVH
);
476 EXPECT_EQ(BV
>= CV
, BitcastVH
>= ConstantVH
);
478 EXPECT_EQ(BV
< CV
, BitcastV
.get() < ConstantVH
);
479 EXPECT_EQ(BV
<= CV
, BitcastV
.get() <= ConstantVH
);
480 EXPECT_EQ(BV
> CV
, BitcastV
.get() > ConstantVH
);
481 EXPECT_EQ(BV
>= CV
, BitcastV
.get() >= ConstantVH
);
483 EXPECT_EQ(BV
< CV
, BitcastVH
< ConstantV
);
484 EXPECT_EQ(BV
<= CV
, BitcastVH
<= ConstantV
);
485 EXPECT_EQ(BV
> CV
, BitcastVH
> ConstantV
);
486 EXPECT_EQ(BV
>= CV
, BitcastVH
>= ConstantV
);
489 TEST_F(ValueHandle
, PoisoningVH_DoesNotFollowRAUW
) {
490 PoisoningVH
<Value
> VH(BitcastV
.get());
491 BitcastV
->replaceAllUsesWith(ConstantV
);
492 EXPECT_TRUE(DenseMapInfo
<PoisoningVH
<Value
>>::isEqual(VH
, BitcastV
.get()));
497 TEST_F(ValueHandle
, PoisoningVH_ReducesToPointer
) {
498 EXPECT_EQ(sizeof(CastInst
*), sizeof(PoisoningVH
<CastInst
>));
503 TEST_F(ValueHandle
, TrackingVH_Tracks
) {
504 TrackingVH
<Value
> VH(BitcastV
.get());
505 BitcastV
->replaceAllUsesWith(ConstantV
);
506 EXPECT_EQ(VH
, ConstantV
);
509 #ifdef GTEST_HAS_DEATH_TEST
511 TEST_F(ValueHandle
, PoisoningVH_Asserts
) {
512 PoisoningVH
<Value
> VH(BitcastV
.get());
514 // The poisoned handle shouldn't assert when the value is deleted.
515 BitcastV
.reset(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
)));
516 // But should when we access the handle.
517 EXPECT_DEATH((void)*VH
, "Accessed a poisoned value handle!");
519 // Now check that poison catches RAUW.
521 // The replace doesn't trigger anything immediately.
522 BitcastV
->replaceAllUsesWith(ConstantV
);
524 EXPECT_DEATH((void)*VH
, "Accessed a poisoned value handle!");
526 // Don't clear anything out here as destroying the handles should be fine.
529 TEST_F(ValueHandle
, TrackingVH_Asserts
) {
531 TrackingVH
<Value
> VH(BitcastV
.get());
533 // The tracking handle shouldn't assert when the value is deleted.
534 BitcastV
.reset(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
)));
535 // But should when we access the handle.
536 EXPECT_DEATH((void)*VH
,
537 "TrackingVH must be non-null and valid on dereference!");
541 TrackingVH
<Instruction
> VH(BitcastV
.get());
543 BitcastV
->replaceAllUsesWith(ConstantV
);
544 EXPECT_DEATH((void)*VH
,
545 "Tracked Value was replaced by one with an invalid type!");
549 #endif // GTEST_HAS_DEATH_TEST