1 //===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/ValueHandle.h"
10 #include "llvm/IR/Constants.h"
11 #include "llvm/IR/Instructions.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "gtest/gtest.h"
20 class ValueHandle
: public testing::Test
{
24 std::unique_ptr
<BitCastInst
> BitcastV
;
27 : ConstantV(ConstantInt::get(Type::getInt32Ty(Context
), 0)),
28 BitcastV(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
))) {}
31 class ConcreteCallbackVH final
: public CallbackVH
{
33 ConcreteCallbackVH(Value
*V
) : CallbackVH(V
) {}
36 TEST_F(ValueHandle
, WeakVH_BasicOperation
) {
37 WeakVH
WVH(BitcastV
.get());
38 EXPECT_EQ(BitcastV
.get(), WVH
);
40 EXPECT_EQ(ConstantV
, WVH
);
42 // Make sure I can call a method on the underlying Value. It
43 // doesn't matter which method.
44 EXPECT_EQ(Type::getInt32Ty(Context
), WVH
->getType());
45 EXPECT_EQ(Type::getInt32Ty(Context
), (*WVH
).getType());
48 BitcastV
->replaceAllUsesWith(ConstantV
);
49 EXPECT_EQ(WVH
, BitcastV
.get());
51 EXPECT_EQ(WVH
, nullptr);
54 TEST_F(ValueHandle
, WeakTrackingVH_BasicOperation
) {
55 WeakTrackingVH
WVH(BitcastV
.get());
56 EXPECT_EQ(BitcastV
.get(), WVH
);
58 EXPECT_EQ(ConstantV
, WVH
);
60 // Make sure I can call a method on the underlying Value. It
61 // doesn't matter which method.
62 EXPECT_EQ(Type::getInt32Ty(Context
), WVH
->getType());
63 EXPECT_EQ(Type::getInt32Ty(Context
), (*WVH
).getType());
66 TEST_F(ValueHandle
, WeakTrackingVH_Comparisons
) {
67 WeakTrackingVH
BitcastWVH(BitcastV
.get());
68 WeakTrackingVH
ConstantWVH(ConstantV
);
70 EXPECT_TRUE(BitcastWVH
== BitcastWVH
);
71 EXPECT_TRUE(BitcastV
.get() == BitcastWVH
);
72 EXPECT_TRUE(BitcastWVH
== BitcastV
.get());
73 EXPECT_FALSE(BitcastWVH
== ConstantWVH
);
75 EXPECT_TRUE(BitcastWVH
!= ConstantWVH
);
76 EXPECT_TRUE(BitcastV
.get() != ConstantWVH
);
77 EXPECT_TRUE(BitcastWVH
!= ConstantV
);
78 EXPECT_FALSE(BitcastWVH
!= BitcastWVH
);
80 // Cast to Value* so comparisons work.
81 Value
*BV
= BitcastV
.get();
82 Value
*CV
= ConstantV
;
83 EXPECT_EQ(BV
< CV
, BitcastWVH
< ConstantWVH
);
84 EXPECT_EQ(BV
<= CV
, BitcastWVH
<= ConstantWVH
);
85 EXPECT_EQ(BV
> CV
, BitcastWVH
> ConstantWVH
);
86 EXPECT_EQ(BV
>= CV
, BitcastWVH
>= ConstantWVH
);
88 EXPECT_EQ(BV
< CV
, BitcastV
.get() < 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
);
93 EXPECT_EQ(BV
< CV
, BitcastWVH
< ConstantV
);
94 EXPECT_EQ(BV
<= CV
, BitcastWVH
<= ConstantV
);
95 EXPECT_EQ(BV
> CV
, BitcastWVH
> ConstantV
);
96 EXPECT_EQ(BV
>= CV
, BitcastWVH
>= ConstantV
);
99 TEST_F(ValueHandle
, WeakTrackingVH_FollowsRAUW
) {
100 WeakTrackingVH
WVH(BitcastV
.get());
101 WeakTrackingVH
WVH_Copy(WVH
);
102 WeakTrackingVH
WVH_Recreated(BitcastV
.get());
103 BitcastV
->replaceAllUsesWith(ConstantV
);
104 EXPECT_EQ(ConstantV
, WVH
);
105 EXPECT_EQ(ConstantV
, WVH_Copy
);
106 EXPECT_EQ(ConstantV
, WVH_Recreated
);
109 TEST_F(ValueHandle
, WeakTrackingVH_NullOnDeletion
) {
110 WeakTrackingVH
WVH(BitcastV
.get());
111 WeakTrackingVH
WVH_Copy(WVH
);
112 WeakTrackingVH
WVH_Recreated(BitcastV
.get());
114 Value
*null_value
= nullptr;
115 EXPECT_EQ(null_value
, WVH
);
116 EXPECT_EQ(null_value
, WVH_Copy
);
117 EXPECT_EQ(null_value
, WVH_Recreated
);
121 TEST_F(ValueHandle
, AssertingVH_BasicOperation
) {
122 AssertingVH
<CastInst
> AVH(BitcastV
.get());
123 CastInst
*implicit_to_exact_type
= AVH
;
124 (void)implicit_to_exact_type
; // Avoid warning.
126 AssertingVH
<Value
> GenericAVH(BitcastV
.get());
127 EXPECT_EQ(BitcastV
.get(), GenericAVH
);
128 GenericAVH
= ConstantV
;
129 EXPECT_EQ(ConstantV
, GenericAVH
);
131 // Make sure I can call a method on the underlying CastInst. It
132 // doesn't matter which method.
133 EXPECT_FALSE(AVH
->mayWriteToMemory());
134 EXPECT_FALSE((*AVH
).mayWriteToMemory());
137 TEST_F(ValueHandle
, AssertingVH_Const
) {
138 const CastInst
*ConstBitcast
= BitcastV
.get();
139 AssertingVH
<const CastInst
> AVH(ConstBitcast
);
140 const CastInst
*implicit_to_exact_type
= AVH
;
141 (void)implicit_to_exact_type
; // Avoid warning.
144 TEST_F(ValueHandle
, AssertingVH_Comparisons
) {
145 AssertingVH
<Value
> BitcastAVH(BitcastV
.get());
146 AssertingVH
<Value
> ConstantAVH(ConstantV
);
148 EXPECT_TRUE(BitcastAVH
== BitcastAVH
);
149 EXPECT_TRUE(BitcastV
.get() == BitcastAVH
);
150 EXPECT_TRUE(BitcastAVH
== BitcastV
.get());
151 EXPECT_FALSE(BitcastAVH
== ConstantAVH
);
153 EXPECT_TRUE(BitcastAVH
!= ConstantAVH
);
154 EXPECT_TRUE(BitcastV
.get() != ConstantAVH
);
155 EXPECT_TRUE(BitcastAVH
!= ConstantV
);
156 EXPECT_FALSE(BitcastAVH
!= BitcastAVH
);
158 // Cast to Value* so comparisons work.
159 Value
*BV
= BitcastV
.get();
160 Value
*CV
= ConstantV
;
161 EXPECT_EQ(BV
< CV
, BitcastAVH
< ConstantAVH
);
162 EXPECT_EQ(BV
<= CV
, BitcastAVH
<= ConstantAVH
);
163 EXPECT_EQ(BV
> CV
, BitcastAVH
> ConstantAVH
);
164 EXPECT_EQ(BV
>= CV
, BitcastAVH
>= ConstantAVH
);
166 EXPECT_EQ(BV
< CV
, BitcastV
.get() < 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
);
171 EXPECT_EQ(BV
< CV
, BitcastAVH
< ConstantV
);
172 EXPECT_EQ(BV
<= CV
, BitcastAVH
<= ConstantV
);
173 EXPECT_EQ(BV
> CV
, BitcastAVH
> ConstantV
);
174 EXPECT_EQ(BV
>= CV
, BitcastAVH
>= ConstantV
);
177 TEST_F(ValueHandle
, AssertingVH_DoesNotFollowRAUW
) {
178 AssertingVH
<Value
> AVH(BitcastV
.get());
179 BitcastV
->replaceAllUsesWith(ConstantV
);
180 EXPECT_EQ(BitcastV
.get(), AVH
);
185 TEST_F(ValueHandle
, AssertingVH_ReducesToPointer
) {
186 EXPECT_EQ(sizeof(CastInst
*), sizeof(AssertingVH
<CastInst
>));
191 #ifdef GTEST_HAS_DEATH_TEST
193 TEST_F(ValueHandle
, AssertingVH_Asserts
) {
194 AssertingVH
<Value
> AVH(BitcastV
.get());
195 EXPECT_DEATH({BitcastV
.reset();},
196 "An asserting value handle still pointed to this value!");
197 AssertingVH
<Value
> Copy(AVH
);
199 EXPECT_DEATH({BitcastV
.reset();},
200 "An asserting value handle still pointed to this value!");
205 #endif // GTEST_HAS_DEATH_TEST
209 TEST_F(ValueHandle
, CallbackVH_BasicOperation
) {
210 ConcreteCallbackVH
CVH(BitcastV
.get());
211 EXPECT_EQ(BitcastV
.get(), CVH
);
213 EXPECT_EQ(ConstantV
, CVH
);
215 // Make sure I can call a method on the underlying Value. It
216 // doesn't matter which method.
217 EXPECT_EQ(Type::getInt32Ty(Context
), CVH
->getType());
218 EXPECT_EQ(Type::getInt32Ty(Context
), (*CVH
).getType());
221 TEST_F(ValueHandle
, CallbackVH_Comparisons
) {
222 ConcreteCallbackVH
BitcastCVH(BitcastV
.get());
223 ConcreteCallbackVH
ConstantCVH(ConstantV
);
225 EXPECT_TRUE(BitcastCVH
== BitcastCVH
);
226 EXPECT_TRUE(BitcastV
.get() == BitcastCVH
);
227 EXPECT_TRUE(BitcastCVH
== BitcastV
.get());
228 EXPECT_FALSE(BitcastCVH
== ConstantCVH
);
230 EXPECT_TRUE(BitcastCVH
!= ConstantCVH
);
231 EXPECT_TRUE(BitcastV
.get() != ConstantCVH
);
232 EXPECT_TRUE(BitcastCVH
!= ConstantV
);
233 EXPECT_FALSE(BitcastCVH
!= BitcastCVH
);
235 // Cast to Value* so comparisons work.
236 Value
*BV
= BitcastV
.get();
237 Value
*CV
= ConstantV
;
238 EXPECT_EQ(BV
< CV
, BitcastCVH
< ConstantCVH
);
239 EXPECT_EQ(BV
<= CV
, BitcastCVH
<= ConstantCVH
);
240 EXPECT_EQ(BV
> CV
, BitcastCVH
> ConstantCVH
);
241 EXPECT_EQ(BV
>= CV
, BitcastCVH
>= ConstantCVH
);
243 EXPECT_EQ(BV
< CV
, BitcastV
.get() < 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
);
248 EXPECT_EQ(BV
< CV
, BitcastCVH
< ConstantV
);
249 EXPECT_EQ(BV
<= CV
, BitcastCVH
<= ConstantV
);
250 EXPECT_EQ(BV
> CV
, BitcastCVH
> ConstantV
);
251 EXPECT_EQ(BV
>= CV
, BitcastCVH
>= ConstantV
);
254 TEST_F(ValueHandle
, CallbackVH_CallbackOnDeletion
) {
255 class RecordingVH final
: public CallbackVH
{
260 RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
261 RecordingVH(Value
*V
) : CallbackVH(V
), DeletedCalls(0), AURWCalls(0) {}
264 void deleted() override
{
266 CallbackVH::deleted();
268 void allUsesReplacedWith(Value
*) override
{ AURWCalls
++; }
272 RVH
= BitcastV
.get();
273 EXPECT_EQ(0, RVH
.DeletedCalls
);
274 EXPECT_EQ(0, RVH
.AURWCalls
);
276 EXPECT_EQ(1, RVH
.DeletedCalls
);
277 EXPECT_EQ(0, RVH
.AURWCalls
);
280 TEST_F(ValueHandle
, CallbackVH_CallbackOnRAUW
) {
281 class RecordingVH final
: public CallbackVH
{
286 RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {}
287 RecordingVH(Value
*V
)
288 : CallbackVH(V
), DeletedCalls(0), AURWArgument(nullptr) {}
291 void deleted() override
{
293 CallbackVH::deleted();
295 void allUsesReplacedWith(Value
*new_value
) override
{
296 EXPECT_EQ(nullptr, AURWArgument
);
297 AURWArgument
= new_value
;
302 RVH
= BitcastV
.get();
303 EXPECT_EQ(0, RVH
.DeletedCalls
);
304 EXPECT_EQ(nullptr, RVH
.AURWArgument
);
305 BitcastV
->replaceAllUsesWith(ConstantV
);
306 EXPECT_EQ(0, RVH
.DeletedCalls
);
307 EXPECT_EQ(ConstantV
, RVH
.AURWArgument
);
310 TEST_F(ValueHandle
, CallbackVH_DeletionCanRAUW
) {
311 class RecoveringVH final
: public CallbackVH
{
315 LLVMContext
*Context
;
317 RecoveringVH(LLVMContext
&TheContext
)
318 : DeletedCalls(0), AURWArgument(nullptr), Context(&TheContext
) {}
320 RecoveringVH(LLVMContext
&TheContext
, Value
*V
)
321 : CallbackVH(V
), DeletedCalls(0), AURWArgument(nullptr),
322 Context(&TheContext
) {}
325 void deleted() override
{
326 getValPtr()->replaceAllUsesWith(
327 Constant::getNullValue(Type::getInt32Ty(*Context
)));
330 void allUsesReplacedWith(Value
*new_value
) override
{
331 ASSERT_TRUE(nullptr != getValPtr());
332 EXPECT_EQ(1U, getValPtr()->getNumUses());
333 EXPECT_EQ(nullptr, AURWArgument
);
334 AURWArgument
= new_value
;
338 // Normally, if a value has uses, deleting it will crash. However, we can use
339 // a CallbackVH to remove the uses before the check for no uses.
340 RecoveringVH
RVH(Context
);
341 RVH
= RecoveringVH(Context
, BitcastV
.get());
342 std::unique_ptr
<BinaryOperator
> BitcastUser(BinaryOperator::CreateAdd(
343 RVH
, Constant::getNullValue(Type::getInt32Ty(Context
))));
344 EXPECT_EQ(BitcastV
.get(), BitcastUser
->getOperand(0));
345 BitcastV
.reset(); // Would crash without the ValueHandler.
346 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context
)),
348 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context
)),
349 BitcastUser
->getOperand(0));
352 TEST_F(ValueHandle
, DestroyingOtherVHOnSameValueDoesntBreakIteration
) {
353 // When a CallbackVH modifies other ValueHandles in its callbacks,
354 // that shouldn't interfere with non-modified ValueHandles receiving
355 // their appropriate callbacks.
357 // We create the active CallbackVH in the middle of a palindromic
358 // arrangement of other VHs so that the bad behavior would be
359 // triggered in whichever order callbacks run.
361 class DestroyingVH final
: public CallbackVH
{
363 std::unique_ptr
<WeakTrackingVH
> ToClear
[2];
364 DestroyingVH(Value
*V
) {
365 ToClear
[0].reset(new WeakTrackingVH(V
));
367 ToClear
[1].reset(new WeakTrackingVH(V
));
369 void deleted() override
{
372 CallbackVH::deleted();
374 void allUsesReplacedWith(Value
*) override
{
381 WeakTrackingVH
ShouldBeVisited1(BitcastV
.get());
382 DestroyingVH
C(BitcastV
.get());
383 WeakTrackingVH
ShouldBeVisited2(BitcastV
.get());
385 BitcastV
->replaceAllUsesWith(ConstantV
);
386 EXPECT_EQ(ConstantV
, static_cast<Value
*>(ShouldBeVisited1
));
387 EXPECT_EQ(ConstantV
, static_cast<Value
*>(ShouldBeVisited2
));
391 WeakTrackingVH
ShouldBeVisited1(BitcastV
.get());
392 DestroyingVH
C(BitcastV
.get());
393 WeakTrackingVH
ShouldBeVisited2(BitcastV
.get());
396 EXPECT_EQ(nullptr, static_cast<Value
*>(ShouldBeVisited1
));
397 EXPECT_EQ(nullptr, static_cast<Value
*>(ShouldBeVisited2
));
401 TEST_F(ValueHandle
, AssertingVHCheckedLast
) {
402 // If a CallbackVH exists to clear out a group of AssertingVHs on
403 // Value deletion, the CallbackVH should get a chance to do so
404 // before the AssertingVHs assert.
406 class ClearingVH final
: public CallbackVH
{
408 AssertingVH
<Value
> *ToClear
[2];
410 AssertingVH
<Value
> &A0
, AssertingVH
<Value
> &A1
)
416 void deleted() override
{
417 *ToClear
[0] = nullptr;
418 *ToClear
[1] = nullptr;
419 CallbackVH::deleted();
423 AssertingVH
<Value
> A1
, A2
;
425 ClearingVH
C(BitcastV
.get(), A1
, A2
);
427 // C.deleted() should run first, clearing the two AssertingVHs,
428 // which should prevent them from asserting.
432 TEST_F(ValueHandle
, PoisoningVH_BasicOperation
) {
433 PoisoningVH
<CastInst
> VH(BitcastV
.get());
434 CastInst
*implicit_to_exact_type
= VH
;
435 (void)implicit_to_exact_type
; // Avoid warning.
437 PoisoningVH
<Value
> GenericVH(BitcastV
.get());
438 EXPECT_EQ(BitcastV
.get(), GenericVH
);
439 GenericVH
= ConstantV
;
440 EXPECT_EQ(ConstantV
, GenericVH
);
442 // Make sure I can call a method on the underlying CastInst. It
443 // doesn't matter which method.
444 EXPECT_FALSE(VH
->mayWriteToMemory());
445 EXPECT_FALSE((*VH
).mayWriteToMemory());
448 TEST_F(ValueHandle
, PoisoningVH_Const
) {
449 const CastInst
*ConstBitcast
= BitcastV
.get();
450 PoisoningVH
<const CastInst
> VH(ConstBitcast
);
451 const CastInst
*implicit_to_exact_type
= VH
;
452 (void)implicit_to_exact_type
; // Avoid warning.
455 TEST_F(ValueHandle
, PoisoningVH_Comparisons
) {
456 PoisoningVH
<Value
> BitcastVH(BitcastV
.get());
457 PoisoningVH
<Value
> ConstantVH(ConstantV
);
459 EXPECT_TRUE(BitcastVH
== BitcastVH
);
460 EXPECT_TRUE(BitcastV
.get() == BitcastVH
);
461 EXPECT_TRUE(BitcastVH
== BitcastV
.get());
462 EXPECT_FALSE(BitcastVH
== ConstantVH
);
464 EXPECT_TRUE(BitcastVH
!= ConstantVH
);
465 EXPECT_TRUE(BitcastV
.get() != ConstantVH
);
466 EXPECT_TRUE(BitcastVH
!= ConstantV
);
467 EXPECT_FALSE(BitcastVH
!= BitcastVH
);
469 // Cast to Value* so comparisons work.
470 Value
*BV
= BitcastV
.get();
471 Value
*CV
= ConstantV
;
472 EXPECT_EQ(BV
< CV
, BitcastVH
< ConstantVH
);
473 EXPECT_EQ(BV
<= CV
, BitcastVH
<= ConstantVH
);
474 EXPECT_EQ(BV
> CV
, BitcastVH
> ConstantVH
);
475 EXPECT_EQ(BV
>= CV
, BitcastVH
>= ConstantVH
);
477 EXPECT_EQ(BV
< CV
, BitcastV
.get() < 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
);
482 EXPECT_EQ(BV
< CV
, BitcastVH
< ConstantV
);
483 EXPECT_EQ(BV
<= CV
, BitcastVH
<= ConstantV
);
484 EXPECT_EQ(BV
> CV
, BitcastVH
> ConstantV
);
485 EXPECT_EQ(BV
>= CV
, BitcastVH
>= ConstantV
);
488 TEST_F(ValueHandle
, PoisoningVH_DoesNotFollowRAUW
) {
489 PoisoningVH
<Value
> VH(BitcastV
.get());
490 BitcastV
->replaceAllUsesWith(ConstantV
);
491 EXPECT_TRUE(DenseMapInfo
<PoisoningVH
<Value
>>::isEqual(VH
, BitcastV
.get()));
496 TEST_F(ValueHandle
, PoisoningVH_ReducesToPointer
) {
497 EXPECT_EQ(sizeof(CastInst
*), sizeof(PoisoningVH
<CastInst
>));
502 TEST_F(ValueHandle
, TrackingVH_Tracks
) {
503 TrackingVH
<Value
> VH(BitcastV
.get());
504 BitcastV
->replaceAllUsesWith(ConstantV
);
505 EXPECT_EQ(VH
, ConstantV
);
508 #ifdef GTEST_HAS_DEATH_TEST
510 TEST_F(ValueHandle
, PoisoningVH_Asserts
) {
511 PoisoningVH
<Value
> VH(BitcastV
.get());
513 // The poisoned handle shouldn't assert when the value is deleted.
514 BitcastV
.reset(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
)));
515 // But should when we access the handle.
516 EXPECT_DEATH((void)*VH
, "Accessed a poisoned value handle!");
518 // Now check that poison catches RAUW.
520 // The replace doesn't trigger anything immediately.
521 BitcastV
->replaceAllUsesWith(ConstantV
);
523 EXPECT_DEATH((void)*VH
, "Accessed a poisoned value handle!");
525 // Don't clear anything out here as destroying the handles should be fine.
528 TEST_F(ValueHandle
, TrackingVH_Asserts
) {
530 TrackingVH
<Value
> VH(BitcastV
.get());
532 // The tracking handle shouldn't assert when the value is deleted.
533 BitcastV
.reset(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
)));
534 // But should when we access the handle.
535 EXPECT_DEATH((void)*VH
,
536 "TrackingVH must be non-null and valid on dereference!");
540 TrackingVH
<Instruction
> VH(BitcastV
.get());
542 BitcastV
->replaceAllUsesWith(ConstantV
);
543 EXPECT_DEATH((void)*VH
,
544 "Tracked Value was replaced by one with an invalid type!");
548 #endif // GTEST_HAS_DEATH_TEST