/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Support/FormatProviders.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- FormatProviders.h - Formatters for common LLVM types -----*- 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 implements format providers for many common LLVM types, for example |
11 | | // allowing precision and width specifiers for scalar and string types. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H |
16 | | #define LLVM_SUPPORT_FORMATPROVIDERS_H |
17 | | |
18 | | #include "llvm/ADT/Optional.h" |
19 | | #include "llvm/ADT/STLExtras.h" |
20 | | #include "llvm/ADT/StringSwitch.h" |
21 | | #include "llvm/ADT/Twine.h" |
22 | | #include "llvm/Support/FormatVariadicDetails.h" |
23 | | #include "llvm/Support/NativeFormatting.h" |
24 | | |
25 | | #include <type_traits> |
26 | | #include <vector> |
27 | | |
28 | | namespace llvm { |
29 | | namespace detail { |
30 | | template <typename T> |
31 | | struct use_integral_formatter |
32 | | : public std::integral_constant< |
33 | | bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t, |
34 | | int64_t, uint64_t, int, unsigned, long, unsigned long, |
35 | | long long, unsigned long long>::value> {}; |
36 | | |
37 | | template <typename T> |
38 | | struct use_char_formatter |
39 | | : public std::integral_constant<bool, std::is_same<T, char>::value> {}; |
40 | | |
41 | | template <typename T> |
42 | | struct is_cstring |
43 | | : public std::integral_constant<bool, |
44 | | is_one_of<T, char *, const char *>::value> { |
45 | | }; |
46 | | |
47 | | template <typename T> |
48 | | struct use_string_formatter |
49 | | : public std::integral_constant<bool, |
50 | | std::is_convertible<T, llvm::StringRef>::value> {}; |
51 | | |
52 | | template <typename T> |
53 | | struct use_pointer_formatter |
54 | | : public std::integral_constant<bool, std::is_pointer<T>::value && |
55 | | !is_cstring<T>::value> {}; |
56 | | |
57 | | template <typename T> |
58 | | struct use_double_formatter |
59 | | : public std::integral_constant<bool, std::is_floating_point<T>::value> {}; |
60 | | |
61 | | class HelperFunctions { |
62 | | protected: |
63 | | static Optional<size_t> parseNumericPrecision(StringRef Str) { |
64 | | size_t Prec; |
65 | | Optional<size_t> Result; |
66 | | if (Str.empty()) |
67 | | Result = None; |
68 | | else if (Str.getAsInteger(10, Prec)) { |
69 | | assert(false && "Invalid precision specifier"); |
70 | | Result = None; |
71 | | } else { |
72 | | assert(Prec < 100 && "Precision out of range"); |
73 | | Result = std::min<size_t>(99u, Prec); |
74 | | } |
75 | | return Result; |
76 | | } |
77 | | |
78 | 6.45k | static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) { |
79 | 6.45k | if (!Str.startswith_lower("x")) |
80 | 4.08k | return false; |
81 | 6.45k | |
82 | 2.37k | if (2.37k Str.consume_front("x-")2.37k ) |
83 | 5 | Style = HexPrintStyle::Lower; |
84 | 2.36k | else if (2.36k Str.consume_front("X-")2.36k ) |
85 | 481 | Style = HexPrintStyle::Upper; |
86 | 1.88k | else if (1.88k Str.consume_front("x+") || 1.88k Str.consume_front("x")1.88k ) |
87 | 51 | Style = HexPrintStyle::PrefixLower; |
88 | 1.83k | else if (1.83k Str.consume_front("X+") || 1.83k Str.consume_front("X")405 ) |
89 | 1.83k | Style = HexPrintStyle::PrefixUpper; |
90 | 2.37k | return true; |
91 | 6.45k | } |
92 | | |
93 | | static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style, |
94 | 2.38k | size_t Default) { |
95 | 2.38k | Str.consumeInteger(10, Default); |
96 | 2.38k | if (isPrefixedHexStyle(Style)) |
97 | 1.89k | Default += 2; |
98 | 2.38k | return Default; |
99 | 2.38k | } |
100 | | }; |
101 | | } |
102 | | |
103 | | /// Implementation of format_provider<T> for integral arithmetic types. |
104 | | /// |
105 | | /// The options string of an integral type has the grammar: |
106 | | /// |
107 | | /// integer_options :: [style][digits] |
108 | | /// style :: <see table below> |
109 | | /// digits :: <non-negative integer> 0-99 |
110 | | /// |
111 | | /// ========================================================================== |
112 | | /// | style | Meaning | Example | Digits Meaning | |
113 | | /// -------------------------------------------------------------------------- |
114 | | /// | | | Input | Output | | |
115 | | /// ========================================================================== |
116 | | /// | x- | Hex no prefix, lower | 42 | 2a | Minimum # digits | |
117 | | /// | X- | Hex no prefix, upper | 42 | 2A | Minimum # digits | |
118 | | /// | x+ / x | Hex + prefix, lower | 42 | 0x2a | Minimum # digits | |
119 | | /// | X+ / X | Hex + prefix, upper | 42 | 0x2A | Minimum # digits | |
120 | | /// | N / n | Digit grouped number | 123456 | 123,456 | Ignored | |
121 | | /// | D / d | Integer | 100000 | 100000 | Ignored | |
122 | | /// | (empty) | Same as D / d | | | | |
123 | | /// ========================================================================== |
124 | | /// |
125 | | |
126 | | template <typename T> |
127 | | struct format_provider< |
128 | | T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type> |
129 | | : public detail::HelperFunctions { |
130 | | private: |
131 | | public: |
132 | 4.38k | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
133 | 4.38k | HexPrintStyle HS; |
134 | 4.38k | size_t Digits = 0; |
135 | 4.38k | if (consumeHexStyle(Style, HS)4.38k ) { |
136 | 1.97k | Digits = consumeNumHexDigits(Style, HS, 0); |
137 | 1.97k | write_hex(Stream, V, HS, Digits); |
138 | 1.97k | return; |
139 | 1.97k | } |
140 | 4.38k | |
141 | 2.40k | IntegerStyle IS = IntegerStyle::Integer; |
142 | 2.40k | if (Style.consume_front("N") || 2.40k Style.consume_front("n")2.36k ) |
143 | 43 | IS = IntegerStyle::Number; |
144 | 2.36k | else if (2.36k Style.consume_front("D") || 2.36k Style.consume_front("d")2.36k ) |
145 | 0 | IS = IntegerStyle::Integer; |
146 | 4.38k | |
147 | 4.38k | Style.consumeInteger(10, Digits); |
148 | 4.38k | assert(Style.empty() && "Invalid integral format style!"); |
149 | 4.38k | write_integer(Stream, V, Digits, IS); |
150 | 4.38k | } |
151 | | }; |
152 | | |
153 | | /// Implementation of format_provider<T> for integral pointer types. |
154 | | /// |
155 | | /// The options string of a pointer type has the grammar: |
156 | | /// |
157 | | /// pointer_options :: [style][precision] |
158 | | /// style :: <see table below> |
159 | | /// digits :: <non-negative integer> 0-sizeof(void*) |
160 | | /// |
161 | | /// ========================================================================== |
162 | | /// | S | Meaning | Example | |
163 | | /// -------------------------------------------------------------------------- |
164 | | /// | | | Input | Output | |
165 | | /// ========================================================================== |
166 | | /// | x- | Hex no prefix, lower | 0xDEADBEEF | deadbeef | |
167 | | /// | X- | Hex no prefix, upper | 0xDEADBEEF | DEADBEEF | |
168 | | /// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef | |
169 | | /// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF | |
170 | | /// | (empty) | Same as X+ / X | | | |
171 | | /// ========================================================================== |
172 | | /// |
173 | | /// The default precision is the number of nibbles in a machine word, and in all |
174 | | /// cases indicates the minimum number of nibbles to print. |
175 | | template <typename T> |
176 | | struct format_provider< |
177 | | T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type> |
178 | | : public detail::HelperFunctions { |
179 | | private: |
180 | | public: |
181 | | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
182 | | HexPrintStyle HS = HexPrintStyle::PrefixUpper; |
183 | | consumeHexStyle(Style, HS); |
184 | | size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2); |
185 | | write_hex(Stream, reinterpret_cast<std::uintptr_t>(V), HS, Digits); |
186 | | } |
187 | | }; |
188 | | |
189 | | /// Implementation of format_provider<T> for c-style strings and string |
190 | | /// objects such as std::string and llvm::StringRef. |
191 | | /// |
192 | | /// The options string of a string type has the grammar: |
193 | | /// |
194 | | /// string_options :: [length] |
195 | | /// |
196 | | /// where `length` is an optional integer specifying the maximum number of |
197 | | /// characters in the string to print. If `length` is omitted, the string is |
198 | | /// printed up to the null terminator. |
199 | | |
200 | | template <typename T> |
201 | | struct format_provider< |
202 | | T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> { |
203 | 3.89k | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
204 | 3.89k | size_t N = StringRef::npos; |
205 | 3.89k | if (!Style.empty() && 3.89k Style.getAsInteger(10, N)4 ) { |
206 | 0 | assert(false && "Style is not a valid integer"); |
207 | 0 | } |
208 | 3.89k | llvm::StringRef S = V; |
209 | 3.89k | Stream << S.substr(0, N); |
210 | 3.89k | } |
211 | | }; |
212 | | |
213 | | /// Implementation of format_provider<T> for llvm::Twine. |
214 | | /// |
215 | | /// This follows the same rules as the string formatter. |
216 | | |
217 | | template <> struct format_provider<Twine> { |
218 | | static void format(const Twine &V, llvm::raw_ostream &Stream, |
219 | 0 | StringRef Style) { |
220 | 0 | format_provider<std::string>::format(V.str(), Stream, Style); |
221 | 0 | } |
222 | | }; |
223 | | |
224 | | /// Implementation of format_provider<T> for characters. |
225 | | /// |
226 | | /// The options string of a character type has the grammar: |
227 | | /// |
228 | | /// char_options :: (empty) | [integer_options] |
229 | | /// |
230 | | /// If `char_options` is empty, the character is displayed as an ASCII |
231 | | /// character. Otherwise, it is treated as an integer options string. |
232 | | /// |
233 | | template <typename T> |
234 | | struct format_provider< |
235 | | T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> { |
236 | | static void format(const char &V, llvm::raw_ostream &Stream, |
237 | | StringRef Style) { |
238 | | if (Style.empty()) |
239 | | Stream << V; |
240 | | else { |
241 | | int X = static_cast<int>(V); |
242 | | format_provider<int>::format(X, Stream, Style); |
243 | | } |
244 | | } |
245 | | }; |
246 | | |
247 | | /// Implementation of format_provider<T> for type `bool` |
248 | | /// |
249 | | /// The options string of a boolean type has the grammar: |
250 | | /// |
251 | | /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t" |
252 | | /// |
253 | | /// ================================== |
254 | | /// | C | Meaning | |
255 | | /// ================================== |
256 | | /// | Y | YES / NO | |
257 | | /// | y | yes / no | |
258 | | /// | D / d | Integer 0 or 1 | |
259 | | /// | T | TRUE / FALSE | |
260 | | /// | t | true / false | |
261 | | /// | (empty) | Equivalent to 't' | |
262 | | /// ================================== |
263 | | template <> struct format_provider<bool> { |
264 | | static void format(const bool &B, llvm::raw_ostream &Stream, |
265 | | StringRef Style) { |
266 | | Stream << StringSwitch<const char *>(Style) |
267 | | .Case("Y", B ? "YES" : "NO") |
268 | | .Case("y", B ? "yes" : "no") |
269 | | .CaseLower("D", B ? "1" : "0") |
270 | | .Case("T", B ? "TRUE" : "FALSE") |
271 | | .Cases("t", "", B ? "true" : "false") |
272 | | .Default(B ? "1" : "0"); |
273 | | } |
274 | | }; |
275 | | |
276 | | /// Implementation of format_provider<T> for floating point types. |
277 | | /// |
278 | | /// The options string of a floating point type has the format: |
279 | | /// |
280 | | /// float_options :: [style][precision] |
281 | | /// style :: <see table below> |
282 | | /// precision :: <non-negative integer> 0-99 |
283 | | /// |
284 | | /// ===================================================== |
285 | | /// | style | Meaning | Example | |
286 | | /// ----------------------------------------------------- |
287 | | /// | | | Input | Output | |
288 | | /// ===================================================== |
289 | | /// | P / p | Percentage | 0.05 | 5.00% | |
290 | | /// | F / f | Fixed point | 1.0 | 1.00 | |
291 | | /// | E | Exponential with E | 100000 | 1.0E+05 | |
292 | | /// | e | Exponential with e | 100000 | 1.0e+05 | |
293 | | /// | (empty) | Same as F / f | | | |
294 | | /// ===================================================== |
295 | | /// |
296 | | /// The default precision is 6 for exponential (E / e) and 2 for everything |
297 | | /// else. |
298 | | |
299 | | template <typename T> |
300 | | struct format_provider< |
301 | | T, typename std::enable_if<detail::use_double_formatter<T>::value>::type> |
302 | | : public detail::HelperFunctions { |
303 | | static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { |
304 | | FloatStyle S; |
305 | | if (Style.consume_front("P") || Style.consume_front("p")) |
306 | | S = FloatStyle::Percent; |
307 | | else if (Style.consume_front("F") || Style.consume_front("f")) |
308 | | S = FloatStyle::Fixed; |
309 | | else if (Style.consume_front("E")) |
310 | | S = FloatStyle::ExponentUpper; |
311 | | else if (Style.consume_front("e")) |
312 | | S = FloatStyle::Exponent; |
313 | | else |
314 | | S = FloatStyle::Fixed; |
315 | | |
316 | | Optional<size_t> Precision = parseNumericPrecision(Style); |
317 | | if (!Precision.hasValue()) |
318 | | Precision = getDefaultPrecision(S); |
319 | | |
320 | | write_double(Stream, static_cast<double>(V), S, Precision); |
321 | | } |
322 | | }; |
323 | | |
324 | | namespace detail { |
325 | | template <typename IterT> |
326 | | using IterValue = typename std::iterator_traits<IterT>::value_type; |
327 | | |
328 | | template <typename IterT> |
329 | | struct range_item_has_provider |
330 | | : public std::integral_constant< |
331 | | bool, !uses_missing_provider<IterValue<IterT>>::value> {}; |
332 | | } |
333 | | |
334 | | /// Implementation of format_provider<T> for ranges. |
335 | | /// |
336 | | /// This will print an arbitrary range as a delimited sequence of items. |
337 | | /// |
338 | | /// The options string of a range type has the grammar: |
339 | | /// |
340 | | /// range_style ::= [separator] [element_style] |
341 | | /// separator ::= "$" delimeted_expr |
342 | | /// element_style ::= "@" delimeted_expr |
343 | | /// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">" |
344 | | /// expr ::= <any string not containing delimeter> |
345 | | /// |
346 | | /// where the separator expression is the string to insert between consecutive |
347 | | /// items in the range and the argument expression is the Style specification to |
348 | | /// be used when formatting the underlying type. The default separator if |
349 | | /// unspecified is ' ' (space). The syntax of the argument expression follows |
350 | | /// whatever grammar is dictated by the format provider or format adapter used |
351 | | /// to format the value type. |
352 | | /// |
353 | | /// Note that attempting to format an `iterator_range<T>` where no format |
354 | | /// provider can be found for T will result in a compile error. |
355 | | /// |
356 | | |
357 | | template <typename IterT> class format_provider<llvm::iterator_range<IterT>> { |
358 | | using value = typename std::iterator_traits<IterT>::value_type; |
359 | | using reference = typename std::iterator_traits<IterT>::reference; |
360 | | |
361 | | static StringRef consumeOneOption(StringRef &Style, char Indicator, |
362 | | StringRef Default) { |
363 | | if (Style.empty()) |
364 | | return Default; |
365 | | if (Style.front() != Indicator) |
366 | | return Default; |
367 | | Style = Style.drop_front(); |
368 | | if (Style.empty()) { |
369 | | assert(false && "Invalid range style"); |
370 | | return Default; |
371 | | } |
372 | | |
373 | | for (const char *D : {"[]", "<>", "()"}) { |
374 | | if (Style.front() != D[0]) |
375 | | continue; |
376 | | size_t End = Style.find_first_of(D[1]); |
377 | | if (End == StringRef::npos) { |
378 | | assert(false && "Missing range option end delimeter!"); |
379 | | return Default; |
380 | | } |
381 | | StringRef Result = Style.slice(1, End); |
382 | | Style = Style.drop_front(End + 1); |
383 | | return Result; |
384 | | } |
385 | | assert(false && "Invalid range style!"); |
386 | | return Default; |
387 | | } |
388 | | |
389 | | static std::pair<StringRef, StringRef> parseOptions(StringRef Style) { |
390 | | StringRef Sep = consumeOneOption(Style, '$', ", "); |
391 | | StringRef Args = consumeOneOption(Style, '@', ""); |
392 | | assert(Style.empty() && "Unexpected text in range option string!"); |
393 | | return std::make_pair(Sep, Args); |
394 | | } |
395 | | |
396 | | public: |
397 | | static_assert(detail::range_item_has_provider<IterT>::value, |
398 | | "Range value_type does not have a format provider!"); |
399 | | static void format(const llvm::iterator_range<IterT> &V, |
400 | | llvm::raw_ostream &Stream, StringRef Style) { |
401 | | StringRef Sep; |
402 | | StringRef ArgStyle; |
403 | | std::tie(Sep, ArgStyle) = parseOptions(Style); |
404 | | auto Begin = V.begin(); |
405 | | auto End = V.end(); |
406 | | if (Begin != End) { |
407 | | auto Adapter = |
408 | | detail::build_format_adapter(std::forward<reference>(*Begin)); |
409 | | Adapter.format(Stream, ArgStyle); |
410 | | ++Begin; |
411 | | } |
412 | | while (Begin != End) { |
413 | | Stream << Sep; |
414 | | auto Adapter = |
415 | | detail::build_format_adapter(std::forward<reference>(*Begin)); |
416 | | Adapter.format(Stream, ArgStyle); |
417 | | ++Begin; |
418 | | } |
419 | | } |
420 | | }; |
421 | | } |
422 | | |
423 | | #endif |