Coverage Report

Created: 2017-10-03 07:32

/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