llvm/llvm/include/llvm/IR/ValueHandle.h

//===- 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