/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Demangle/Utility.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Utility.h ----------------------------------------------*- 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 | | // This file contains several utility classes used by the demangle library. |
10 | | //===----------------------------------------------------------------------===// |
11 | | |
12 | | #ifndef LLVM_DEMANGLE_UTILITY_H |
13 | | #define LLVM_DEMANGLE_UTILITY_H |
14 | | |
15 | | #include "StringView.h" |
16 | | |
17 | | #include <cstdint> |
18 | | #include <cstdlib> |
19 | | #include <cstring> |
20 | | #include <iterator> |
21 | | #include <limits> |
22 | | |
23 | | // Stream that AST nodes write their string representation into after the AST |
24 | | // has been parsed. |
25 | | class OutputStream { |
26 | | char *Buffer; |
27 | | size_t CurrentPosition; |
28 | | size_t BufferCapacity; |
29 | | |
30 | | // Ensure there is at least n more positions in buffer. |
31 | 17.0k | void grow(size_t N) { |
32 | 17.0k | if (N + CurrentPosition >= BufferCapacity) { |
33 | 93 | BufferCapacity *= 2; |
34 | 93 | if (BufferCapacity < N + CurrentPosition) |
35 | 6 | BufferCapacity = N + CurrentPosition; |
36 | 93 | Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); |
37 | 93 | if (Buffer == nullptr) |
38 | 0 | std::terminate(); |
39 | 93 | } |
40 | 17.0k | } |
41 | | |
42 | | void writeUnsigned(uint64_t N, bool isNeg = false) { |
43 | | // Handle special case... |
44 | | if (N == 0) { |
45 | | *this << '0'; |
46 | | return; |
47 | | } |
48 | | |
49 | | char Temp[21]; |
50 | | char *TempPtr = std::end(Temp); |
51 | | |
52 | | while (N) { |
53 | | *--TempPtr = '0' + char(N % 10); |
54 | | N /= 10; |
55 | | } |
56 | | |
57 | | // Add negative sign... |
58 | | if (isNeg) |
59 | | *--TempPtr = '-'; |
60 | | this->operator<<(StringView(TempPtr, std::end(Temp))); |
61 | | } |
62 | | |
63 | | public: |
64 | | OutputStream(char *StartBuf, size_t Size) |
65 | 0 | : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} |
66 | 2.23k | OutputStream() = default; |
67 | 1.85k | void reset(char *Buffer_, size_t BufferCapacity_) { |
68 | 1.85k | CurrentPosition = 0; |
69 | 1.85k | Buffer = Buffer_; |
70 | 1.85k | BufferCapacity = BufferCapacity_; |
71 | 1.85k | } |
72 | | |
73 | | /// Create an OutputStream from a buffer and a size. If either of these are |
74 | | /// null a buffer is allocated. |
75 | | static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) { |
76 | | OutputStream Result; |
77 | | |
78 | | if (!StartBuf || !Size) { |
79 | | StartBuf = static_cast<char *>(std::malloc(AllocSize)); |
80 | | if (StartBuf == nullptr) |
81 | | std::terminate(); |
82 | | Size = &AllocSize; |
83 | | } |
84 | | |
85 | | Result.reset(StartBuf, *Size); |
86 | | return Result; |
87 | | } |
88 | | |
89 | | /// If a ParameterPackExpansion (or similar type) is encountered, the offset |
90 | | /// into the pack that we're currently printing. |
91 | | unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); |
92 | | unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); |
93 | | |
94 | 14.5k | OutputStream &operator+=(StringView R) { |
95 | 14.5k | size_t Size = R.size(); |
96 | 14.5k | if (Size == 0) |
97 | 3 | return *this; |
98 | 14.5k | grow(Size); |
99 | 14.5k | std::memmove(Buffer + CurrentPosition, R.begin(), Size); |
100 | 14.5k | CurrentPosition += Size; |
101 | 14.5k | return *this; |
102 | 14.5k | } |
103 | | |
104 | 2.44k | OutputStream &operator+=(char C) { |
105 | 2.44k | grow(1); |
106 | 2.44k | Buffer[CurrentPosition++] = C; |
107 | 2.44k | return *this; |
108 | 2.44k | } |
109 | | |
110 | | OutputStream &operator<<(StringView R) { return (*this += R); } |
111 | | |
112 | | OutputStream &operator<<(char C) { return (*this += C); } |
113 | | |
114 | | OutputStream &operator<<(long long N) { |
115 | | if (N < 0) |
116 | | writeUnsigned(static_cast<unsigned long long>(-N), true); |
117 | | else |
118 | | writeUnsigned(static_cast<unsigned long long>(N)); |
119 | | return *this; |
120 | | } |
121 | | |
122 | | OutputStream &operator<<(unsigned long long N) { |
123 | | writeUnsigned(N, false); |
124 | | return *this; |
125 | | } |
126 | | |
127 | 0 | OutputStream &operator<<(long N) { |
128 | 0 | return this->operator<<(static_cast<long long>(N)); |
129 | 0 | } |
130 | | |
131 | 0 | OutputStream &operator<<(unsigned long N) { |
132 | 0 | return this->operator<<(static_cast<unsigned long long>(N)); |
133 | 0 | } |
134 | | |
135 | | OutputStream &operator<<(int N) { |
136 | | return this->operator<<(static_cast<long long>(N)); |
137 | | } |
138 | | |
139 | | OutputStream &operator<<(unsigned int N) { |
140 | | return this->operator<<(static_cast<unsigned long long>(N)); |
141 | | } |
142 | | |
143 | 418 | size_t getCurrentPosition() const { return CurrentPosition; } |
144 | 0 | void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } |
145 | | |
146 | 2.79k | char back() const { |
147 | 2.79k | return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'0 ; |
148 | 2.79k | } |
149 | | |
150 | | bool empty() const { return CurrentPosition == 0; } |
151 | | |
152 | 1.85k | char *getBuffer() { return Buffer; } |
153 | 0 | char *getBufferEnd() { return Buffer + CurrentPosition - 1; } |
154 | 0 | size_t getBufferCapacity() { return BufferCapacity; } |
155 | | }; |
156 | | |
157 | | template <class T> class SwapAndRestore { |
158 | | T &Restore; |
159 | | T OriginalValue; |
160 | | bool ShouldRestore = true; |
161 | | |
162 | | public: |
163 | | SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {} |
164 | | |
165 | | SwapAndRestore(T &Restore_, T NewVal) |
166 | 22 | : Restore(Restore_), OriginalValue(Restore) { |
167 | 22 | Restore = std::move(NewVal); |
168 | 22 | } SwapAndRestore<bool>::SwapAndRestore(bool&, bool) Line | Count | Source | 166 | 18 | : Restore(Restore_), OriginalValue(Restore) { | 167 | 18 | Restore = std::move(NewVal); | 168 | 18 | } |
SwapAndRestore<unsigned int>::SwapAndRestore(unsigned int&, unsigned int) Line | Count | Source | 166 | 4 | : Restore(Restore_), OriginalValue(Restore) { | 167 | 4 | Restore = std::move(NewVal); | 168 | 4 | } |
Unexecuted instantiation: SwapAndRestore<char const*>::SwapAndRestore(char const*&, char const*) |
169 | 22 | ~SwapAndRestore() { |
170 | 22 | if (ShouldRestore) |
171 | 22 | Restore = std::move(OriginalValue); |
172 | 22 | } SwapAndRestore<bool>::~SwapAndRestore() Line | Count | Source | 169 | 18 | ~SwapAndRestore() { | 170 | 18 | if (ShouldRestore) | 171 | 18 | Restore = std::move(OriginalValue); | 172 | 18 | } |
SwapAndRestore<unsigned int>::~SwapAndRestore() Line | Count | Source | 169 | 4 | ~SwapAndRestore() { | 170 | 4 | if (ShouldRestore) | 171 | 4 | Restore = std::move(OriginalValue); | 172 | 4 | } |
Unexecuted instantiation: SwapAndRestore<char const*>::~SwapAndRestore() |
173 | | |
174 | | void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; } |
175 | | |
176 | | void restoreNow(bool Force) { |
177 | | if (!Force && !ShouldRestore) |
178 | | return; |
179 | | |
180 | | Restore = std::move(OriginalValue); |
181 | | ShouldRestore = false; |
182 | | } |
183 | | |
184 | | SwapAndRestore(const SwapAndRestore &) = delete; |
185 | | SwapAndRestore &operator=(const SwapAndRestore &) = delete; |
186 | | }; |
187 | | |
188 | | #endif |