Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/ADT/EpochTracker.h
Line
Count
Source (jump to first uncovered line)
1
//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
11
// These can be used to write iterators that are fail-fast when LLVM is built
12
// with asserts enabled.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#ifndef LLVM_ADT_EPOCH_TRACKER_H
17
#define LLVM_ADT_EPOCH_TRACKER_H
18
19
#include "llvm/Config/abi-breaking.h"
20
#include "llvm/Config/llvm-config.h"
21
22
#include <cstdint>
23
24
namespace llvm {
25
26
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
27
28
/// \brief A base class for data structure classes wishing to make iterators
29
/// ("handles") pointing into themselves fail-fast.  When building without
30
/// asserts, this class is empty and does nothing.
31
///
32
/// DebugEpochBase does not by itself track handles pointing into itself.  The
33
/// expectation is that routines touching the handles will poll on
34
/// isHandleInSync at appropriate points to assert that the handle they're using
35
/// is still valid.
36
///
37
class DebugEpochBase {
38
  uint64_t Epoch;
39
40
public:
41
  DebugEpochBase() : Epoch(0) {}
42
43
  /// \brief Calling incrementEpoch invalidates all handles pointing into the
44
  /// calling instance.
45
  void incrementEpoch() { ++Epoch; }
46
47
  /// \brief The destructor calls incrementEpoch to make use-after-free bugs
48
  /// more likely to crash deterministically.
49
  ~DebugEpochBase() { incrementEpoch(); }
50
51
  /// \brief A base class for iterator classes ("handles") that wish to poll for
52
  /// iterator invalidating modifications in the underlying data structure.
53
  /// When LLVM is built without asserts, this class is empty and does nothing.
54
  ///
55
  /// HandleBase does not track the parent data structure by itself.  It expects
56
  /// the routines modifying the data structure to call incrementEpoch when they
57
  /// make an iterator-invalidating modification.
58
  ///
59
  class HandleBase {
60
    const uint64_t *EpochAddress;
61
    uint64_t EpochAtCreation;
62
63
  public:
64
    HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
65
66
    explicit HandleBase(const DebugEpochBase *Parent)
67
        : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
68
69
    /// \brief Returns true if the DebugEpochBase this Handle is linked to has
70
    /// not called incrementEpoch on itself since the creation of this
71
    /// HandleBase instance.
72
    bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
73
74
    /// \brief Returns a pointer to the epoch word stored in the data structure
75
    /// this handle points into.  Can be used to check if two iterators point
76
    /// into the same data structure.
77
    const void *getEpochAddress() const { return EpochAddress; }
78
  };
79
};
80
81
#else
82
83
class DebugEpochBase {
84
public:
85
3.14G
  void incrementEpoch() {}
86
87
  class HandleBase {
88
  public:
89
    HandleBase() = default;
90
20.3G
    explicit HandleBase(const DebugEpochBase *) {}
91
0
    bool isHandleInSync() const { return true; }
92
0
    const void *getEpochAddress() const { return nullptr; }
93
  };
94
};
95
96
#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
97
98
} // namespace llvm
99
100
#endif