Index: llvm/trunk/include/llvm/IR/ValueHandle.h =================================================================== --- llvm/trunk/include/llvm/IR/ValueHandle.h +++ llvm/trunk/include/llvm/IR/ValueHandle.h @@ -34,7 +34,7 @@ /// /// This is to avoid having a vtable for the light-weight handle pointers. The /// fully general Callback version does have a vtable. - enum HandleBaseKind { Assert, Callback, Tracking, WeakTracking }; + enum HandleBaseKind { Assert, Callback, Tracking, Weak, WeakTracking }; ValueHandleBase(const ValueHandleBase &RHS) : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {} @@ -46,7 +46,7 @@ } private: - PointerIntPair PrevPair; + PointerIntPair PrevPair; ValueHandleBase *Next; Value* V; @@ -126,6 +126,42 @@ void AddToUseList(); }; +/// \brief A nullable Value handle that is nullable. +/// +/// This is a value handle that points to a value, and nulls itself +/// out if that value is deleted. +class WeakVH : public ValueHandleBase { +public: + WeakVH() : ValueHandleBase(Weak) {} + WeakVH(Value *P) : ValueHandleBase(Weak, P) {} + WeakVH(const WeakVH &RHS) + : ValueHandleBase(Weak, RHS) {} + + WeakVH &operator=(const WeakVH &RHS) = default; + + Value *operator=(Value *RHS) { + return ValueHandleBase::operator=(RHS); + } + Value *operator=(const ValueHandleBase &RHS) { + return ValueHandleBase::operator=(RHS); + } + + operator Value*() const { + return getValPtr(); + } +}; + +// Specialize simplify_type to allow WeakVH to participate in +// dyn_cast, isa, etc. +template <> struct simplify_type { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } +}; +template <> struct simplify_type { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } +}; + /// \brief Value handle that is nullable, but tries to track the Value. /// /// This is a value handle that tries hard to point to a Value, even across Index: llvm/trunk/lib/IR/Value.cpp =================================================================== --- llvm/trunk/lib/IR/Value.cpp +++ llvm/trunk/lib/IR/Value.cpp @@ -825,8 +825,10 @@ // pointer. Entry->operator=(DenseMapInfo::getTombstoneKey()); break; + case Weak: case WeakTracking: - // WeakTracking just goes to null, which will unlink it from the list. + // WeakTracking and Weak just go to null, which unlinks them + // from the list. Entry->operator=(nullptr); break; case Callback: @@ -874,7 +876,8 @@ switch (Entry->getKind()) { case Assert: - // Asserting handle does not follow RAUW implicitly. + case Weak: + // Asserting and Weak handles do not follow RAUW implicitly. break; case Tracking: // Tracking goes to new value like a WeakTrackingVH. Note that this may Index: llvm/trunk/unittests/IR/ValueHandleTest.cpp =================================================================== --- llvm/trunk/unittests/IR/ValueHandleTest.cpp +++ llvm/trunk/unittests/IR/ValueHandleTest.cpp @@ -34,6 +34,24 @@ ConcreteCallbackVH(Value *V) : CallbackVH(V) {} }; +TEST_F(ValueHandle, WeakVH_BasicOperation) { + WeakVH WVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), WVH); + WVH = ConstantV; + EXPECT_EQ(ConstantV, WVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(Context), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(Context), (*WVH).getType()); + + WVH = BitcastV.get(); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(WVH, BitcastV.get()); + BitcastV.reset(); + EXPECT_EQ(WVH, nullptr); +} + TEST_F(ValueHandle, WeakTrackingVH_BasicOperation) { WeakTrackingVH WVH(BitcastV.get()); EXPECT_EQ(BitcastV.get(), WVH);