1//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
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"
14#include <memory>
15
16using namespace llvm;
17
18namespace {
19
20class ValueHandle : public testing::Test {
21protected:
22 LLVMContext Context;
23 Constant *ConstantV;
24 std::unique_ptr<BitCastInst> BitcastV;
25
26 ValueHandle()
27 : ConstantV(ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 0)),
28 BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(C&: Context))) {}
29};
30
31class ConcreteCallbackVH final : public CallbackVH {
32public:
33 ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
34};
35
36TEST_F(ValueHandle, WeakVH_BasicOperation) {
37 WeakVH WVH(BitcastV.get());
38 EXPECT_EQ(BitcastV.get(), WVH);
39 WVH = ConstantV;
40 EXPECT_EQ(ConstantV, WVH);
41
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());
46
47 WVH = BitcastV.get();
48 BitcastV->replaceAllUsesWith(V: ConstantV);
49 EXPECT_EQ(WVH, BitcastV.get());
50 BitcastV.reset();
51 EXPECT_EQ(WVH, nullptr);
52}
53
54TEST_F(ValueHandle, WeakTrackingVH_BasicOperation) {
55 WeakTrackingVH WVH(BitcastV.get());
56 EXPECT_EQ(BitcastV.get(), WVH);
57 WVH = ConstantV;
58 EXPECT_EQ(ConstantV, WVH);
59
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());
64}
65
66TEST_F(ValueHandle, WeakTrackingVH_Comparisons) {
67 WeakTrackingVH BitcastWVH(BitcastV.get());
68 WeakTrackingVH ConstantWVH(ConstantV);
69
70 EXPECT_TRUE(BitcastWVH == BitcastWVH);
71 EXPECT_TRUE(BitcastV.get() == BitcastWVH);
72 EXPECT_TRUE(BitcastWVH == BitcastV.get());
73 EXPECT_FALSE(BitcastWVH == ConstantWVH);
74
75 EXPECT_TRUE(BitcastWVH != ConstantWVH);
76 EXPECT_TRUE(BitcastV.get() != ConstantWVH);
77 EXPECT_TRUE(BitcastWVH != ConstantV);
78 EXPECT_FALSE(BitcastWVH != BitcastWVH);
79
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);
87
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);
92
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);
97}
98
99TEST_F(ValueHandle, WeakTrackingVH_FollowsRAUW) {
100 WeakTrackingVH WVH(BitcastV.get());
101 WeakTrackingVH WVH_Copy(WVH);
102 WeakTrackingVH WVH_Recreated(BitcastV.get());
103 BitcastV->replaceAllUsesWith(V: ConstantV);
104 EXPECT_EQ(ConstantV, WVH);
105 EXPECT_EQ(ConstantV, WVH_Copy);
106 EXPECT_EQ(ConstantV, WVH_Recreated);
107}
108
109TEST_F(ValueHandle, WeakTrackingVH_NullOnDeletion) {
110 WeakTrackingVH WVH(BitcastV.get());
111 WeakTrackingVH WVH_Copy(WVH);
112 WeakTrackingVH WVH_Recreated(BitcastV.get());
113 BitcastV.reset();
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);
118}
119
120
121TEST_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.
125
126 AssertingVH<Value> GenericAVH(BitcastV.get());
127 EXPECT_EQ(BitcastV.get(), GenericAVH);
128 GenericAVH = ConstantV;
129 EXPECT_EQ(ConstantV, GenericAVH);
130
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());
135}
136
137TEST_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.
142}
143
144TEST_F(ValueHandle, AssertingVH_Comparisons) {
145 AssertingVH<Value> BitcastAVH(BitcastV.get());
146 AssertingVH<Value> ConstantAVH(ConstantV);
147
148 EXPECT_TRUE(BitcastAVH == BitcastAVH);
149 EXPECT_TRUE(BitcastV.get() == BitcastAVH);
150 EXPECT_TRUE(BitcastAVH == BitcastV.get());
151 EXPECT_FALSE(BitcastAVH == ConstantAVH);
152
153 EXPECT_TRUE(BitcastAVH != ConstantAVH);
154 EXPECT_TRUE(BitcastV.get() != ConstantAVH);
155 EXPECT_TRUE(BitcastAVH != ConstantV);
156 EXPECT_FALSE(BitcastAVH != BitcastAVH);
157
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);
165
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);
170
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);
175}
176
177TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) {
178 AssertingVH<Value> AVH(BitcastV.get());
179 BitcastV->replaceAllUsesWith(V: ConstantV);
180 EXPECT_EQ(BitcastV.get(), AVH);
181}
182
183#ifdef NDEBUG
184
185TEST_F(ValueHandle, AssertingVH_ReducesToPointer) {
186 EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>));
187}
188
189#elif LLVM_ENABLE_ABI_BREAKING_CHECKS // && !NDEBUG
190
191#ifdef GTEST_HAS_DEATH_TEST
192
193TEST_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);
198 AVH = nullptr;
199 EXPECT_DEATH({BitcastV.reset();},
200 "An asserting value handle still pointed to this value!");
201 Copy = nullptr;
202 BitcastV.reset();
203}
204
205#endif // GTEST_HAS_DEATH_TEST
206
207#endif // NDEBUG
208
209TEST_F(ValueHandle, CallbackVH_BasicOperation) {
210 ConcreteCallbackVH CVH(BitcastV.get());
211 EXPECT_EQ(BitcastV.get(), CVH);
212 CVH = ConstantV;
213 EXPECT_EQ(ConstantV, CVH);
214
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());
219}
220
221TEST_F(ValueHandle, CallbackVH_Comparisons) {
222 ConcreteCallbackVH BitcastCVH(BitcastV.get());
223 ConcreteCallbackVH ConstantCVH(ConstantV);
224
225 EXPECT_TRUE(BitcastCVH == BitcastCVH);
226 EXPECT_TRUE(BitcastV.get() == BitcastCVH);
227 EXPECT_TRUE(BitcastCVH == BitcastV.get());
228 EXPECT_FALSE(BitcastCVH == ConstantCVH);
229
230 EXPECT_TRUE(BitcastCVH != ConstantCVH);
231 EXPECT_TRUE(BitcastV.get() != ConstantCVH);
232 EXPECT_TRUE(BitcastCVH != ConstantV);
233 EXPECT_FALSE(BitcastCVH != BitcastCVH);
234
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);
242
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);
247
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);
252}
253
254TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) {
255 class RecordingVH final : public CallbackVH {
256 public:
257 int DeletedCalls;
258 int AURWCalls;
259
260 RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
261 RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {}
262
263 private:
264 void deleted() override {
265 DeletedCalls++;
266 CallbackVH::deleted();
267 }
268 void allUsesReplacedWith(Value *) override { AURWCalls++; }
269 };
270
271 RecordingVH RVH;
272 RVH = BitcastV.get();
273 EXPECT_EQ(0, RVH.DeletedCalls);
274 EXPECT_EQ(0, RVH.AURWCalls);
275 BitcastV.reset();
276 EXPECT_EQ(1, RVH.DeletedCalls);
277 EXPECT_EQ(0, RVH.AURWCalls);
278}
279
280TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) {
281 class RecordingVH final : public CallbackVH {
282 public:
283 int DeletedCalls;
284 Value *AURWArgument;
285
286 RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {}
287 RecordingVH(Value *V)
288 : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr) {}
289
290 private:
291 void deleted() override {
292 DeletedCalls++;
293 CallbackVH::deleted();
294 }
295 void allUsesReplacedWith(Value *new_value) override {
296 EXPECT_EQ(nullptr, AURWArgument);
297 AURWArgument = new_value;
298 }
299 };
300
301 RecordingVH RVH;
302 RVH = BitcastV.get();
303 EXPECT_EQ(0, RVH.DeletedCalls);
304 EXPECT_EQ(nullptr, RVH.AURWArgument);
305 BitcastV->replaceAllUsesWith(V: ConstantV);
306 EXPECT_EQ(0, RVH.DeletedCalls);
307 EXPECT_EQ(ConstantV, RVH.AURWArgument);
308}
309
310TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
311 class RecoveringVH final : public CallbackVH {
312 public:
313 int DeletedCalls;
314 Value *AURWArgument;
315 LLVMContext *Context;
316
317 RecoveringVH(LLVMContext &TheContext)
318 : DeletedCalls(0), AURWArgument(nullptr), Context(&TheContext) {}
319
320 RecoveringVH(LLVMContext &TheContext, Value *V)
321 : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr),
322 Context(&TheContext) {}
323
324 private:
325 void deleted() override {
326 getValPtr()->replaceAllUsesWith(
327 V: Constant::getNullValue(Ty: Type::getInt32Ty(C&: *Context)));
328 setValPtr(nullptr);
329 }
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;
335 }
336 };
337
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 V1: RVH, V2: Constant::getNullValue(Ty: Type::getInt32Ty(C&: 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)),
347 RVH.AURWArgument);
348 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context)),
349 BitcastUser->getOperand(0));
350}
351
352TEST_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.
356 //
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.
360
361 class DestroyingVH final : public CallbackVH {
362 public:
363 std::unique_ptr<WeakTrackingVH> ToClear[2];
364 DestroyingVH(Value *V) {
365 ToClear[0].reset(p: new WeakTrackingVH(V));
366 setValPtr(V);
367 ToClear[1].reset(p: new WeakTrackingVH(V));
368 }
369 void deleted() override {
370 ToClear[0].reset();
371 ToClear[1].reset();
372 CallbackVH::deleted();
373 }
374 void allUsesReplacedWith(Value *) override {
375 ToClear[0].reset();
376 ToClear[1].reset();
377 }
378 };
379
380 {
381 WeakTrackingVH ShouldBeVisited1(BitcastV.get());
382 DestroyingVH C(BitcastV.get());
383 WeakTrackingVH ShouldBeVisited2(BitcastV.get());
384
385 BitcastV->replaceAllUsesWith(V: ConstantV);
386 EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
387 EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
388 }
389
390 {
391 WeakTrackingVH ShouldBeVisited1(BitcastV.get());
392 DestroyingVH C(BitcastV.get());
393 WeakTrackingVH ShouldBeVisited2(BitcastV.get());
394
395 BitcastV.reset();
396 EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited1));
397 EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited2));
398 }
399}
400
401TEST_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.
405
406 class ClearingVH final : public CallbackVH {
407 public:
408 AssertingVH<Value> *ToClear[2];
409 ClearingVH(Value *V,
410 AssertingVH<Value> &A0, AssertingVH<Value> &A1)
411 : CallbackVH(V) {
412 ToClear[0] = &A0;
413 ToClear[1] = &A1;
414 }
415
416 void deleted() override {
417 *ToClear[0] = nullptr;
418 *ToClear[1] = nullptr;
419 CallbackVH::deleted();
420 }
421 };
422
423 AssertingVH<Value> A1, A2;
424 A1 = BitcastV.get();
425 ClearingVH C(BitcastV.get(), A1, A2);
426 A2 = BitcastV.get();
427 // C.deleted() should run first, clearing the two AssertingVHs,
428 // which should prevent them from asserting.
429 BitcastV.reset();
430}
431
432TEST_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.
436
437 PoisoningVH<Value> GenericVH(BitcastV.get());
438 EXPECT_EQ(BitcastV.get(), GenericVH);
439 GenericVH = ConstantV;
440 EXPECT_EQ(ConstantV, GenericVH);
441
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());
446}
447
448TEST_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.
453}
454
455TEST_F(ValueHandle, PoisoningVH_Comparisons) {
456 PoisoningVH<Value> BitcastVH(BitcastV.get());
457 PoisoningVH<Value> ConstantVH(ConstantV);
458
459 EXPECT_TRUE(BitcastVH == BitcastVH);
460 EXPECT_TRUE(BitcastV.get() == BitcastVH);
461 EXPECT_TRUE(BitcastVH == BitcastV.get());
462 EXPECT_FALSE(BitcastVH == ConstantVH);
463
464 EXPECT_TRUE(BitcastVH != ConstantVH);
465 EXPECT_TRUE(BitcastV.get() != ConstantVH);
466 EXPECT_TRUE(BitcastVH != ConstantV);
467 EXPECT_FALSE(BitcastVH != BitcastVH);
468
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);
476
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);
481
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);
486}
487
488TEST_F(ValueHandle, PoisoningVH_DoesNotFollowRAUW) {
489 PoisoningVH<Value> VH(BitcastV.get());
490 BitcastV->replaceAllUsesWith(V: ConstantV);
491 EXPECT_TRUE(DenseMapInfo<PoisoningVH<Value>>::isEqual(VH, BitcastV.get()));
492}
493
494TEST_F(ValueHandle, AssertingVH_DenseMap) {
495 DenseMap<AssertingVH<Value>, int> Map;
496 Map.insert(KV: {BitcastV.get(), 1});
497 Map.insert(KV: {ConstantV, 2});
498 // These will create a temporary AssertingVH during lookup.
499 EXPECT_TRUE(Map.contains(BitcastV.get()));
500 EXPECT_TRUE(Map.contains(ConstantV));
501 // These will not create a temporary AssertingVH.
502 EXPECT_TRUE(Map.find_as(BitcastV.get()) != Map.end());
503 EXPECT_TRUE(Map.find_as(ConstantV) != Map.end());
504}
505
506TEST_F(ValueHandle, PoisoningVH_DenseMap) {
507 DenseMap<PoisoningVH<Value>, int> Map;
508 Map.insert(KV: {BitcastV.get(), 1});
509 Map.insert(KV: {ConstantV, 2});
510 // These will create a temporary PoisoningVH during lookup.
511 EXPECT_TRUE(Map.contains(BitcastV.get()));
512 EXPECT_TRUE(Map.contains(ConstantV));
513 // These will not create a temporary PoisoningVH.
514 EXPECT_TRUE(Map.find_as(BitcastV.get()) != Map.end());
515 EXPECT_TRUE(Map.find_as(ConstantV) != Map.end());
516}
517
518#ifdef NDEBUG
519
520TEST_F(ValueHandle, PoisoningVH_ReducesToPointer) {
521 EXPECT_EQ(sizeof(CastInst *), sizeof(PoisoningVH<CastInst>));
522}
523
524#else // !NDEBUG
525
526TEST_F(ValueHandle, TrackingVH_Tracks) {
527 TrackingVH<Value> VH(BitcastV.get());
528 BitcastV->replaceAllUsesWith(V: ConstantV);
529 EXPECT_EQ(VH, ConstantV);
530}
531
532#ifdef GTEST_HAS_DEATH_TEST
533#if LLVM_ENABLE_ABI_BREAKING_CHECKS
534
535TEST_F(ValueHandle, PoisoningVH_Asserts) {
536 PoisoningVH<Value> VH(BitcastV.get());
537
538 // The poisoned handle shouldn't assert when the value is deleted.
539 BitcastV.reset(p: new BitCastInst(ConstantV, Type::getInt32Ty(C&: Context)));
540 // But should when we access the handle.
541 EXPECT_DEATH((void)*VH, "Accessed a poisoned value handle!");
542
543 // Now check that poison catches RAUW.
544 VH = BitcastV.get();
545 // The replace doesn't trigger anything immediately.
546 BitcastV->replaceAllUsesWith(V: ConstantV);
547 // But a use does.
548 EXPECT_DEATH((void)*VH, "Accessed a poisoned value handle!");
549
550 // Don't clear anything out here as destroying the handles should be fine.
551}
552
553#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
554
555TEST_F(ValueHandle, TrackingVH_Asserts) {
556 {
557 TrackingVH<Value> VH(BitcastV.get());
558
559 // The tracking handle shouldn't assert when the value is deleted.
560 BitcastV.reset(p: new BitCastInst(ConstantV, Type::getInt32Ty(C&: Context)));
561 // But should when we access the handle.
562 EXPECT_DEATH((void)*VH,
563 "TrackingVH must be non-null and valid on dereference!");
564 }
565
566 {
567 TrackingVH<Instruction> VH(BitcastV.get());
568
569 BitcastV->replaceAllUsesWith(V: ConstantV);
570 EXPECT_DEATH((void)*VH,
571 "Tracked Value was replaced by one with an invalid type!");
572 }
573}
574
575#endif // GTEST_HAS_DEATH_TEST
576
577#endif // NDEBUG
578}
579

source code of llvm/unittests/IR/ValueHandleTest.cpp