• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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