File: | tools/clang/lib/Format/TokenAnalyzer.cpp |
Warning: | line 157, column 38 Potential leak of memory pointed to by field 'Obj' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- TokenAnalyzer.cpp - Analyze Token Streams --------------*- 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 | /// \file | |||
11 | /// \brief This file implements an abstract TokenAnalyzer and associated helper | |||
12 | /// classes. TokenAnalyzer can be extended to generate replacements based on | |||
13 | /// an annotated and pre-processed token stream. | |||
14 | /// | |||
15 | //===----------------------------------------------------------------------===// | |||
16 | ||||
17 | #include "TokenAnalyzer.h" | |||
18 | #include "AffectedRangeManager.h" | |||
19 | #include "Encoding.h" | |||
20 | #include "FormatToken.h" | |||
21 | #include "FormatTokenLexer.h" | |||
22 | #include "TokenAnnotator.h" | |||
23 | #include "UnwrappedLineParser.h" | |||
24 | #include "clang/Basic/Diagnostic.h" | |||
25 | #include "clang/Basic/DiagnosticOptions.h" | |||
26 | #include "clang/Basic/FileManager.h" | |||
27 | #include "clang/Basic/SourceManager.h" | |||
28 | #include "clang/Format/Format.h" | |||
29 | #include "llvm/ADT/STLExtras.h" | |||
30 | #include "llvm/Support/Debug.h" | |||
31 | ||||
32 | #define DEBUG_TYPE"format-formatter" "format-formatter" | |||
33 | ||||
34 | namespace clang { | |||
35 | namespace format { | |||
36 | ||||
37 | // This sets up an virtual file system with file \p FileName containing \p | |||
38 | // Code. | |||
39 | std::unique_ptr<Environment> | |||
40 | Environment::CreateVirtualEnvironment(StringRef Code, StringRef FileName, | |||
41 | ArrayRef<tooling::Range> Ranges, | |||
42 | unsigned FirstStartColumn, | |||
43 | unsigned NextStartColumn, | |||
44 | unsigned LastStartColumn) { | |||
45 | // This is referenced by `FileMgr` and will be released by `FileMgr` when it | |||
46 | // is deleted. | |||
47 | IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem( | |||
48 | new vfs::InMemoryFileSystem); | |||
49 | // This is passed to `SM` as reference, so the pointer has to be referenced | |||
50 | // in `Environment` so that `FileMgr` can out-live this function scope. | |||
51 | std::unique_ptr<FileManager> FileMgr( | |||
52 | new FileManager(FileSystemOptions(), InMemoryFileSystem)); | |||
53 | // This is passed to `SM` as reference, so the pointer has to be referenced | |||
54 | // by `Environment` due to the same reason above. | |||
55 | std::unique_ptr<DiagnosticsEngine> Diagnostics(new DiagnosticsEngine( | |||
56 | IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), | |||
57 | new DiagnosticOptions)); | |||
| ||||
58 | // This will be stored as reference, so the pointer has to be stored in | |||
59 | // due to the same reason above. | |||
60 | std::unique_ptr<SourceManager> VirtualSM( | |||
61 | new SourceManager(*Diagnostics, *FileMgr)); | |||
62 | InMemoryFileSystem->addFile( | |||
63 | FileName, 0, | |||
64 | llvm::MemoryBuffer::getMemBuffer(Code, FileName, | |||
65 | /*RequiresNullTerminator=*/false)); | |||
66 | FileID ID = VirtualSM->createFileID(FileMgr->getFile(FileName), | |||
67 | SourceLocation(), clang::SrcMgr::C_User); | |||
68 | assert(ID.isValid())(static_cast <bool> (ID.isValid()) ? void (0) : __assert_fail ("ID.isValid()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Format/TokenAnalyzer.cpp" , 68, __extension__ __PRETTY_FUNCTION__)); | |||
69 | SourceLocation StartOfFile = VirtualSM->getLocForStartOfFile(ID); | |||
70 | std::vector<CharSourceRange> CharRanges; | |||
71 | for (const tooling::Range &Range : Ranges) { | |||
72 | SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset()); | |||
73 | SourceLocation End = Start.getLocWithOffset(Range.getLength()); | |||
74 | CharRanges.push_back(CharSourceRange::getCharRange(Start, End)); | |||
75 | } | |||
76 | return llvm::make_unique<Environment>( | |||
77 | ID, std::move(FileMgr), std::move(VirtualSM), std::move(Diagnostics), | |||
78 | CharRanges, FirstStartColumn, NextStartColumn, LastStartColumn); | |||
79 | } | |||
80 | ||||
81 | TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style) | |||
82 | : Style(Style), Env(Env), | |||
83 | AffectedRangeMgr(Env.getSourceManager(), Env.getCharRanges()), | |||
84 | UnwrappedLines(1), | |||
85 | Encoding(encoding::detectEncoding( | |||
86 | Env.getSourceManager().getBufferData(Env.getFileID()))) { | |||
87 | DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "File encoding: " << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown" ) << "\n"; } } while (false) | |||
88 | llvm::dbgs() << "File encoding: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "File encoding: " << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown" ) << "\n"; } } while (false) | |||
89 | << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "File encoding: " << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown" ) << "\n"; } } while (false) | |||
90 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "File encoding: " << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown" ) << "\n"; } } while (false); | |||
91 | DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "Language: " << getLanguageName(Style.Language) << "\n"; } } while (false ) | |||
92 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "Language: " << getLanguageName(Style.Language) << "\n"; } } while (false ); | |||
93 | } | |||
94 | ||||
95 | std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() { | |||
96 | tooling::Replacements Result; | |||
97 | FormatTokenLexer Tokens(Env.getSourceManager(), Env.getFileID(), | |||
98 | Env.getFirstStartColumn(), Style, Encoding); | |||
99 | ||||
100 | UnwrappedLineParser Parser(Style, Tokens.getKeywords(), | |||
101 | Env.getFirstStartColumn(), Tokens.lex(), *this); | |||
102 | Parser.parse(); | |||
103 | assert(UnwrappedLines.rbegin()->empty())(static_cast <bool> (UnwrappedLines.rbegin()->empty( )) ? void (0) : __assert_fail ("UnwrappedLines.rbegin()->empty()" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Format/TokenAnalyzer.cpp" , 103, __extension__ __PRETTY_FUNCTION__)); | |||
104 | unsigned Penalty = 0; | |||
105 | for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE; ++Run) { | |||
106 | DEBUG(llvm::dbgs() << "Run " << Run << "...\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { llvm::dbgs() << "Run " << Run << "...\n"; } } while (false); | |||
107 | SmallVector<AnnotatedLine *, 16> AnnotatedLines; | |||
108 | ||||
109 | TokenAnnotator Annotator(Style, Tokens.getKeywords()); | |||
110 | for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) { | |||
111 | AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i])); | |||
112 | Annotator.annotate(*AnnotatedLines.back()); | |||
113 | } | |||
114 | ||||
115 | std::pair<tooling::Replacements, unsigned> RunResult = | |||
116 | analyze(Annotator, AnnotatedLines, Tokens); | |||
117 | ||||
118 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
119 | llvm::dbgs() << "Replacements for run " << Run << ":\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
120 | for (tooling::Replacements::const_iterator I = RunResult.first.begin(),do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
121 | E = RunResult.first.end();do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
122 | I != E; ++I) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
123 | llvm::dbgs() << I->toString() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
124 | }do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false) | |||
125 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-formatter")) { { llvm::dbgs() << "Replacements for run " << Run << ":\n"; for (tooling::Replacements::const_iterator I = RunResult.first.begin(), E = RunResult.first.end(); I != E; ++I) { llvm::dbgs() << I->toString() << "\n" ; } }; } } while (false); | |||
126 | for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { | |||
127 | delete AnnotatedLines[i]; | |||
128 | } | |||
129 | ||||
130 | Penalty += RunResult.second; | |||
131 | for (const auto &R : RunResult.first) { | |||
132 | auto Err = Result.add(R); | |||
133 | // FIXME: better error handling here. For now, simply return an empty | |||
134 | // Replacements to indicate failure. | |||
135 | if (Err) { | |||
136 | llvm::errs() << llvm::toString(std::move(Err)) << "\n"; | |||
137 | return {tooling::Replacements(), 0}; | |||
138 | } | |||
139 | } | |||
140 | } | |||
141 | return {Result, Penalty}; | |||
142 | } | |||
143 | ||||
144 | void TokenAnalyzer::consumeUnwrappedLine(const UnwrappedLine &TheLine) { | |||
145 | assert(!UnwrappedLines.empty())(static_cast <bool> (!UnwrappedLines.empty()) ? void (0 ) : __assert_fail ("!UnwrappedLines.empty()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Format/TokenAnalyzer.cpp" , 145, __extension__ __PRETTY_FUNCTION__)); | |||
146 | UnwrappedLines.back().push_back(TheLine); | |||
147 | } | |||
148 | ||||
149 | void TokenAnalyzer::finishRun() { | |||
150 | UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>()); | |||
151 | } | |||
152 | ||||
153 | } // end namespace format | |||
154 | } // end namespace clang |
1 | //==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- 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 RefCountedBase, ThreadSafeRefCountedBase, and | |||
11 | // IntrusiveRefCntPtr classes. | |||
12 | // | |||
13 | // IntrusiveRefCntPtr is a smart pointer to an object which maintains a | |||
14 | // reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a | |||
15 | // refcount member variable and methods for updating the refcount. An object | |||
16 | // that inherits from (ThreadSafe)RefCountedBase deletes itself when its | |||
17 | // refcount hits zero. | |||
18 | // | |||
19 | // For example: | |||
20 | // | |||
21 | // class MyClass : public RefCountedBase<MyClass> {}; | |||
22 | // | |||
23 | // void foo() { | |||
24 | // // Constructing an IntrusiveRefCntPtr increases the pointee's refcount by | |||
25 | // // 1 (from 0 in this case). | |||
26 | // IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); | |||
27 | // | |||
28 | // // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. | |||
29 | // IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1); | |||
30 | // | |||
31 | // // Constructing an IntrusiveRefCntPtr has no effect on the object's | |||
32 | // // refcount. After a move, the moved-from pointer is null. | |||
33 | // IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1)); | |||
34 | // assert(Ptr1 == nullptr); | |||
35 | // | |||
36 | // // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. | |||
37 | // Ptr2.reset(); | |||
38 | // | |||
39 | // // The object deletes itself when we return from the function, because | |||
40 | // // Ptr3's destructor decrements its refcount to 0. | |||
41 | // } | |||
42 | // | |||
43 | // You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.: | |||
44 | // | |||
45 | // IntrusiveRefCntPtr<MyClass> Ptr(new MyClass()); | |||
46 | // OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required | |||
47 | // | |||
48 | // IntrusiveRefCntPtr works with any class that | |||
49 | // | |||
50 | // - inherits from (ThreadSafe)RefCountedBase, | |||
51 | // - has Retain() and Release() methods, or | |||
52 | // - specializes IntrusiveRefCntPtrInfo. | |||
53 | // | |||
54 | //===----------------------------------------------------------------------===// | |||
55 | ||||
56 | #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H | |||
57 | #define LLVM_ADT_INTRUSIVEREFCNTPTR_H | |||
58 | ||||
59 | #include <atomic> | |||
60 | #include <cassert> | |||
61 | #include <cstddef> | |||
62 | ||||
63 | namespace llvm { | |||
64 | ||||
65 | /// A CRTP mixin class that adds reference counting to a type. | |||
66 | /// | |||
67 | /// The lifetime of an object which inherits from RefCountedBase is managed by | |||
68 | /// calls to Release() and Retain(), which increment and decrement the object's | |||
69 | /// refcount, respectively. When a Release() call decrements the refcount to 0, | |||
70 | /// the object deletes itself. | |||
71 | template <class Derived> class RefCountedBase { | |||
72 | mutable unsigned RefCount = 0; | |||
73 | ||||
74 | public: | |||
75 | RefCountedBase() = default; | |||
76 | RefCountedBase(const RefCountedBase &) {} | |||
77 | ||||
78 | void Retain() const { ++RefCount; } | |||
79 | ||||
80 | void Release() const { | |||
81 | assert(RefCount > 0 && "Reference count is already zero.")(static_cast <bool> (RefCount > 0 && "Reference count is already zero." ) ? void (0) : __assert_fail ("RefCount > 0 && \"Reference count is already zero.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/IntrusiveRefCntPtr.h" , 81, __extension__ __PRETTY_FUNCTION__)); | |||
82 | if (--RefCount == 0) | |||
83 | delete static_cast<const Derived *>(this); | |||
84 | } | |||
85 | }; | |||
86 | ||||
87 | /// A thread-safe version of \c RefCountedBase. | |||
88 | template <class Derived> class ThreadSafeRefCountedBase { | |||
89 | mutable std::atomic<int> RefCount; | |||
90 | ||||
91 | protected: | |||
92 | ThreadSafeRefCountedBase() : RefCount(0) {} | |||
93 | ||||
94 | public: | |||
95 | void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } | |||
96 | ||||
97 | void Release() const { | |||
98 | int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; | |||
99 | assert(NewRefCount >= 0 && "Reference count was already zero.")(static_cast <bool> (NewRefCount >= 0 && "Reference count was already zero." ) ? void (0) : __assert_fail ("NewRefCount >= 0 && \"Reference count was already zero.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/IntrusiveRefCntPtr.h" , 99, __extension__ __PRETTY_FUNCTION__)); | |||
100 | if (NewRefCount == 0) | |||
101 | delete static_cast<const Derived *>(this); | |||
102 | } | |||
103 | }; | |||
104 | ||||
105 | /// Class you can specialize to provide custom retain/release functionality for | |||
106 | /// a type. | |||
107 | /// | |||
108 | /// Usually specializing this class is not necessary, as IntrusiveRefCntPtr | |||
109 | /// works with any type which defines Retain() and Release() functions -- you | |||
110 | /// can define those functions yourself if RefCountedBase doesn't work for you. | |||
111 | /// | |||
112 | /// One case when you might want to specialize this type is if you have | |||
113 | /// - Foo.h defines type Foo and includes Bar.h, and | |||
114 | /// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions. | |||
115 | /// | |||
116 | /// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in | |||
117 | /// the declaration of Foo. Without the declaration of Foo, normally Bar.h | |||
118 | /// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call | |||
119 | /// T::Retain and T::Release. | |||
120 | /// | |||
121 | /// To resolve this, Bar.h could include a third header, FooFwd.h, which | |||
122 | /// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then | |||
123 | /// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any | |||
124 | /// functions on Foo itself, because Foo would be an incomplete type. | |||
125 | template <typename T> struct IntrusiveRefCntPtrInfo { | |||
126 | static void retain(T *obj) { obj->Retain(); } | |||
127 | static void release(T *obj) { obj->Release(); } | |||
128 | }; | |||
129 | ||||
130 | /// A smart pointer to a reference-counted object that inherits from | |||
131 | /// RefCountedBase or ThreadSafeRefCountedBase. | |||
132 | /// | |||
133 | /// This class increments its pointee's reference count when it is created, and | |||
134 | /// decrements its refcount when it's destroyed (or is changed to point to a | |||
135 | /// different object). | |||
136 | template <typename T> class IntrusiveRefCntPtr { | |||
137 | T *Obj = nullptr; | |||
138 | ||||
139 | public: | |||
140 | using element_type = T; | |||
141 | ||||
142 | explicit IntrusiveRefCntPtr() = default; | |||
143 | IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } | |||
144 | IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } | |||
145 | IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } | |||
146 | ||||
147 | template <class X> | |||
148 | IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> &&S) : Obj(S.get()) { | |||
149 | S.Obj = nullptr; | |||
150 | } | |||
151 | ||||
152 | template <class X> | |||
153 | IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> &S) : Obj(S.get()) { | |||
154 | retain(); | |||
155 | } | |||
156 | ||||
157 | ~IntrusiveRefCntPtr() { release(); } | |||
| ||||
158 | ||||
159 | IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { | |||
160 | swap(S); | |||
161 | return *this; | |||
162 | } | |||
163 | ||||
164 | T &operator*() const { return *Obj; } | |||
165 | T *operator->() const { return Obj; } | |||
166 | T *get() const { return Obj; } | |||
167 | explicit operator bool() const { return Obj; } | |||
168 | ||||
169 | void swap(IntrusiveRefCntPtr &other) { | |||
170 | T *tmp = other.Obj; | |||
171 | other.Obj = Obj; | |||
172 | Obj = tmp; | |||
173 | } | |||
174 | ||||
175 | void reset() { | |||
176 | release(); | |||
177 | Obj = nullptr; | |||
178 | } | |||
179 | ||||
180 | void resetWithoutRelease() { Obj = nullptr; } | |||
181 | ||||
182 | private: | |||
183 | void retain() { | |||
184 | if (Obj) | |||
185 | IntrusiveRefCntPtrInfo<T>::retain(Obj); | |||
186 | } | |||
187 | ||||
188 | void release() { | |||
189 | if (Obj) | |||
190 | IntrusiveRefCntPtrInfo<T>::release(Obj); | |||
191 | } | |||
192 | ||||
193 | template <typename X> friend class IntrusiveRefCntPtr; | |||
194 | }; | |||
195 | ||||
196 | template <class T, class U> | |||
197 | inline bool operator==(const IntrusiveRefCntPtr<T> &A, | |||
198 | const IntrusiveRefCntPtr<U> &B) { | |||
199 | return A.get() == B.get(); | |||
200 | } | |||
201 | ||||
202 | template <class T, class U> | |||
203 | inline bool operator!=(const IntrusiveRefCntPtr<T> &A, | |||
204 | const IntrusiveRefCntPtr<U> &B) { | |||
205 | return A.get() != B.get(); | |||
206 | } | |||
207 | ||||
208 | template <class T, class U> | |||
209 | inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) { | |||
210 | return A.get() == B; | |||
211 | } | |||
212 | ||||
213 | template <class T, class U> | |||
214 | inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) { | |||
215 | return A.get() != B; | |||
216 | } | |||
217 | ||||
218 | template <class T, class U> | |||
219 | inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) { | |||
220 | return A == B.get(); | |||
221 | } | |||
222 | ||||
223 | template <class T, class U> | |||
224 | inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) { | |||
225 | return A != B.get(); | |||
226 | } | |||
227 | ||||
228 | template <class T> | |||
229 | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { | |||
230 | return !B; | |||
231 | } | |||
232 | ||||
233 | template <class T> | |||
234 | bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { | |||
235 | return B == A; | |||
236 | } | |||
237 | ||||
238 | template <class T> | |||
239 | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { | |||
240 | return !(A == B); | |||
241 | } | |||
242 | ||||
243 | template <class T> | |||
244 | bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { | |||
245 | return !(A == B); | |||
246 | } | |||
247 | ||||
248 | // Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from | |||
249 | // Casting.h. | |||
250 | template <typename From> struct simplify_type; | |||
251 | ||||
252 | template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> { | |||
253 | using SimpleType = T *; | |||
254 | ||||
255 | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) { | |||
256 | return Val.get(); | |||
257 | } | |||
258 | }; | |||
259 | ||||
260 | template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> { | |||
261 | using SimpleType = /*const*/ T *; | |||
262 | ||||
263 | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) { | |||
264 | return Val.get(); | |||
265 | } | |||
266 | }; | |||
267 | ||||
268 | } // end namespace llvm | |||
269 | ||||
270 | #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H |