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
21using namespace llvm;
22
23namespace {
24
25class ValueHandle : public testing::Test {
26protected:
27  Constant *ConstantV;
28  std::auto_ptr<BitCastInst> BitcastV;
29
30  ValueHandle() :
31    ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
32    BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) {
33  }
34};
35
36class ConcreteCallbackVH : public CallbackVH {
37public:
38  ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
39};
40
41TEST_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
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  (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
124TEST_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
131TEST_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
196TEST_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
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;
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
331TEST_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
411}
412