Coverage Report

Created: 2019-07-24 05:18

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