Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:04

0001 //===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
0011 /// These can be used to write iterators that are fail-fast when LLVM is built
0012 /// with asserts enabled.
0013 ///
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_ADT_EPOCHTRACKER_H
0017 #define LLVM_ADT_EPOCHTRACKER_H
0018 
0019 #include "llvm/Config/abi-breaking.h"
0020 
0021 #include <cstdint>
0022 
0023 namespace llvm {
0024 
0025 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0026 #define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE
0027 
0028 /// A base class for data structure classes wishing to make iterators
0029 /// ("handles") pointing into themselves fail-fast.  When building without
0030 /// asserts, this class is empty and does nothing.
0031 ///
0032 /// DebugEpochBase does not by itself track handles pointing into itself.  The
0033 /// expectation is that routines touching the handles will poll on
0034 /// isHandleInSync at appropriate points to assert that the handle they're using
0035 /// is still valid.
0036 ///
0037 class DebugEpochBase {
0038   uint64_t Epoch = 0;
0039 
0040 public:
0041   DebugEpochBase() = default;
0042 
0043   /// Calling incrementEpoch invalidates all handles pointing into the
0044   /// calling instance.
0045   void incrementEpoch() { ++Epoch; }
0046 
0047   /// The destructor calls incrementEpoch to make use-after-free bugs
0048   /// more likely to crash deterministically.
0049   ~DebugEpochBase() { incrementEpoch(); }
0050 
0051   /// A base class for iterator classes ("handles") that wish to poll for
0052   /// iterator invalidating modifications in the underlying data structure.
0053   /// When LLVM is built without asserts, this class is empty and does nothing.
0054   ///
0055   /// HandleBase does not track the parent data structure by itself.  It expects
0056   /// the routines modifying the data structure to call incrementEpoch when they
0057   /// make an iterator-invalidating modification.
0058   ///
0059   class HandleBase {
0060     const uint64_t *EpochAddress = nullptr;
0061     uint64_t EpochAtCreation = UINT64_MAX;
0062 
0063   public:
0064     HandleBase() = default;
0065 
0066     explicit HandleBase(const DebugEpochBase *Parent)
0067         : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
0068 
0069     /// Returns true if the DebugEpochBase this Handle is linked to has
0070     /// not called incrementEpoch on itself since the creation of this
0071     /// HandleBase instance.
0072     bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
0073 
0074     /// Returns a pointer to the epoch word stored in the data structure
0075     /// this handle points into.  Can be used to check if two iterators point
0076     /// into the same data structure.
0077     const void *getEpochAddress() const { return EpochAddress; }
0078   };
0079 };
0080 
0081 #else
0082 #ifdef _MSC_VER
0083 #define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE __declspec(empty_bases)
0084 #else
0085 #define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE
0086 #endif // _MSC_VER
0087 
0088 class DebugEpochBase {
0089 public:
0090   void incrementEpoch() {}
0091 
0092   class HandleBase {
0093   public:
0094     HandleBase() = default;
0095     explicit HandleBase(const DebugEpochBase *) {}
0096     bool isHandleInSync() const { return true; }
0097     const void *getEpochAddress() const { return nullptr; }
0098   };
0099 };
0100 
0101 #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
0102 
0103 } // namespace llvm
0104 
0105 #endif