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