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