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
ValueHandle()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:
ConcreteCallbackVH(Value * V)38 ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
39 };
40
TEST_F(ValueHandle,WeakVH_BasicOperation)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
TEST_F(ValueHandle,WeakVH_Comparisons)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
TEST_F(ValueHandle,WeakVH_FollowsRAUW)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
TEST_F(ValueHandle,WeakVH_NullOnDeletion)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
TEST_F(ValueHandle,AssertingVH_BasicOperation)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
TEST_F(ValueHandle,AssertingVH_Const)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
TEST_F(ValueHandle,AssertingVH_Comparisons)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
TEST_F(ValueHandle,AssertingVH_DoesNotFollowRAUW)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
TEST_F(ValueHandle,AssertingVH_ReducesToPointer)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
TEST_F(ValueHandle,AssertingVH_Asserts)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
TEST_F(ValueHandle,CallbackVH_BasicOperation)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
TEST_F(ValueHandle,CallbackVH_Comparisons)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
TEST_F(ValueHandle,CallbackVH_CallbackOnDeletion)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
TEST_F(ValueHandle,CallbackVH_CallbackOnRAUW)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
TEST_F(ValueHandle,CallbackVH_DeletionCanRAUW)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
TEST_F(ValueHandle,DestroyingOtherVHOnSameValueDoesntBreakIteration)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
TEST_F(ValueHandle,AssertingVHCheckedLast)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