xref: /aosp_15_r20/external/llvm/unittests/IR/ValueHandleTest.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/ValueHandle.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
14*9880d681SAndroid Build Coastguard Worker #include "gtest/gtest.h"
15*9880d681SAndroid Build Coastguard Worker #include <memory>
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker using namespace llvm;
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker namespace {
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker class ValueHandle : public testing::Test {
22*9880d681SAndroid Build Coastguard Worker protected:
23*9880d681SAndroid Build Coastguard Worker   LLVMContext Context;
24*9880d681SAndroid Build Coastguard Worker   Constant *ConstantV;
25*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<BitCastInst> BitcastV;
26*9880d681SAndroid Build Coastguard Worker 
ValueHandle()27*9880d681SAndroid Build Coastguard Worker   ValueHandle()
28*9880d681SAndroid Build Coastguard Worker       : ConstantV(ConstantInt::get(Type::getInt32Ty(Context), 0)),
29*9880d681SAndroid Build Coastguard Worker         BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(Context))) {}
30*9880d681SAndroid Build Coastguard Worker };
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker class ConcreteCallbackVH final : public CallbackVH {
33*9880d681SAndroid Build Coastguard Worker public:
ConcreteCallbackVH(Value * V)34*9880d681SAndroid Build Coastguard Worker   ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
35*9880d681SAndroid Build Coastguard Worker };
36*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,WeakVH_BasicOperation)37*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, WeakVH_BasicOperation) {
38*9880d681SAndroid Build Coastguard Worker   WeakVH WVH(BitcastV.get());
39*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BitcastV.get(), WVH);
40*9880d681SAndroid Build Coastguard Worker   WVH = ConstantV;
41*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, WVH);
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   // Make sure I can call a method on the underlying Value.  It
44*9880d681SAndroid Build Coastguard Worker   // doesn't matter which method.
45*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Type::getInt32Ty(Context), WVH->getType());
46*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Type::getInt32Ty(Context), (*WVH).getType());
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,WeakVH_Comparisons)49*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, WeakVH_Comparisons) {
50*9880d681SAndroid Build Coastguard Worker   WeakVH BitcastWVH(BitcastV.get());
51*9880d681SAndroid Build Coastguard Worker   WeakVH ConstantWVH(ConstantV);
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastWVH == BitcastWVH);
54*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() == BitcastWVH);
55*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastWVH == BitcastV.get());
56*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastWVH == ConstantWVH);
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastWVH != ConstantWVH);
59*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() != ConstantWVH);
60*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastWVH != ConstantV);
61*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastWVH != BitcastWVH);
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   // Cast to Value* so comparisons work.
64*9880d681SAndroid Build Coastguard Worker   Value *BV = BitcastV.get();
65*9880d681SAndroid Build Coastguard Worker   Value *CV = ConstantV;
66*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH);
67*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH);
68*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH);
69*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH);
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH);
72*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH);
73*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH);
74*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH);
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastWVH < ConstantV);
77*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV);
78*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastWVH > ConstantV);
79*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV);
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,WeakVH_FollowsRAUW)82*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, WeakVH_FollowsRAUW) {
83*9880d681SAndroid Build Coastguard Worker   WeakVH WVH(BitcastV.get());
84*9880d681SAndroid Build Coastguard Worker   WeakVH WVH_Copy(WVH);
85*9880d681SAndroid Build Coastguard Worker   WeakVH WVH_Recreated(BitcastV.get());
86*9880d681SAndroid Build Coastguard Worker   BitcastV->replaceAllUsesWith(ConstantV);
87*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, WVH);
88*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, WVH_Copy);
89*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, WVH_Recreated);
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,WeakVH_NullOnDeletion)92*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, WeakVH_NullOnDeletion) {
93*9880d681SAndroid Build Coastguard Worker   WeakVH WVH(BitcastV.get());
94*9880d681SAndroid Build Coastguard Worker   WeakVH WVH_Copy(WVH);
95*9880d681SAndroid Build Coastguard Worker   WeakVH WVH_Recreated(BitcastV.get());
96*9880d681SAndroid Build Coastguard Worker   BitcastV.reset();
97*9880d681SAndroid Build Coastguard Worker   Value *null_value = nullptr;
98*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(null_value, WVH);
99*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(null_value, WVH_Copy);
100*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(null_value, WVH_Recreated);
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_BasicOperation)104*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_BasicOperation) {
105*9880d681SAndroid Build Coastguard Worker   AssertingVH<CastInst> AVH(BitcastV.get());
106*9880d681SAndroid Build Coastguard Worker   CastInst *implicit_to_exact_type = AVH;
107*9880d681SAndroid Build Coastguard Worker   (void)implicit_to_exact_type;  // Avoid warning.
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> GenericAVH(BitcastV.get());
110*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BitcastV.get(), GenericAVH);
111*9880d681SAndroid Build Coastguard Worker   GenericAVH = ConstantV;
112*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, GenericAVH);
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   // Make sure I can call a method on the underlying CastInst.  It
115*9880d681SAndroid Build Coastguard Worker   // doesn't matter which method.
116*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(AVH->mayWriteToMemory());
117*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE((*AVH).mayWriteToMemory());
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_Const)120*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_Const) {
121*9880d681SAndroid Build Coastguard Worker   const CastInst *ConstBitcast = BitcastV.get();
122*9880d681SAndroid Build Coastguard Worker   AssertingVH<const CastInst> AVH(ConstBitcast);
123*9880d681SAndroid Build Coastguard Worker   const CastInst *implicit_to_exact_type = AVH;
124*9880d681SAndroid Build Coastguard Worker   (void)implicit_to_exact_type;  // Avoid warning.
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_Comparisons)127*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_Comparisons) {
128*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> BitcastAVH(BitcastV.get());
129*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> ConstantAVH(ConstantV);
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastAVH == BitcastAVH);
132*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() == BitcastAVH);
133*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastAVH == BitcastV.get());
134*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastAVH == ConstantAVH);
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastAVH != ConstantAVH);
137*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() != ConstantAVH);
138*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastAVH != ConstantV);
139*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastAVH != BitcastAVH);
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker   // Cast to Value* so comparisons work.
142*9880d681SAndroid Build Coastguard Worker   Value *BV = BitcastV.get();
143*9880d681SAndroid Build Coastguard Worker   Value *CV = ConstantV;
144*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH);
145*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH);
146*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH);
147*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH);
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH);
150*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH);
151*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH);
152*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH);
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastAVH < ConstantV);
155*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV);
156*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastAVH > ConstantV);
157*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV);
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_DoesNotFollowRAUW)160*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) {
161*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> AVH(BitcastV.get());
162*9880d681SAndroid Build Coastguard Worker   BitcastV->replaceAllUsesWith(ConstantV);
163*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BitcastV.get(), AVH);
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker #ifdef NDEBUG
167*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_ReducesToPointer)168*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_ReducesToPointer) {
169*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>));
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker #else  // !NDEBUG
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker #ifdef GTEST_HAS_DEATH_TEST
175*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVH_Asserts)176*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVH_Asserts) {
177*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> AVH(BitcastV.get());
178*9880d681SAndroid Build Coastguard Worker   EXPECT_DEATH({BitcastV.reset();},
179*9880d681SAndroid Build Coastguard Worker                "An asserting value handle still pointed to this value!");
180*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> Copy(AVH);
181*9880d681SAndroid Build Coastguard Worker   AVH = nullptr;
182*9880d681SAndroid Build Coastguard Worker   EXPECT_DEATH({BitcastV.reset();},
183*9880d681SAndroid Build Coastguard Worker                "An asserting value handle still pointed to this value!");
184*9880d681SAndroid Build Coastguard Worker   Copy = nullptr;
185*9880d681SAndroid Build Coastguard Worker   BitcastV.reset();
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker #endif  // GTEST_HAS_DEATH_TEST
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker #endif  // NDEBUG
191*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,CallbackVH_BasicOperation)192*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, CallbackVH_BasicOperation) {
193*9880d681SAndroid Build Coastguard Worker   ConcreteCallbackVH CVH(BitcastV.get());
194*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BitcastV.get(), CVH);
195*9880d681SAndroid Build Coastguard Worker   CVH = ConstantV;
196*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, CVH);
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   // Make sure I can call a method on the underlying Value.  It
199*9880d681SAndroid Build Coastguard Worker   // doesn't matter which method.
200*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Type::getInt32Ty(Context), CVH->getType());
201*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Type::getInt32Ty(Context), (*CVH).getType());
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,CallbackVH_Comparisons)204*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, CallbackVH_Comparisons) {
205*9880d681SAndroid Build Coastguard Worker   ConcreteCallbackVH BitcastCVH(BitcastV.get());
206*9880d681SAndroid Build Coastguard Worker   ConcreteCallbackVH ConstantCVH(ConstantV);
207*9880d681SAndroid Build Coastguard Worker 
208*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastCVH == BitcastCVH);
209*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() == BitcastCVH);
210*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastCVH == BitcastV.get());
211*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastCVH == ConstantCVH);
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastCVH != ConstantCVH);
214*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastV.get() != ConstantCVH);
215*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(BitcastCVH != ConstantV);
216*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(BitcastCVH != BitcastCVH);
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker   // Cast to Value* so comparisons work.
219*9880d681SAndroid Build Coastguard Worker   Value *BV = BitcastV.get();
220*9880d681SAndroid Build Coastguard Worker   Value *CV = ConstantV;
221*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH);
222*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH);
223*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH);
224*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH);
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH);
227*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH);
228*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH);
229*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH);
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV < CV, BitcastCVH < ConstantV);
232*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV);
233*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV > CV, BitcastCVH > ConstantV);
234*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV);
235*9880d681SAndroid Build Coastguard Worker }
236*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,CallbackVH_CallbackOnDeletion)237*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) {
238*9880d681SAndroid Build Coastguard Worker   class RecordingVH final : public CallbackVH {
239*9880d681SAndroid Build Coastguard Worker   public:
240*9880d681SAndroid Build Coastguard Worker     int DeletedCalls;
241*9880d681SAndroid Build Coastguard Worker     int AURWCalls;
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker     RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
244*9880d681SAndroid Build Coastguard Worker     RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {}
245*9880d681SAndroid Build Coastguard Worker 
246*9880d681SAndroid Build Coastguard Worker   private:
247*9880d681SAndroid Build Coastguard Worker     void deleted() override {
248*9880d681SAndroid Build Coastguard Worker       DeletedCalls++;
249*9880d681SAndroid Build Coastguard Worker       CallbackVH::deleted();
250*9880d681SAndroid Build Coastguard Worker     }
251*9880d681SAndroid Build Coastguard Worker     void allUsesReplacedWith(Value *) override { AURWCalls++; }
252*9880d681SAndroid Build Coastguard Worker   };
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker   RecordingVH RVH;
255*9880d681SAndroid Build Coastguard Worker   RVH = BitcastV.get();
256*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(0, RVH.DeletedCalls);
257*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(0, RVH.AURWCalls);
258*9880d681SAndroid Build Coastguard Worker   BitcastV.reset();
259*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(1, RVH.DeletedCalls);
260*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(0, RVH.AURWCalls);
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,CallbackVH_CallbackOnRAUW)263*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) {
264*9880d681SAndroid Build Coastguard Worker   class RecordingVH final : public CallbackVH {
265*9880d681SAndroid Build Coastguard Worker   public:
266*9880d681SAndroid Build Coastguard Worker     int DeletedCalls;
267*9880d681SAndroid Build Coastguard Worker     Value *AURWArgument;
268*9880d681SAndroid Build Coastguard Worker 
269*9880d681SAndroid Build Coastguard Worker     RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {}
270*9880d681SAndroid Build Coastguard Worker     RecordingVH(Value *V)
271*9880d681SAndroid Build Coastguard Worker       : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr) {}
272*9880d681SAndroid Build Coastguard Worker 
273*9880d681SAndroid Build Coastguard Worker   private:
274*9880d681SAndroid Build Coastguard Worker     void deleted() override {
275*9880d681SAndroid Build Coastguard Worker       DeletedCalls++;
276*9880d681SAndroid Build Coastguard Worker       CallbackVH::deleted();
277*9880d681SAndroid Build Coastguard Worker     }
278*9880d681SAndroid Build Coastguard Worker     void allUsesReplacedWith(Value *new_value) override {
279*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(nullptr, AURWArgument);
280*9880d681SAndroid Build Coastguard Worker       AURWArgument = new_value;
281*9880d681SAndroid Build Coastguard Worker     }
282*9880d681SAndroid Build Coastguard Worker   };
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker   RecordingVH RVH;
285*9880d681SAndroid Build Coastguard Worker   RVH = BitcastV.get();
286*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(0, RVH.DeletedCalls);
287*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, RVH.AURWArgument);
288*9880d681SAndroid Build Coastguard Worker   BitcastV->replaceAllUsesWith(ConstantV);
289*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(0, RVH.DeletedCalls);
290*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(ConstantV, RVH.AURWArgument);
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,CallbackVH_DeletionCanRAUW)293*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
294*9880d681SAndroid Build Coastguard Worker   class RecoveringVH final : public CallbackVH {
295*9880d681SAndroid Build Coastguard Worker   public:
296*9880d681SAndroid Build Coastguard Worker     int DeletedCalls;
297*9880d681SAndroid Build Coastguard Worker     Value *AURWArgument;
298*9880d681SAndroid Build Coastguard Worker     LLVMContext *Context;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker     RecoveringVH(LLVMContext &TheContext)
301*9880d681SAndroid Build Coastguard Worker         : DeletedCalls(0), AURWArgument(nullptr), Context(&TheContext) {}
302*9880d681SAndroid Build Coastguard Worker 
303*9880d681SAndroid Build Coastguard Worker     RecoveringVH(LLVMContext &TheContext, Value *V)
304*9880d681SAndroid Build Coastguard Worker         : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr),
305*9880d681SAndroid Build Coastguard Worker           Context(&TheContext) {}
306*9880d681SAndroid Build Coastguard Worker 
307*9880d681SAndroid Build Coastguard Worker   private:
308*9880d681SAndroid Build Coastguard Worker     void deleted() override {
309*9880d681SAndroid Build Coastguard Worker       getValPtr()->replaceAllUsesWith(
310*9880d681SAndroid Build Coastguard Worker           Constant::getNullValue(Type::getInt32Ty(*Context)));
311*9880d681SAndroid Build Coastguard Worker       setValPtr(nullptr);
312*9880d681SAndroid Build Coastguard Worker     }
313*9880d681SAndroid Build Coastguard Worker     void allUsesReplacedWith(Value *new_value) override {
314*9880d681SAndroid Build Coastguard Worker       ASSERT_TRUE(nullptr != getValPtr());
315*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(1U, getValPtr()->getNumUses());
316*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(nullptr, AURWArgument);
317*9880d681SAndroid Build Coastguard Worker       AURWArgument = new_value;
318*9880d681SAndroid Build Coastguard Worker     }
319*9880d681SAndroid Build Coastguard Worker   };
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker   // Normally, if a value has uses, deleting it will crash.  However, we can use
322*9880d681SAndroid Build Coastguard Worker   // a CallbackVH to remove the uses before the check for no uses.
323*9880d681SAndroid Build Coastguard Worker   RecoveringVH RVH(Context);
324*9880d681SAndroid Build Coastguard Worker   RVH = RecoveringVH(Context, BitcastV.get());
325*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<BinaryOperator> BitcastUser(BinaryOperator::CreateAdd(
326*9880d681SAndroid Build Coastguard Worker       RVH, Constant::getNullValue(Type::getInt32Ty(Context))));
327*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0));
328*9880d681SAndroid Build Coastguard Worker   BitcastV.reset();  // Would crash without the ValueHandler.
329*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context)),
330*9880d681SAndroid Build Coastguard Worker             RVH.AURWArgument);
331*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(Context)),
332*9880d681SAndroid Build Coastguard Worker             BitcastUser->getOperand(0));
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,DestroyingOtherVHOnSameValueDoesntBreakIteration)335*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) {
336*9880d681SAndroid Build Coastguard Worker   // When a CallbackVH modifies other ValueHandles in its callbacks,
337*9880d681SAndroid Build Coastguard Worker   // that shouldn't interfere with non-modified ValueHandles receiving
338*9880d681SAndroid Build Coastguard Worker   // their appropriate callbacks.
339*9880d681SAndroid Build Coastguard Worker   //
340*9880d681SAndroid Build Coastguard Worker   // We create the active CallbackVH in the middle of a palindromic
341*9880d681SAndroid Build Coastguard Worker   // arrangement of other VHs so that the bad behavior would be
342*9880d681SAndroid Build Coastguard Worker   // triggered in whichever order callbacks run.
343*9880d681SAndroid Build Coastguard Worker 
344*9880d681SAndroid Build Coastguard Worker   class DestroyingVH final : public CallbackVH {
345*9880d681SAndroid Build Coastguard Worker   public:
346*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<WeakVH> ToClear[2];
347*9880d681SAndroid Build Coastguard Worker     DestroyingVH(Value *V) {
348*9880d681SAndroid Build Coastguard Worker       ToClear[0].reset(new WeakVH(V));
349*9880d681SAndroid Build Coastguard Worker       setValPtr(V);
350*9880d681SAndroid Build Coastguard Worker       ToClear[1].reset(new WeakVH(V));
351*9880d681SAndroid Build Coastguard Worker     }
352*9880d681SAndroid Build Coastguard Worker     void deleted() override {
353*9880d681SAndroid Build Coastguard Worker       ToClear[0].reset();
354*9880d681SAndroid Build Coastguard Worker       ToClear[1].reset();
355*9880d681SAndroid Build Coastguard Worker       CallbackVH::deleted();
356*9880d681SAndroid Build Coastguard Worker     }
357*9880d681SAndroid Build Coastguard Worker     void allUsesReplacedWith(Value *) override {
358*9880d681SAndroid Build Coastguard Worker       ToClear[0].reset();
359*9880d681SAndroid Build Coastguard Worker       ToClear[1].reset();
360*9880d681SAndroid Build Coastguard Worker     }
361*9880d681SAndroid Build Coastguard Worker   };
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker   {
364*9880d681SAndroid Build Coastguard Worker     WeakVH ShouldBeVisited1(BitcastV.get());
365*9880d681SAndroid Build Coastguard Worker     DestroyingVH C(BitcastV.get());
366*9880d681SAndroid Build Coastguard Worker     WeakVH ShouldBeVisited2(BitcastV.get());
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker     BitcastV->replaceAllUsesWith(ConstantV);
369*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
370*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
371*9880d681SAndroid Build Coastguard Worker   }
372*9880d681SAndroid Build Coastguard Worker 
373*9880d681SAndroid Build Coastguard Worker   {
374*9880d681SAndroid Build Coastguard Worker     WeakVH ShouldBeVisited1(BitcastV.get());
375*9880d681SAndroid Build Coastguard Worker     DestroyingVH C(BitcastV.get());
376*9880d681SAndroid Build Coastguard Worker     WeakVH ShouldBeVisited2(BitcastV.get());
377*9880d681SAndroid Build Coastguard Worker 
378*9880d681SAndroid Build Coastguard Worker     BitcastV.reset();
379*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited1));
380*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited2));
381*9880d681SAndroid Build Coastguard Worker   }
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker 
TEST_F(ValueHandle,AssertingVHCheckedLast)384*9880d681SAndroid Build Coastguard Worker TEST_F(ValueHandle, AssertingVHCheckedLast) {
385*9880d681SAndroid Build Coastguard Worker   // If a CallbackVH exists to clear out a group of AssertingVHs on
386*9880d681SAndroid Build Coastguard Worker   // Value deletion, the CallbackVH should get a chance to do so
387*9880d681SAndroid Build Coastguard Worker   // before the AssertingVHs assert.
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker   class ClearingVH final : public CallbackVH {
390*9880d681SAndroid Build Coastguard Worker   public:
391*9880d681SAndroid Build Coastguard Worker     AssertingVH<Value> *ToClear[2];
392*9880d681SAndroid Build Coastguard Worker     ClearingVH(Value *V,
393*9880d681SAndroid Build Coastguard Worker                AssertingVH<Value> &A0, AssertingVH<Value> &A1)
394*9880d681SAndroid Build Coastguard Worker       : CallbackVH(V) {
395*9880d681SAndroid Build Coastguard Worker       ToClear[0] = &A0;
396*9880d681SAndroid Build Coastguard Worker       ToClear[1] = &A1;
397*9880d681SAndroid Build Coastguard Worker     }
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker     void deleted() override {
400*9880d681SAndroid Build Coastguard Worker       *ToClear[0] = nullptr;
401*9880d681SAndroid Build Coastguard Worker       *ToClear[1] = nullptr;
402*9880d681SAndroid Build Coastguard Worker       CallbackVH::deleted();
403*9880d681SAndroid Build Coastguard Worker     }
404*9880d681SAndroid Build Coastguard Worker   };
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   AssertingVH<Value> A1, A2;
407*9880d681SAndroid Build Coastguard Worker   A1 = BitcastV.get();
408*9880d681SAndroid Build Coastguard Worker   ClearingVH C(BitcastV.get(), A1, A2);
409*9880d681SAndroid Build Coastguard Worker   A2 = BitcastV.get();
410*9880d681SAndroid Build Coastguard Worker   // C.deleted() should run first, clearing the two AssertingVHs,
411*9880d681SAndroid Build Coastguard Worker   // which should prevent them from asserting.
412*9880d681SAndroid Build Coastguard Worker   BitcastV.reset();
413*9880d681SAndroid Build Coastguard Worker }
414*9880d681SAndroid Build Coastguard Worker 
415*9880d681SAndroid Build Coastguard Worker }
416