Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Support/FormatVariadic.h
Line
Count
Source (jump to first uncovered line)
1
//===- FormatVariadic.h - Efficient type-safe string formatting --*- 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 the formatv() function which can be used with other LLVM
11
// subsystems to provide printf-like formatting, but with improved safety and
12
// flexibility.  The result of `formatv` is an object which can be streamed to
13
// a raw_ostream or converted to a std::string or llvm::SmallString.
14
//
15
//   // Convert to std::string.
16
//   std::string S = formatv("{0} {1}", 1234.412, "test").str();
17
//
18
//   // Convert to llvm::SmallString
19
//   SmallString<8> S = formatv("{0} {1}", 1234.412, "test").sstr<8>();
20
//
21
//   // Stream to an existing raw_ostream.
22
//   OS << formatv("{0} {1}", 1234.412, "test");
23
//
24
//===----------------------------------------------------------------------===//
25
26
#ifndef LLVM_SUPPORT_FORMATVARIADIC_H
27
#define LLVM_SUPPORT_FORMATVARIADIC_H
28
29
#include "llvm/ADT/Optional.h"
30
#include "llvm/ADT/STLExtras.h"
31
#include "llvm/ADT/SmallString.h"
32
#include "llvm/ADT/StringRef.h"
33
#include "llvm/Support/FormatCommon.h"
34
#include "llvm/Support/FormatProviders.h"
35
#include "llvm/Support/FormatVariadicDetails.h"
36
#include "llvm/Support/raw_ostream.h"
37
#include <cstddef>
38
#include <string>
39
#include <tuple>
40
#include <utility>
41
#include <vector>
42
43
namespace llvm {
44
45
enum class ReplacementType { Empty, Format, Literal };
46
47
struct ReplacementItem {
48
8.46k
  ReplacementItem() = default;
49
  explicit ReplacementItem(StringRef Literal)
50
14.7k
      : Type(ReplacementType::Literal), Spec(Literal) {}
51
  ReplacementItem(StringRef Spec, size_t Index, size_t Align, AlignStyle Where,
52
                  char Pad, StringRef Options)
53
      : Type(ReplacementType::Format), Spec(Spec), Index(Index), Align(Align),
54
16.4k
        Where(Where), Pad(Pad), Options(Options) {}
55
56
  ReplacementType Type = ReplacementType::Empty;
57
  StringRef Spec;
58
  size_t Index = 0;
59
  size_t Align = 0;
60
  AlignStyle Where = AlignStyle::Right;
61
  char Pad;
62
  StringRef Options;
63
};
64
65
class formatv_object_base {
66
protected:
67
  // The parameters are stored in a std::tuple, which does not provide runtime
68
  // indexing capabilities.  In order to enable runtime indexing, we use this
69
  // structure to put the parameters into a std::vector.  Since the parameters
70
  // are not all the same type, we use some type-erasure by wrapping the
71
  // parameters in a template class that derives from a non-template superclass.
72
  // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
73
  // std::vector<Base*>.
74
  struct create_adapters {
75
    template <typename... Ts>
76
2.33k
    std::vector<detail::format_adapter *> operator()(Ts &... Items) {
77
2.33k
      return std::vector<detail::format_adapter *>{&Items...};
78
2.33k
    }
std::__1::vector<llvm::detail::format_adapter*, std::__1::allocator<llvm::detail::format_adapter*> > llvm::formatv_object_base::create_adapters::operator()<llvm::detail::provider_format_adapter<llvm::codeview::GUID const&> >(llvm::detail::provider_format_adapter<llvm::codeview::GUID const&>&)
Line
Count
Source
76
2
    std::vector<detail::format_adapter *> operator()(Ts &... Items) {
77
2
      return std::vector<detail::format_adapter *>{&Items...};
78
2
    }
std::__1::vector<llvm::detail::format_adapter*, std::__1::allocator<llvm::detail::format_adapter*> > llvm::formatv_object_base::create_adapters::operator()<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> >(llvm::detail::provider_format_adapter<llvm::StringRef&>&, llvm::detail::provider_format_adapter<llvm::StringRef&>&, llvm::detail::provider_format_adapter<llvm::StringRef&>&)
Line
Count
Source
76
178
    std::vector<detail::format_adapter *> operator()(Ts &... Items) {
77
178
      return std::vector<detail::format_adapter *>{&Items...};
78
178
    }
std::__1::vector<llvm::detail::format_adapter*, std::__1::allocator<llvm::detail::format_adapter*> > llvm::formatv_object_base::create_adapters::operator()<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> >(llvm::detail::provider_format_adapter<llvm::StringRef&>&, llvm::detail::provider_format_adapter<llvm::StringRef&>&)
Line
Count
Source
76
168
    std::vector<detail::format_adapter *> operator()(Ts &... Items) {
77
168
      return std::vector<detail::format_adapter *>{&Items...};
78
168
    }
std::__1::vector<llvm::detail::format_adapter*, std::__1::allocator<llvm::detail::format_adapter*> > llvm::formatv_object_base::create_adapters::operator()<llvm::detail::provider_format_adapter<unsigned int> >(llvm::detail::provider_format_adapter<unsigned int>&)
Line
Count
Source
76
1.98k
    std::vector<detail::format_adapter *> operator()(Ts &... Items) {
77
1.98k
      return std::vector<detail::format_adapter *>{&Items...};
78
1.98k
    }
79
  };
80
81
  StringRef Fmt;
82
  std::vector<detail::format_adapter *> Adapters;
83
  std::vector<ReplacementItem> Replacements;
84
85
  static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
86
                                 size_t &Align, char &Pad);
87
88
  static std::pair<ReplacementItem, StringRef>
89
  splitLiteralAndReplacement(StringRef Fmt);
90
91
public:
92
  formatv_object_base(StringRef Fmt, std::size_t ParamCount)
93
8.44k
      : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
94
8.44k
    Adapters.reserve(ParamCount);
95
8.44k
  }
96
97
  formatv_object_base(formatv_object_base const &rhs) = delete;
98
99
  formatv_object_base(formatv_object_base &&rhs)
100
      : Fmt(std::move(rhs.Fmt)),
101
        Adapters(), // Adapters are initialized by formatv_object
102
0
        Replacements(std::move(rhs.Replacements)) {
103
0
    Adapters.reserve(rhs.Adapters.size());
104
0
  };
105
106
8.44k
  void format(raw_ostream &S) const {
107
31.1k
    for (auto &R : Replacements) {
108
31.1k
      if (R.Type == ReplacementType::Empty)
109
0
        continue;
110
31.1k
      
if (31.1k
R.Type == ReplacementType::Literal31.1k
) {
111
14.6k
        S << R.Spec;
112
14.6k
        continue;
113
14.6k
      }
114
16.4k
      
if (16.4k
R.Index >= Adapters.size()16.4k
) {
115
3
        S << R.Spec;
116
3
        continue;
117
3
      }
118
16.4k
119
16.4k
      auto W = Adapters[R.Index];
120
16.4k
121
16.4k
      FmtAlign Align(*W, R.Where, R.Align);
122
16.4k
      Align.format(S, R.Options);
123
16.4k
    }
124
8.44k
  }
125
  static std::vector<ReplacementItem> parseFormatString(StringRef Fmt);
126
127
  static Optional<ReplacementItem> parseReplacementItem(StringRef Spec);
128
129
1.64k
  std::string str() const {
130
1.64k
    std::string Result;
131
1.64k
    raw_string_ostream Stream(Result);
132
1.64k
    Stream << *this;
133
1.64k
    Stream.flush();
134
1.64k
    return Result;
135
1.64k
  }
136
137
359
  template <unsigned N> SmallString<N> sstr() const {
138
359
    SmallString<N> Result;
139
359
    raw_svector_ostream Stream(Result);
140
359
    Stream << *this;
141
359
    return Result;
142
359
  }
143
144
27
  template <unsigned N> operator SmallString<N>() const { return sstr<N>(); }
145
146
0
  operator std::string() const { return str(); }
147
};
148
149
template <typename Tuple> class formatv_object : public formatv_object_base {
150
  // Storage for the parameter adapters.  Since the base class erases the type
151
  // of the parameters, we have to own the storage for the parameters here, and
152
  // have the base class store type-erased pointers into this tuple.
153
  Tuple Parameters;
154
155
public:
156
  formatv_object(StringRef Fmt, Tuple &&Params)
157
      : formatv_object_base(Fmt, std::tuple_size<Tuple>::value),
158
2.33k
        Parameters(std::move(Params)) {
159
2.33k
    Adapters = apply_tuple(create_adapters(), Parameters);
160
2.33k
  }
llvm::formatv_object<std::__1::tuple<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> > >::formatv_object(llvm::StringRef, std::__1::tuple<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> >&&)
Line
Count
Source
158
168
        Parameters(std::move(Params)) {
159
168
    Adapters = apply_tuple(create_adapters(), Parameters);
160
168
  }
llvm::formatv_object<std::__1::tuple<llvm::detail::provider_format_adapter<llvm::codeview::GUID const&> > >::formatv_object(llvm::StringRef, std::__1::tuple<llvm::detail::provider_format_adapter<llvm::codeview::GUID const&> >&&)
Line
Count
Source
158
2
        Parameters(std::move(Params)) {
159
2
    Adapters = apply_tuple(create_adapters(), Parameters);
160
2
  }
llvm::formatv_object<std::__1::tuple<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> > >::formatv_object(llvm::StringRef, std::__1::tuple<llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&>, llvm::detail::provider_format_adapter<llvm::StringRef&> >&&)
Line
Count
Source
158
178
        Parameters(std::move(Params)) {
159
178
    Adapters = apply_tuple(create_adapters(), Parameters);
160
178
  }
llvm::formatv_object<std::__1::tuple<llvm::detail::provider_format_adapter<unsigned int> > >::formatv_object(llvm::StringRef, std::__1::tuple<llvm::detail::provider_format_adapter<unsigned int> >&&)
Line
Count
Source
158
1.98k
        Parameters(std::move(Params)) {
159
1.98k
    Adapters = apply_tuple(create_adapters(), Parameters);
160
1.98k
  }
161
162
  formatv_object(formatv_object const &rhs) = delete;
163
164
  formatv_object(formatv_object &&rhs)
165
      : formatv_object_base(std::move(rhs)),
166
        Parameters(std::move(rhs.Parameters)) {
167
    Adapters = apply_tuple(create_adapters(), Parameters);
168
  }
169
};
170
171
// \brief Format text given a format string and replacement parameters.
172
//
173
// ===General Description===
174
//
175
// Formats textual output.  `Fmt` is a string consisting of one or more
176
// replacement sequences with the following grammar:
177
//
178
// rep_field ::= "{" [index] ["," layout] [":" format] "}"
179
// index     ::= <non-negative integer>
180
// layout    ::= [[[char]loc]width]
181
// format    ::= <any string not containing "{" or "}">
182
// char      ::= <any character except "{" or "}">
183
// loc       ::= "-" | "=" | "+"
184
// width     ::= <positive integer>
185
//
186
// index   - A non-negative integer specifying the index of the item in the
187
//           parameter pack to print.  Any other value is invalid.
188
// layout  - A string controlling how the field is laid out within the available
189
//           space.
190
// format  - A type-dependent string used to provide additional options to
191
//           the formatting operation.  Refer to the documentation of the
192
//           various individual format providers for per-type options.
193
// char    - The padding character.  Defaults to ' ' (space).  Only valid if
194
//           `loc` is also specified.
195
// loc     - Where to print the formatted text within the field.  Only valid if
196
//           `width` is also specified.
197
//           '-' : The field is left aligned within the available space.
198
//           '=' : The field is centered within the available space.
199
//           '+' : The field is right aligned within the available space (this
200
//                 is the default).
201
// width   - The width of the field within which to print the formatted text.
202
//           If this is less than the required length then the `char` and `loc`
203
//           fields are ignored, and the field is printed with no leading or
204
//           trailing padding.  If this is greater than the required length,
205
//           then the text is output according to the value of `loc`, and padded
206
//           as appropriate on the left and/or right by `char`.
207
//
208
// ===Special Characters===
209
//
210
// The characters '{' and '}' are reserved and cannot appear anywhere within a
211
// replacement sequence.  Outside of a replacement sequence, in order to print
212
// a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and
213
// "}}" to print a literal '}'.
214
//
215
// ===Parameter Indexing===
216
// `index` specifies the index of the parameter in the parameter pack to format
217
// into the output.  Note that it is possible to refer to the same parameter
218
// index multiple times in a given format string.  This makes it possible to
219
// output the same value multiple times without passing it multiple times to the
220
// function. For example:
221
//
222
//   formatv("{0} {1} {0}", "a", "bb")
223
//
224
// would yield the string "abba".  This can be convenient when it is expensive
225
// to compute the value of the parameter, and you would otherwise have had to
226
// save it to a temporary.
227
//
228
// ===Formatter Search===
229
//
230
// For a given parameter of type T, the following steps are executed in order
231
// until a match is found:
232
//
233
//   1. If the parameter is of class type, and contains a method
234
//      void format(raw_ostream &Stream, StringRef Options)
235
//      Then this method is invoked to produce the formatted output.  The
236
//      implementation should write the formatted text into `Stream`.
237
//   2. If there is a suitable template specialization of format_provider<>
238
//      for type T containing a method whose signature is:
239
//      void format(const T &Obj, raw_ostream &Stream, StringRef Options)
240
//      Then this method is invoked as described in Step 1.
241
//
242
// If a match cannot be found through either of the above methods, a compiler
243
// error is generated.
244
//
245
// ===Invalid Format String Handling===
246
//
247
// In the case of a format string which does not match the grammar described
248
// above, the output is undefined.  With asserts enabled, LLVM will trigger an
249
// assertion.  Otherwise, it will try to do something reasonable, but in general
250
// the details of what that is are undefined.
251
//
252
template <typename... Ts>
253
inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype(
254
2.33k
    std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
255
2.33k
  using ParamTuple = decltype(
256
2.33k
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
257
2.33k
  return formatv_object<ParamTuple>(
258
2.33k
      Fmt,
259
2.33k
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
260
2.33k
}
llvm::formatv_object<decltype(std::make_tuple(detail::build_format_adapter(std::forward<llvm::StringRef&, llvm::StringRef&>(fp0))))> llvm::formatv<llvm::StringRef&, llvm::StringRef&>(char const*, llvm::StringRef&&&, llvm::StringRef&&&)
Line
Count
Source
254
168
    std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
255
168
  using ParamTuple = decltype(
256
168
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
257
168
  return formatv_object<ParamTuple>(
258
168
      Fmt,
259
168
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
260
168
}
llvm::formatv_object<decltype(std::make_tuple(detail::build_format_adapter(std::forward<llvm::codeview::GUID const&>(fp0))))> llvm::formatv<llvm::codeview::GUID const&>(char const*, llvm::codeview::GUID const&&&)
Line
Count
Source
254
2
    std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
255
2
  using ParamTuple = decltype(
256
2
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
257
2
  return formatv_object<ParamTuple>(
258
2
      Fmt,
259
2
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
260
2
}
llvm::formatv_object<decltype(std::make_tuple(detail::build_format_adapter(std::forward<unsigned int>(fp0))))> llvm::formatv<unsigned int>(char const*, unsigned int&&)
Line
Count
Source
254
1.98k
    std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
255
1.98k
  using ParamTuple = decltype(
256
1.98k
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
257
1.98k
  return formatv_object<ParamTuple>(
258
1.98k
      Fmt,
259
1.98k
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
260
1.98k
}
llvm::formatv_object<decltype(std::make_tuple(detail::build_format_adapter(std::forward<llvm::StringRef&, llvm::StringRef&, llvm::StringRef&>(fp0))))> llvm::formatv<llvm::StringRef&, llvm::StringRef&, llvm::StringRef&>(char const*, llvm::StringRef&&&, llvm::StringRef&&&, llvm::StringRef&&&)
Line
Count
Source
254
178
    std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
255
178
  using ParamTuple = decltype(
256
178
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
257
178
  return formatv_object<ParamTuple>(
258
178
      Fmt,
259
178
      std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
260
178
}
261
262
} // end namespace llvm
263
264
#endif // LLVM_SUPPORT_FORMATVARIADIC_H