Coverage Report

Created: 2020-02-15 09:57

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- 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
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
10
11
namespace clang {
12
namespace ast_matchers {
13
namespace dynamic {
14
Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
15
90
                                                     SourceRange Range) {
16
90
  ContextStack.emplace_back();
17
90
  ContextFrame& data = ContextStack.back();
18
90
  data.Type = Type;
19
90
  data.Range = Range;
20
90
  return ArgStream(&data.Args);
21
90
}
22
23
Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
24
                              StringRef MatcherName,
25
                              SourceRange MatcherRange)
26
41
    : Error(Error) {
27
41
  Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
28
41
}
29
30
Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
31
                              StringRef MatcherName,
32
                              SourceRange MatcherRange,
33
                              unsigned ArgNumber)
34
49
    : Error(Error) {
35
49
  Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
36
49
                                                       << MatcherName;
37
49
}
38
39
90
Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }
40
41
Diagnostics::OverloadContext::OverloadContext(Diagnostics *Error)
42
14
    : Error(Error), BeginIndex(Error->Errors.size()) {}
43
44
14
Diagnostics::OverloadContext::~OverloadContext() {
45
14
  // Merge all errors that happened while in this context.
46
14
  if (BeginIndex < Error->Errors.size()) {
47
1
    Diagnostics::ErrorContent &Dest = Error->Errors[BeginIndex];
48
2
    for (size_t i = BeginIndex + 1, e = Error->Errors.size(); i < e; 
++i1
) {
49
1
      Dest.Messages.push_back(Error->Errors[i].Messages[0]);
50
1
    }
51
1
    Error->Errors.resize(BeginIndex + 1);
52
1
  }
53
14
}
54
55
13
void Diagnostics::OverloadContext::revertErrors() {
56
13
  // Revert the errors.
57
13
  Error->Errors.resize(BeginIndex);
58
13
}
59
60
278
Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
61
278
  Out->push_back(Arg.str());
62
278
  return *this;
63
278
}
64
65
Diagnostics::ArgStream Diagnostics::addError(SourceRange Range,
66
69
                                             ErrorType Error) {
67
69
  Errors.emplace_back();
68
69
  ErrorContent &Last = Errors.back();
69
69
  Last.ContextStack = ContextStack;
70
69
  Last.Messages.emplace_back();
71
69
  Last.Messages.back().Range = Range;
72
69
  Last.Messages.back().Type = Error;
73
69
  return ArgStream(&Last.Messages.back().Args);
74
69
}
75
76
8
static StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
77
8
  switch (Type) {
78
3
    case Diagnostics::CT_MatcherConstruct:
79
3
      return "Error building matcher $0.";
80
5
    case Diagnostics::CT_MatcherArg:
81
5
      return "Error parsing argument $0 for matcher $1.";
82
0
  }
83
0
  llvm_unreachable("Unknown ContextType value.");
84
0
}
85
86
37
static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
87
37
  switch (Type) {
88
4
  case Diagnostics::ET_RegistryMatcherNotFound:
89
4
    return "Matcher not found: $0";
90
4
  case Diagnostics::ET_RegistryWrongArgCount:
91
4
    return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
92
7
  case Diagnostics::ET_RegistryWrongArgType:
93
7
    return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
94
1
  case Diagnostics::ET_RegistryNotBindable:
95
1
    return "Matcher does not support binding.";
96
0
  case Diagnostics::ET_RegistryAmbiguousOverload:
97
0
    // TODO: Add type info about the overload error.
98
0
    return "Ambiguous matcher overload.";
99
1
  case Diagnostics::ET_RegistryValueNotFound:
100
1
    return "Value not found: $0";
101
0
102
1
  case Diagnostics::ET_ParserStringError:
103
1
    return "Error parsing string token: <$0>";
104
2
  case Diagnostics::ET_ParserNoOpenParen:
105
2
    return "Error parsing matcher. Found token <$0> while looking for '('.";
106
2
  case Diagnostics::ET_ParserNoCloseParen:
107
2
    return "Error parsing matcher. Found end-of-code while looking for ')'.";
108
1
  case Diagnostics::ET_ParserNoComma:
109
1
    return "Error parsing matcher. Found token <$0> while looking for ','.";
110
1
  case Diagnostics::ET_ParserNoCode:
111
1
    return "End of code found while looking for token.";
112
1
  case Diagnostics::ET_ParserNotAMatcher:
113
1
    return "Input value is not a matcher expression.";
114
1
  case Diagnostics::ET_ParserInvalidToken:
115
1
    return "Invalid token <$0> found when looking for a value.";
116
6
  case Diagnostics::ET_ParserMalformedBindExpr:
117
6
    return "Malformed bind() expression.";
118
1
  case Diagnostics::ET_ParserTrailingCode:
119
1
    return "Expected end of code.";
120
3
  case Diagnostics::ET_ParserNumberError:
121
3
    return "Error parsing numeric literal: <$0>";
122
1
  case Diagnostics::ET_ParserOverloadedType:
123
1
    return "Input value has unresolved overloaded type: $0";
124
0
125
0
  case Diagnostics::ET_None:
126
0
    return "<N/A>";
127
0
  }
128
0
  llvm_unreachable("Unknown ErrorType value.");
129
0
}
130
131
static void formatErrorString(StringRef FormatString,
132
                              ArrayRef<std::string> Args,
133
45
                              llvm::raw_ostream &OS) {
134
101
  while (!FormatString.empty()) {
135
95
    std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
136
95
    OS << Pieces.first.str();
137
95
    if (Pieces.second.empty()) 
break39
;
138
56
139
56
    const char Next = Pieces.second.front();
140
56
    FormatString = Pieces.second.drop_front();
141
56
    if (Next >= '0' && Next <= '9') {
142
56
      const unsigned Index = Next - '0';
143
56
      if (Index < Args.size()) {
144
56
        OS << Args[Index];
145
56
      } else {
146
0
        OS << "<Argument_Not_Provided>";
147
0
      }
148
56
    }
149
56
  }
150
45
}
151
152
static void maybeAddLineAndColumn(SourceRange Range,
153
45
                                  llvm::raw_ostream &OS) {
154
45
  if (Range.Start.Line > 0 && 
Range.Start.Column > 035
) {
155
35
    OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
156
35
  }
157
45
}
158
159
static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
160
8
                                      llvm::raw_ostream &OS) {
161
8
  maybeAddLineAndColumn(Frame.Range, OS);
162
8
  formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
163
8
}
164
165
static void
166
printMessageToStream(const Diagnostics::ErrorContent::Message &Message,
167
37
                     const Twine Prefix, llvm::raw_ostream &OS) {
168
37
  maybeAddLineAndColumn(Message.Range, OS);
169
37
  OS << Prefix;
170
37
  formatErrorString(errorTypeToFormatString(Message.Type), Message.Args, OS);
171
37
}
172
173
static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
174
36
                                      llvm::raw_ostream &OS) {
175
36
  if (Content.Messages.size() == 1) {
176
35
    printMessageToStream(Content.Messages[0], "", OS);
177
35
  } else {
178
3
    for (size_t i = 0, e = Content.Messages.size(); i != e; 
++i2
) {
179
2
      if (i != 0) 
OS << "\n"1
;
180
2
      printMessageToStream(Content.Messages[i],
181
2
                           "Candidate " + Twine(i + 1) + ": ", OS);
182
2
    }
183
1
  }
184
36
}
185
186
8
void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
187
16
  for (size_t i = 0, e = Errors.size(); i != e; 
++i8
) {
188
8
    if (i != 0) 
OS << "\n"0
;
189
8
    printErrorContentToStream(Errors[i], OS);
190
8
  }
191
8
}
192
193
8
std::string Diagnostics::toString() const {
194
8
  std::string S;
195
8
  llvm::raw_string_ostream OS(S);
196
8
  printToStream(OS);
197
8
  return OS.str();
198
8
}
199
200
151
void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
201
179
  for (size_t i = 0, e = Errors.size(); i != e; 
++i28
) {
202
28
    if (i != 0) 
OS << "\n"3
;
203
28
    const ErrorContent &Error = Errors[i];
204
36
    for (size_t i = 0, e = Error.ContextStack.size(); i != e; 
++i8
) {
205
8
      printContextFrameToStream(Error.ContextStack[i], OS);
206
8
      OS << "\n";
207
8
    }
208
28
    printErrorContentToStream(Error, OS);
209
28
  }
210
151
}
211
212
151
std::string Diagnostics::toStringFull() const {
213
151
  std::string S;
214
151
  llvm::raw_string_ostream OS(S);
215
151
  printToStreamFull(OS);
216
151
  return OS.str();
217
151
}
218
219
}  // namespace dynamic
220
}  // namespace ast_matchers
221
}  // namespace clang