LLVM  10.0.0svn
FormatVariadic.cpp
Go to the documentation of this file.
1 //===- FormatVariadic.cpp - Format string parsing and analysis ----*-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 
9 
10 using namespace llvm;
11 
13  switch (C) {
14  case '-':
15  return AlignStyle::Left;
16  case '=':
17  return AlignStyle::Center;
18  case '+':
19  return AlignStyle::Right;
20  default:
21  return None;
22  }
23  LLVM_BUILTIN_UNREACHABLE;
24 }
25 
27  size_t &Align, char &Pad) {
28  Where = AlignStyle::Right;
29  Align = 0;
30  Pad = ' ';
31  if (Spec.empty())
32  return true;
33 
34  if (Spec.size() > 1) {
35  // A maximum of 2 characters at the beginning can be used for something
36  // other
37  // than the width.
38  // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...]
39  // contains the width.
40  // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width.
41  // Otherwise, Spec[0:...] contains the width.
42  if (auto Loc = translateLocChar(Spec[1])) {
43  Pad = Spec[0];
44  Where = *Loc;
45  Spec = Spec.drop_front(2);
46  } else if (auto Loc = translateLocChar(Spec[0])) {
47  Where = *Loc;
48  Spec = Spec.drop_front(1);
49  }
50  }
51 
52  bool Failed = Spec.consumeInteger(0, Align);
53  return !Failed;
54 }
55 
58  StringRef RepString = Spec.trim("{}");
59 
60  // If the replacement sequence does not start with a non-negative integer,
61  // this is an error.
62  char Pad = ' ';
63  std::size_t Align = 0;
65  StringRef Options;
66  size_t Index = 0;
67  RepString = RepString.trim();
68  if (RepString.consumeInteger(0, Index)) {
69  assert(false && "Invalid replacement sequence index!");
70  return ReplacementItem{};
71  }
72  RepString = RepString.trim();
73  if (!RepString.empty() && RepString.front() == ',') {
74  RepString = RepString.drop_front();
75  if (!consumeFieldLayout(RepString, Where, Align, Pad))
76  assert(false && "Invalid replacement field layout specification!");
77  }
78  RepString = RepString.trim();
79  if (!RepString.empty() && RepString.front() == ':') {
80  Options = RepString.drop_front().trim();
81  RepString = StringRef();
82  }
83  RepString = RepString.trim();
84  if (!RepString.empty()) {
85  assert(false && "Unexpected characters found in replacement string!");
86  }
87 
88  return ReplacementItem{Spec, Index, Align, Where, Pad, Options};
89 }
90 
91 std::pair<ReplacementItem, StringRef>
93  std::size_t From = 0;
94  while (From < Fmt.size() && From != StringRef::npos) {
95  std::size_t BO = Fmt.find_first_of('{', From);
96  // Everything up until the first brace is a literal.
97  if (BO != 0)
98  return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO));
99 
100  StringRef Braces =
101  Fmt.drop_front(BO).take_while([](char C) { return C == '{'; });
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;
106  StringRef Middle = Fmt.substr(BO, NumEscapedBraces);
107  StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2);
108  return std::make_pair(ReplacementItem{Middle}, Right);
109  }
110  // An unterminated open brace is undefined. We treat the rest of the string
111  // as a literal replacement, but we assert to indicate that this is
112  // undefined and that we consider it an error.
113  std::size_t BC = Fmt.find_first_of('}', BO);
114  if (BC == StringRef::npos) {
115  assert(
116  false &&
117  "Unterminated brace sequence. Escape with {{ for a literal brace.");
118  return std::make_pair(ReplacementItem{Fmt}, StringRef());
119  }
120 
121  // Even if there is a closing brace, if there is another open brace before
122  // this closing brace, treat this portion as literal, and try again with the
123  // next one.
124  std::size_t BO2 = Fmt.find_first_of('{', BO + 1);
125  if (BO2 < BC)
126  return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)},
127  Fmt.substr(BO2));
128 
129  StringRef Spec = Fmt.slice(BO + 1, BC);
130  StringRef Right = Fmt.substr(BC + 1);
131 
132  auto RI = parseReplacementItem(Spec);
133  if (RI.hasValue())
134  return std::make_pair(*RI, Right);
135 
136  // If there was an error parsing the replacement item, treat it as an
137  // invalid replacement spec, and just continue.
138  From = BC + 1;
139  }
140  return std::make_pair(ReplacementItem{Fmt}, StringRef());
141 }
142 
143 std::vector<ReplacementItem>
145  std::vector<ReplacementItem> Replacements;
147  while (!Fmt.empty()) {
148  std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt);
149  if (I.Type != ReplacementType::Empty)
150  Replacements.push_back(I);
151  }
152  return Replacements;
153 }
154 
155 void detail::format_adapter::anchor() { }
const NoneType None
Definition: None.h:23
uint64_t CallInst * C
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
LLVM_NODISCARD StringRef drop_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the first N elements dropped.
Definition: StringRef.h:620
LLVM_NODISCARD StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:679
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:578
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:126
LLVM_NODISCARD StringRef take_while(function_ref< bool(char)> F) const
Return the longest prefix of &#39;this&#39; such that every character in the prefix satisfies the given predi...
Definition: StringRef.h:606
static std::vector< ReplacementItem > parseFormatString(StringRef Fmt)
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:512
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
LLVM_NODISCARD StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:817
AlignStyle
Definition: FormatCommon.h:17
static std::pair< ReplacementItem, StringRef > splitLiteralAndReplacement(StringRef Fmt)
static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where, size_t &Align, char &Pad)
std::vector< ReplacementItem > Replacements
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
static Optional< ReplacementItem > parseReplacementItem(StringRef Spec)
BlockVerifier::State From
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition: Error.h:147
static const size_t npos
Definition: StringRef.h:50
LLVM_NODISCARD 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.
Definition: StringRef.h:380
#define I(x, y, z)
Definition: MD5.cpp:58
ReplacementType Type
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM_NODISCARD char front() const
front - Get the first character in the string.
Definition: StringRef.h:134
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
static Optional< AlignStyle > translateLocChar(char C)