blob: ba610ea4ff9a557ad8bb3ae46b0128a712108259 [file] [log] [blame]
Jeffrey Yasskin487fa012009-04-27 20:32:07 +00001//===- 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"
Chris Lattnerf3523592009-10-27 17:08:31 +000014#include "llvm/LLVMContext.h"
Jeffrey Yasskin6a9291a2009-10-12 17:43:32 +000015#include "llvm/ADT/OwningPtr.h"
Jeffrey Yasskin487fa012009-04-27 20:32:07 +000016
17#include "gtest/gtest.h"
18
19#include <memory>
20
21using namespace llvm;
22
23namespace {
24
25class ValueHandle : public testing::Test {
26protected:
27 Constant *ConstantV;
28 std::auto_ptr<BitCastInst> BitcastV;
29
Owen Anderson9adc0ab2009-07-14 23:09:55 +000030 ValueHandle() :
Owen Anderson1d0be152009-08-13 21:58:54 +000031 ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
32 BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) {
Jeffrey Yasskin487fa012009-04-27 20:32:07 +000033 }
34};
35
Dan Gohmanc09b12c2009-05-02 21:10:48 +000036class ConcreteCallbackVH : public CallbackVH {
37public:
Dan Gohmanc09b12c2009-05-02 21:10:48 +000038 ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
39};
40
Jeffrey Yasskin487fa012009-04-27 20:32:07 +000041TEST_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.
Owen Anderson1d0be152009-08-13 21:58:54 +000049 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType());
50 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType());
Jeffrey Yasskin487fa012009-04-27 20:32:07 +000051}
52
53TEST_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
86TEST_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
96TEST_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
108TEST_F(ValueHandle, AssertingVH_BasicOperation) {
109 AssertingVH<CastInst> AVH(BitcastV.get());
110 CastInst *implicit_to_exact_type = AVH;
111 implicit_to_exact_type = 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
Jeffrey Yasskin0d5bd592009-08-07 19:54:29 +0000124TEST_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 implicit_to_exact_type = implicit_to_exact_type; // Avoid warning.
129}
130
Jeffrey Yasskin487fa012009-04-27 20:32:07 +0000131TEST_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
164TEST_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
172TEST_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
180TEST_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
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000196TEST_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.
Owen Anderson1d0be152009-08-13 21:58:54 +0000204 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType());
205 EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType());
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000206}
207
208TEST_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
241TEST_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
264TEST_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
291TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
292 class RecoveringVH : public CallbackVH {
293 public:
294 int DeletedCalls;
295 Value *AURWArgument;
Owen Anderson0a5372e2009-07-13 04:09:18 +0000296 LLVMContext *Context;
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000297
Owen Anderson0a5372e2009-07-13 04:09:18 +0000298 RecoveringVH() : DeletedCalls(0), AURWArgument(NULL),
299 Context(&getGlobalContext()) {}
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000300 RecoveringVH(Value *V)
Owen Anderson0a5372e2009-07-13 04:09:18 +0000301 : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL),
302 Context(&getGlobalContext()) {}
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000303
304 private:
305 virtual void deleted() {
Owen Anderson1d0be152009-08-13 21:58:54 +0000306 getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())));
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000307 setValPtr(NULL);
308 }
309 virtual void allUsesReplacedWith(Value *new_value) {
310 ASSERT_TRUE(NULL != getValPtr());
Daniel Dunbar7ce55362009-05-18 03:44:24 +0000311 EXPECT_EQ(1U, getValPtr()->getNumUses());
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000312 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(
Owen Anderson0a5372e2009-07-13 04:09:18 +0000322 BinaryOperator::CreateAdd(RVH,
Owen Anderson1d0be152009-08-13 21:58:54 +0000323 Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))));
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000324 EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0));
325 BitcastV.reset(); // Would crash without the ValueHandler.
Owen Anderson1d0be152009-08-13 21:58:54 +0000326 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument);
327 EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())),
Owen Anderson0a5372e2009-07-13 04:09:18 +0000328 BitcastUser->getOperand(0));
Dan Gohmanc09b12c2009-05-02 21:10:48 +0000329}
330
Jeffrey Yasskin6a9291a2009-10-12 17:43:32 +0000331TEST_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
380TEST_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
Jeffrey Yasskin487fa012009-04-27 20:32:07 +0000411}