Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/FormatVariadic.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- FormatVariadic.cpp - Format string parsing and analysis ----*-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
#include "llvm/Support/FormatVariadic.h"
10
11
using namespace llvm;
12
13
1.94k
static Optional<AlignStyle> translateLocChar(char C) {
14
1.94k
  switch (C) {
15
172
  case '-':
16
172
    return AlignStyle::Left;
17
120
  case '=':
18
120
    return AlignStyle::Center;
19
440
  case '+':
20
440
    return AlignStyle::Right;
21
1.21k
  default:
22
1.21k
    return None;
23
0
  }
24
0
  
LLVM_BUILTIN_UNREACHABLE0
;
25
0
}
26
27
bool formatv_object_base::consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
28
1.15k
                                             size_t &Align, char &Pad) {
29
1.15k
  Where = AlignStyle::Right;
30
1.15k
  Align = 0;
31
1.15k
  Pad = ' ';
32
1.15k
  if (Spec.empty())
33
0
    return true;
34
1.15k
35
1.15k
  
if (1.15k
Spec.size() > 11.15k
) {
36
972
    // A maximum of 2 characters at the beginning can be used for something
37
972
    // other
38
972
    // than the width.
39
972
    // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...]
40
972
    // contains the width.
41
972
    // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width.
42
972
    // Otherwise, Spec[0:...] contains the width.
43
972
    if (auto 
Loc972
= translateLocChar(Spec[1])) {
44
1
      Pad = Spec[0];
45
1
      Where = *Loc;
46
1
      Spec = Spec.drop_front(2);
47
972
    } else 
if (auto 971
Loc971
= translateLocChar(Spec[0])) {
48
731
      Where = *Loc;
49
731
      Spec = Spec.drop_front(1);
50
731
    }
51
972
  }
52
1.15k
53
1.15k
  bool Failed = Spec.consumeInteger(0, Align);
54
1.15k
  return !Failed;
55
1.15k
}
56
57
Optional<ReplacementItem>
58
16.4k
formatv_object_base::parseReplacementItem(StringRef Spec) {
59
16.4k
  StringRef RepString = Spec.trim("{}");
60
16.4k
61
16.4k
  // If the replacement sequence does not start with a non-negative integer,
62
16.4k
  // this is an error.
63
16.4k
  char Pad = ' ';
64
16.4k
  std::size_t Align = 0;
65
16.4k
  AlignStyle Where = AlignStyle::Right;
66
16.4k
  StringRef Options;
67
16.4k
  size_t Index = 0;
68
16.4k
  RepString = RepString.trim();
69
16.4k
  if (
RepString.consumeInteger(0, Index)16.4k
) {
70
0
    assert(false && "Invalid replacement sequence index!");
71
0
    return ReplacementItem{};
72
0
  }
73
16.4k
  RepString = RepString.trim();
74
16.4k
  if (
!RepString.empty() && 16.4k
RepString.front() == ','3.97k
) {
75
1.15k
    RepString = RepString.drop_front();
76
1.15k
    if (!consumeFieldLayout(RepString, Where, Align, Pad))
77
1.15k
      assert(false && "Invalid replacement field layout specification!");
78
1.15k
  }
79
16.4k
  RepString = RepString.trim();
80
16.4k
  if (
!RepString.empty() && 16.4k
RepString.front() == ':'3.11k
) {
81
3.11k
    Options = RepString.drop_front().trim();
82
3.11k
    RepString = StringRef();
83
3.11k
  }
84
16.4k
  RepString = RepString.trim();
85
16.4k
  if (
!RepString.empty()16.4k
) {
86
0
    assert(false && "Unexpected characters found in replacement string!");
87
0
  }
88
16.4k
89
16.4k
  return ReplacementItem{Spec, Index, Align, Where, Pad, Options};
90
16.4k
}
91
92
std::pair<ReplacementItem, StringRef>
93
31.1k
formatv_object_base::splitLiteralAndReplacement(StringRef Fmt) {
94
31.1k
  StringRef Rep;
95
31.1k
  StringRef Remainder;
96
31.1k
  std::size_t From = 0;
97
31.1k
  while (
From < Fmt.size() && 31.1k
From != StringRef::npos31.1k
) {
98
31.1k
    std::size_t BO = Fmt.find_first_of('{', From);
99
31.1k
    // Everything up until the first brace is a literal.
100
31.1k
    if (BO != 0)
101
14.5k
      return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO));
102
16.5k
103
16.5k
    StringRef Braces =
104
33.2k
        Fmt.drop_front(BO).take_while([](char C) { return C == '{'; });
105
16.5k
    // If there is more than one brace, then some of them are escaped.  Treat
106
16.5k
    // these as replacements.
107
16.5k
    if (
Braces.size() > 116.5k
) {
108
107
      size_t NumEscapedBraces = Braces.size() / 2;
109
107
      StringRef Middle = Fmt.substr(BO, NumEscapedBraces);
110
107
      StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2);
111
107
      return std::make_pair(ReplacementItem{Middle}, Right);
112
107
    }
113
16.4k
    // An unterminated open brace is undefined.  We treat the rest of the string
114
16.4k
    // as a literal replacement, but we assert to indicate that this is
115
16.4k
    // undefined and that we consider it an error.
116
16.4k
    std::size_t BC = Fmt.find_first_of('}', BO);
117
16.4k
    if (
BC == StringRef::npos16.4k
) {
118
0
      assert(
119
0
          false &&
120
0
          "Unterminated brace sequence.  Escape with {{ for a literal brace.");
121
0
      return std::make_pair(ReplacementItem{Fmt}, StringRef());
122
0
    }
123
16.4k
124
16.4k
    // Even if there is a closing brace, if there is another open brace before
125
16.4k
    // this closing brace, treat this portion as literal, and try again with the
126
16.4k
    // next one.
127
16.4k
    std::size_t BO2 = Fmt.find_first_of('{', BO + 1);
128
16.4k
    if (BO2 < BC)
129
3
      return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)},
130
3
                            Fmt.substr(BO2));
131
16.4k
132
16.4k
    StringRef Spec = Fmt.slice(BO + 1, BC);
133
16.4k
    StringRef Right = Fmt.substr(BC + 1);
134
16.4k
135
16.4k
    auto RI = parseReplacementItem(Spec);
136
16.4k
    if (RI.hasValue())
137
16.4k
      return std::make_pair(*RI, Right);
138
0
139
0
    // If there was an error parsing the replacement item, treat it as an
140
0
    // invalid replacement spec, and just continue.
141
0
    From = BC + 1;
142
0
  }
143
0
  return std::make_pair(ReplacementItem{Fmt}, StringRef());
144
31.1k
}
145
146
std::vector<ReplacementItem>
147
8.46k
formatv_object_base::parseFormatString(StringRef Fmt) {
148
8.46k
  std::vector<ReplacementItem> Replacements;
149
8.46k
  ReplacementItem I;
150
39.6k
  while (
!Fmt.empty()39.6k
) {
151
31.1k
    std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt);
152
31.1k
    if (I.Type != ReplacementType::Empty)
153
31.1k
      Replacements.push_back(I);
154
31.1k
  }
155
8.46k
  return Replacements;
156
8.46k
}