//===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file declares the ValueHandle class and its sub-classes. // //===----------------------------------------------------------------------===// #ifndef LLVM_IR_VALUEHANDLE_H #define LLVM_IR_VALUEHANDLE_H #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include <cassert> namespace llvm { /// This is the common base class of value handles. /// /// ValueHandle's are smart pointers to Value's that have special behavior when /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles /// below for details. class ValueHandleBase { … }; /// 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 { … }; // Specialize simplify_type to allow WeakVH to participate in // dyn_cast, isa, etc. template <> struct simplify_type<WeakVH> { … }; template <> struct simplify_type<const WeakVH> { … }; // Specialize DenseMapInfo to allow WeakVH to participate in DenseMap. template <> struct DenseMapInfo<WeakVH> { … }; /// 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 /// RAUW operations, but will null itself out if the value is destroyed. this /// is useful for advisory sorts of information, but should not be used as the /// key of a map (since the map would have to rearrange itself when the pointer /// changes). class WeakTrackingVH : public ValueHandleBase { … }; // Specialize simplify_type to allow WeakTrackingVH to participate in // dyn_cast, isa, etc. template <> struct simplify_type<WeakTrackingVH> { … }; template <> struct simplify_type<const WeakTrackingVH> { … }; /// Value handle that asserts if the Value is deleted. /// /// This is a Value Handle that points to a value and asserts out if the value /// is destroyed while the handle is still live. This is very useful for /// catching dangling pointer bugs and other things which can be non-obvious. /// One particularly useful place to use this is as the Key of a map. Dangling /// pointer bugs often lead to really subtle bugs that only occur if another /// object happens to get allocated to the same address as the old one. Using /// an AssertingVH ensures that an assert is triggered as soon as the bad /// delete occurs. /// /// Note that an AssertingVH handle does *not* follow values across RAUW /// operations. This means that RAUW's need to explicitly update the /// AssertingVH's as it moves. This is required because in non-assert mode this /// class turns into a trivial wrapper around a pointer. template <typename ValueTy> class AssertingVH #if LLVM_ENABLE_ABI_BREAKING_CHECKS : public ValueHandleBase #endif { … }; // Treat AssertingVH<T> like T* inside maps. This also allows using find_as() // to look up a value without constructing a value handle. DenseMapInfo<AssertingVH<T>>; /// Value handle that tracks a Value across RAUW. /// /// TrackingVH is designed for situations where a client needs to hold a handle /// to a Value (or subclass) across some operations which may move that value, /// but should never destroy it or replace it with some unacceptable type. /// /// It is an error to attempt to replace a value with one of a type which is /// incompatible with any of its outstanding TrackingVHs. /// /// It is an error to read from a TrackingVH that does not point to a valid /// value. A TrackingVH is said to not point to a valid value if either it /// hasn't yet been assigned a value yet or because the value it was tracking /// has since been deleted. /// /// Assigning a value to a TrackingVH is always allowed, even if said TrackingVH /// no longer points to a valid value. template <typename ValueTy> class TrackingVH { … }; /// Value handle with callbacks on RAUW and destruction. /// /// This is a value handle that allows subclasses to define callbacks that run /// when the underlying Value has RAUW called on it or is destroyed. This /// class can be used as the key of a map, as long as the user takes it out of /// the map before calling setValPtr() (since the map has to rearrange itself /// when the pointer changes). Unlike ValueHandleBase, this class has a vtable. class CallbackVH : public ValueHandleBase { … }; /// Value handle that poisons itself if the Value is deleted. /// /// This is a Value Handle that points to a value and poisons itself if the /// value is destroyed while the handle is still live. This is very useful for /// catching dangling pointer bugs where an \c AssertingVH cannot be used /// because the dangling handle needs to outlive the value without ever being /// used. /// /// One particularly useful place to use this is as the Key of a map. Dangling /// pointer bugs often lead to really subtle bugs that only occur if another /// object happens to get allocated to the same address as the old one. Using /// a PoisoningVH ensures that an assert is triggered if looking up a new value /// in the map finds a handle from the old value. /// /// Note that a PoisoningVH handle does *not* follow values across RAUW /// operations. This means that RAUW's need to explicitly update the /// PoisoningVH's as it moves. This is required because in non-assert mode this /// class turns into a trivial wrapper around a pointer. template <typename ValueTy> class PoisoningVH final #if LLVM_ENABLE_ABI_BREAKING_CHECKS : public CallbackVH #endif { … }; // Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap. DenseMapInfo<PoisoningVH<T>>; } // end namespace llvm #endif // LLVM_IR_VALUEHANDLE_H