/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Demangle/Utility.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Utility.h ----------------------------------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Provide some utility classes for use in the demangler(s). |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef DEMANGLE_UTILITY_H |
14 | | #define DEMANGLE_UTILITY_H |
15 | | |
16 | | #include "StringView.h" |
17 | | #include <cstdint> |
18 | | #include <cstdlib> |
19 | | #include <cstring> |
20 | | #include <iterator> |
21 | | #include <limits> |
22 | | |
23 | | DEMANGLE_NAMESPACE_BEGIN |
24 | | |
25 | | // Stream that AST nodes write their string representation into after the AST |
26 | | // has been parsed. |
27 | | class OutputStream { |
28 | | char *Buffer; |
29 | | size_t CurrentPosition; |
30 | | size_t BufferCapacity; |
31 | | |
32 | | // Ensure there is at least n more positions in buffer. |
33 | 41.9k | void grow(size_t N) { |
34 | 41.9k | if (N + CurrentPosition >= BufferCapacity) { |
35 | 94 | BufferCapacity *= 2; |
36 | 94 | if (BufferCapacity < N + CurrentPosition) |
37 | 6 | BufferCapacity = N + CurrentPosition; |
38 | 94 | Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); |
39 | 94 | if (Buffer == nullptr) |
40 | 0 | std::terminate(); |
41 | 94 | } |
42 | 41.9k | } |
43 | | |
44 | 349 | void writeUnsigned(uint64_t N, bool isNeg = false) { |
45 | 349 | // Handle special case... |
46 | 349 | if (N == 0) { |
47 | 86 | *this << '0'; |
48 | 86 | return; |
49 | 86 | } |
50 | 263 | |
51 | 263 | char Temp[21]; |
52 | 263 | char *TempPtr = std::end(Temp); |
53 | 263 | |
54 | 914 | while (N) { |
55 | 651 | *--TempPtr = '0' + char(N % 10); |
56 | 651 | N /= 10; |
57 | 651 | } |
58 | 263 | |
59 | 263 | // Add negative sign... |
60 | 263 | if (isNeg) |
61 | 10 | *--TempPtr = '-'; |
62 | 263 | this->operator<<(StringView(TempPtr, std::end(Temp))); |
63 | 263 | } |
64 | | |
65 | | public: |
66 | | OutputStream(char *StartBuf, size_t Size) |
67 | 0 | : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} |
68 | 4.09k | OutputStream() = default; |
69 | 3.96k | void reset(char *Buffer_, size_t BufferCapacity_) { |
70 | 3.96k | CurrentPosition = 0; |
71 | 3.96k | Buffer = Buffer_; |
72 | 3.96k | BufferCapacity = BufferCapacity_; |
73 | 3.96k | } |
74 | | |
75 | | /// If a ParameterPackExpansion (or similar type) is encountered, the offset |
76 | | /// into the pack that we're currently printing. |
77 | | unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); |
78 | | unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); |
79 | | |
80 | 37.2k | OutputStream &operator+=(StringView R) { |
81 | 37.2k | size_t Size = R.size(); |
82 | 37.2k | if (Size == 0) |
83 | 3 | return *this; |
84 | 37.2k | grow(Size); |
85 | 37.2k | std::memmove(Buffer + CurrentPosition, R.begin(), Size); |
86 | 37.2k | CurrentPosition += Size; |
87 | 37.2k | return *this; |
88 | 37.2k | } |
89 | | |
90 | 4.70k | OutputStream &operator+=(char C) { |
91 | 4.70k | grow(1); |
92 | 4.70k | Buffer[CurrentPosition++] = C; |
93 | 4.70k | return *this; |
94 | 4.70k | } |
95 | | |
96 | 17.5k | OutputStream &operator<<(StringView R) { return (*this += R); } |
97 | | |
98 | 1.39k | OutputStream &operator<<(char C) { return (*this += C); } |
99 | | |
100 | 64 | OutputStream &operator<<(long long N) { |
101 | 64 | if (N < 0) |
102 | 10 | writeUnsigned(static_cast<unsigned long long>(-N), true); |
103 | 54 | else |
104 | 54 | writeUnsigned(static_cast<unsigned long long>(N)); |
105 | 64 | return *this; |
106 | 64 | } |
107 | | |
108 | 285 | OutputStream &operator<<(unsigned long long N) { |
109 | 285 | writeUnsigned(N, false); |
110 | 285 | return *this; |
111 | 285 | } |
112 | | |
113 | 0 | OutputStream &operator<<(long N) { |
114 | 0 | return this->operator<<(static_cast<long long>(N)); |
115 | 0 | } |
116 | | |
117 | 0 | OutputStream &operator<<(unsigned long N) { |
118 | 0 | return this->operator<<(static_cast<unsigned long long>(N)); |
119 | 0 | } |
120 | | |
121 | 5 | OutputStream &operator<<(int N) { |
122 | 5 | return this->operator<<(static_cast<long long>(N)); |
123 | 5 | } |
124 | | |
125 | 9 | OutputStream &operator<<(unsigned int N) { |
126 | 9 | return this->operator<<(static_cast<unsigned long long>(N)); |
127 | 9 | } |
128 | | |
129 | 11.5k | size_t getCurrentPosition() const { return CurrentPosition; } |
130 | 0 | void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } |
131 | | |
132 | 2.35k | char back() const { |
133 | 2.35k | return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'0 ; |
134 | 2.35k | } |
135 | | |
136 | 2.32k | bool empty() const { return CurrentPosition == 0; } |
137 | | |
138 | 3.96k | char *getBuffer() { return Buffer; } |
139 | 0 | char *getBufferEnd() { return Buffer + CurrentPosition - 1; } |
140 | 0 | size_t getBufferCapacity() { return BufferCapacity; } |
141 | | }; |
142 | | |
143 | | template <class T> class SwapAndRestore { |
144 | | T &Restore; |
145 | | T OriginalValue; |
146 | | bool ShouldRestore = true; |
147 | | |
148 | | public: |
149 | | SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {} |
150 | | |
151 | | SwapAndRestore(T &Restore_, T NewVal) |
152 | 38 | : Restore(Restore_), OriginalValue(Restore) { |
153 | 38 | Restore = std::move(NewVal); |
154 | 38 | } llvm::itanium_demangle::SwapAndRestore<unsigned int>::SwapAndRestore(unsigned int&, unsigned int) Line | Count | Source | 152 | 4 | : Restore(Restore_), OriginalValue(Restore) { | 153 | 4 | Restore = std::move(NewVal); | 154 | 4 | } |
llvm::itanium_demangle::SwapAndRestore<bool>::SwapAndRestore(bool&, bool) Line | Count | Source | 152 | 34 | : Restore(Restore_), OriginalValue(Restore) { | 153 | 34 | Restore = std::move(NewVal); | 154 | 34 | } |
Unexecuted instantiation: llvm::itanium_demangle::SwapAndRestore<char const*>::SwapAndRestore(char const*&, char const*) |
155 | 38 | ~SwapAndRestore() { |
156 | 38 | if (ShouldRestore) |
157 | 38 | Restore = std::move(OriginalValue); |
158 | 38 | } llvm::itanium_demangle::SwapAndRestore<unsigned int>::~SwapAndRestore() Line | Count | Source | 155 | 4 | ~SwapAndRestore() { | 156 | 4 | if (ShouldRestore) | 157 | 4 | Restore = std::move(OriginalValue); | 158 | 4 | } |
llvm::itanium_demangle::SwapAndRestore<bool>::~SwapAndRestore() Line | Count | Source | 155 | 34 | ~SwapAndRestore() { | 156 | 34 | if (ShouldRestore) | 157 | 34 | Restore = std::move(OriginalValue); | 158 | 34 | } |
Unexecuted instantiation: llvm::itanium_demangle::SwapAndRestore<char const*>::~SwapAndRestore() |
159 | | |
160 | | void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; } |
161 | | |
162 | | void restoreNow(bool Force) { |
163 | | if (!Force && !ShouldRestore) |
164 | | return; |
165 | | |
166 | | Restore = std::move(OriginalValue); |
167 | | ShouldRestore = false; |
168 | | } |
169 | | |
170 | | SwapAndRestore(const SwapAndRestore &) = delete; |
171 | | SwapAndRestore &operator=(const SwapAndRestore &) = delete; |
172 | | }; |
173 | | |
174 | | inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, |
175 | 3.96k | size_t InitSize) { |
176 | 3.96k | size_t BufferSize; |
177 | 3.96k | if (Buf == nullptr) { |
178 | 3.88k | Buf = static_cast<char *>(std::malloc(InitSize)); |
179 | 3.88k | if (Buf == nullptr) |
180 | 0 | return false; |
181 | 3.88k | BufferSize = InitSize; |
182 | 3.88k | } else |
183 | 82 | BufferSize = *N; |
184 | 3.96k | |
185 | 3.96k | S.reset(Buf, BufferSize); |
186 | 3.96k | return true; |
187 | 3.96k | } |
188 | | |
189 | | DEMANGLE_NAMESPACE_END |
190 | | |
191 | | #endif |