1//===- FormatVariadic.cpp - Format string parsing and analysis ----*-C++-*-===//
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//===----------------------------------------------------------------------===//
25 LLVM_BUILTIN_UNREACHABLE;
29 unsigned &
Align,
char &Pad) {
36 if (
Spec.size() > 1) {
37 // A maximum of 2 characters at the beginning can be used for something
38 // other than the width.
39 // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...]
40 // contains the width.
41 // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width.
42 // Otherwise, Spec[0:...] contains the width.
60 // If the replacement sequence does not start with a non-negative integer,
67 RepString = RepString.
ltrim();
69 // If index is not specified, keep it ~0U to indicate unresolved index.
74 assert(
false &&
"Invalid replacement field layout specification!");
78 RepString = RepString.
ltrim();
83 RepString = RepString.
trim();
84 if (!RepString.
empty()) {
85 assert(0 &&
"Unexpected characters found in replacement string!");
92static std::pair<std::optional<ReplacementItem>,
StringRef>
95 // Everything up until the first brace is a literal.
96 if (Fmt.
front() !=
'{') {
102 // If there is more than one brace, then some of them are escaped. Treat
103 // these as replacements.
104 if (Braces.
size() > 1) {
105 size_t NumEscapedBraces = Braces.
size() / 2;
110 // An unterminated open brace is undefined. Assert to indicate that this is
111 // undefined and that we consider it an error. When asserts are disabled,
112 // build a replacement item with an error message.
116 "Unterminated brace sequence. Escape with {{ for a literal brace.");
117 return {
ReplacementItem(
"Unterminated brace sequence. Escape with {{ for a "
122 // Even if there is a closing brace, if there is another open brace before
123 // this closing brace, treat this portion as literal, and try again with the
136 #define ENABLE_VALIDATION 1
138#define ENABLE_VALIDATION 0 // Conveniently enable validation in release mode.
145 unsigned NextAutomaticIndex = 0;
149 unsigned NumExpectedArgs = 0;
150 bool HasExplicitIndex =
false;
153 while (!
Fmt.empty()) {
154 std::optional<ReplacementItem>
I;
160 I->Index = NextAutomaticIndex++;
163 HasExplicitIndex =
true;
164 NumExpectedArgs = std::max(NumExpectedArgs,
I->Index + 1);
175 // Perform additional validation. Verify that the number of arguments matches
176 // the number of replacement indices and that there are no holes in the
177 // replacement indices.
179 // When validation fails, return an array of replacement items that
180 // will print an error message as the outout of this formatv() (used when
181 // validation is enabled in release mode).
182 auto getErrorReplacements = [SavedFmtStr](
StringLiteral ErrorMsg) {
188 if (NumExpectedArgs != NumArgs) {
189 errs() <<
formatv(
"Expected {} Args, but got {} for format string '{}'\n",
190 NumExpectedArgs, NumArgs, SavedFmtStr);
191 assert(0 &&
"Invalid formatv() call");
192 return getErrorReplacements(
"Unexpected number of arguments");
195 // Find the number of unique indices seen. All replacement indices
196 // are < NumExpectedArgs.
202 Indices[
I.Index] =
true;
206 if (
Count != NumExpectedArgs) {
208 "Replacement field indices cannot have holes for format string '{}'\n",
210 assert(0 &&
"Invalid format string");
211 return getErrorReplacements(
"Replacement indices have holes");
214 // Fail validation if we see both automatic index and explicit index.
215 if (NextAutomaticIndex != 0 && HasExplicitIndex) {
217 "Cannot mix automatic and explicit indices for format string '{}'\n",
219 assert(0 &&
"Invalid format string");
220 return getErrorReplacements(
"Cannot mix automatic and explicit indices");
222#endif // ENABLE_VALIDATION
226void support::detail::format_adapter::anchor() {}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
StringRef take_while(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that every character in the prefix satisfies the given predi...
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
testing::Matcher< const detail::ErrorHolder & > Failed()
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr Count
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
This struct is a compact representation of a valid (non-zero power of two) alignment.