Fix an MSVC failure from r223802
[oota-llvm.git] / include / llvm / IR / TrackingMDRef.h
1 //===- llvm/IR/TrackingMDRef.h - Tracking Metadata references -------------===//
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 // References to metadata that track RAUW.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_IR_TRACKINGMDREF_H
15 #define LLVM_IR_TRACKINGMDREF_H
16
17 #include "llvm/IR/MetadataTracking.h"
18 #include "llvm/Support/Casting.h"
19
20 namespace llvm {
21
22 class Metadata;
23 class MDNode;
24 class ValueAsMetadata;
25
26 /// \brief Tracking metadata reference.
27 ///
28 /// This class behaves like \a TrackingVH, but for metadata.
29 class TrackingMDRef {
30   Metadata *MD;
31
32 public:
33   TrackingMDRef() : MD(nullptr) {}
34   explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
35
36   TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
37   TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
38   TrackingMDRef &operator=(TrackingMDRef &&X) {
39     if (&X == this)
40       return *this;
41
42     untrack();
43     MD = X.MD;
44     retrack(X);
45     return *this;
46   }
47   TrackingMDRef &operator=(const TrackingMDRef &X) {
48     if (&X == this)
49       return *this;
50
51     untrack();
52     MD = X.MD;
53     track();
54     return *this;
55   }
56   ~TrackingMDRef() { untrack(); }
57
58   LLVM_EXPLICIT operator bool() const { return get(); }
59   Metadata *get() const { return MD; }
60   operator Metadata *() const { return get(); }
61   Metadata *operator->() const { return get(); }
62   Metadata &operator*() const { return *get(); }
63
64   void reset() {
65     untrack();
66     MD = nullptr;
67   }
68   void reset(Metadata *MD) {
69     untrack();
70     this->MD = MD;
71     track();
72   }
73
74   /// \brief Check whether this has a trivial destructor.
75   ///
76   /// If \c MD isn't replaceable, the destructor will be a no-op.
77   bool hasTrivialDestructor() const {
78     return !MD || !MetadataTracking::isReplaceable(*MD);
79   }
80
81   bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
82   bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
83
84 private:
85   void track() {
86     if (MD)
87       MetadataTracking::track(MD);
88   }
89   void untrack() {
90     if (MD)
91       MetadataTracking::untrack(MD);
92   }
93   void retrack(TrackingMDRef &X) {
94     assert(MD == X.MD && "Expected values to match");
95     if (X.MD) {
96       MetadataTracking::retrack(X.MD, MD);
97       X.MD = nullptr;
98     }
99   }
100 };
101
102 /// \brief Typed tracking ref.
103 ///
104 /// Track refererences of a particular type.  It's useful to use this for \a
105 /// MDNode and \a ValueAsMetadata.
106 template <class T> class TypedTrackingMDRef {
107   TrackingMDRef Ref;
108
109 public:
110   TypedTrackingMDRef() {}
111   explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
112
113   TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
114   TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
115   TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
116     Ref = std::move(X.Ref);
117     return *this;
118   }
119   TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
120     Ref = X.Ref;
121     return *this;
122   }
123
124   LLVM_EXPLICIT operator bool() const { return get(); }
125   T *get() const { return (T *)Ref.get(); }
126   operator T *() const { return get(); }
127   T *operator->() const { return get(); }
128   T &operator*() const { return *get(); }
129
130   bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
131   bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
132
133   void reset() { Ref.reset(); }
134   void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
135
136   /// \brief Check whether this has a trivial destructor.
137   bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
138 };
139
140 typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
141 typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
142
143 // Expose the underlying metadata to casting.
144 template <> struct simplify_type<TrackingMDRef> {
145   typedef Metadata *SimpleType;
146   static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
147 };
148
149 template <> struct simplify_type<const TrackingMDRef> {
150   typedef Metadata *SimpleType;
151   static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
152     return MD.get();
153   }
154 };
155
156 template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
157   typedef T *SimpleType;
158   static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
159     return MD.get();
160   }
161 };
162
163 template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
164   typedef T *SimpleType;
165   static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
166     return MD.get();
167   }
168 };
169
170 } // end namespace llvm
171
172 #endif