P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
error_reporter.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef LIB_ERROR_REPORTER_H_
18#define LIB_ERROR_REPORTER_H_
19
20#include <ostream>
21#include <set>
22#include <type_traits>
23#include <unordered_map>
24
25#include <boost/format.hpp>
26
27#include "error_catalog.h"
28#include "error_helper.h"
29#include "exceptions.h"
30
32enum class DiagnosticAction {
33 Ignore,
34 Info,
35 Warn,
36 Error
37};
38
39// Keeps track of compilation errors.
40// Errors are specified using the error() and warning() methods,
41// that use boost::format format strings, i.e.,
42// %1%, %2%, etc (starting at 1, not at 0).
43// Some compatibility for printf-style arguments is also supported.
45 protected:
46 unsigned int infoCount;
47 unsigned int warningCount;
48 unsigned int errorCount;
49 unsigned int maxErrorCount;
50
51 std::ostream *outputstream;
52
54 std::set<std::pair<int, const Util::SourceInfo>> errorTracker;
55
57 virtual void emit_message(const ErrorMessage &msg) {
58 *outputstream << msg.toString();
59 outputstream->flush();
60 }
61
62 virtual void emit_message(const ParserErrorMessage &msg) {
63 *outputstream << msg.toString();
64 outputstream->flush();
65 }
66
71 bool error_reported(int err, const Util::SourceInfo source) {
72 if (!source.isValid()) return false;
73 auto p = errorTracker.emplace(err, source);
74 return !p.second; // if insertion took place, then we have not seen the error.
75 }
76
78 const char *get_error_name(int errorCode) {
79 return ErrorCatalog::getCatalog().getName(errorCode);
80 }
81
82 public:
84 : infoCount(0),
85 warningCount(0),
86 errorCount(0),
87 maxErrorCount(20),
88 defaultInfoDiagnosticAction(DiagnosticAction::Info),
89 defaultWarningDiagnosticAction(DiagnosticAction::Warn) {
90 outputstream = &std::cerr;
91 }
92
93 // error message for a bug
94 template <typename... T>
95 std::string bug_message(const char *format, T... args) {
96 boost::format fmt(format);
97 std::string message = ::bug_helper(fmt, "", "", "", args...);
98 return message;
99 }
100
101 template <typename... T>
102 std::string format_message(const char *format, T... args) {
103 boost::format fmt(format);
104 std::string message = ::error_helper(fmt, args...).toString();
105 return message;
106 }
107
108 template <
109 class T,
110 typename = typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value>::type,
111 typename... Args>
112 void diagnose(DiagnosticAction action, const int errorCode, const char *format,
113 const char *suffix, const T *node, Args... args) {
114 if (node && !error_reported(errorCode, node->getSourceInfo())) {
115 const char *name = get_error_name(errorCode);
116 auto da = getDiagnosticAction(name, action);
117 if (name)
118 diagnose(da, name, format, suffix, node, args...);
119 else
120 diagnose(action, nullptr, format, suffix, node, std::forward<Args>(args)...);
121 }
122 }
123
124 template <
125 class T,
126 typename = typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value>::type,
127 typename... Args>
128 void diagnose(DiagnosticAction action, const int errorCode, const char *format,
129 const char *suffix, const T &node, Args... args) {
130 diagnose(action, errorCode, format, suffix, &node, std::forward<Args>(args)...);
131 }
132
133 template <typename... Args>
134 void diagnose(DiagnosticAction action, const int errorCode, const char *format,
135 const char *suffix, Args... args) {
136 const char *name = get_error_name(errorCode);
137 auto da = getDiagnosticAction(name, action);
138 if (name)
139 diagnose(da, name, format, suffix, args...);
140 else
141 diagnose(action, nullptr, format, suffix, std::forward<Args>(args)...);
142 }
143
146 template <typename... T>
147 void diagnose(DiagnosticAction action, const char *diagnosticName, const char *format,
148 const char *suffix, T... args) {
149 if (action == DiagnosticAction::Ignore) return;
150
151 ErrorMessage::MessageType msgType = ErrorMessage::MessageType::None;
152 if (action == DiagnosticAction::Info) {
153 // Avoid burying errors in a pile of info messages:
154 // don't emit any more info messages if we've emitted errors.
155 if (errorCount > 0) return;
156
157 infoCount++;
158 msgType = ErrorMessage::MessageType::Info;
159 } else if (action == DiagnosticAction::Warn) {
160 // Avoid burying errors in a pile of warnings: don't emit any more warnings if we've
161 // emitted errors.
162 if (errorCount > 0) return;
163
164 warningCount++;
165 msgType = ErrorMessage::MessageType::Warning;
166 } else if (action == DiagnosticAction::Error) {
167 errorCount++;
168 msgType = ErrorMessage::MessageType::Error;
169 }
170
171 boost::format fmt(format);
172 ErrorMessage msg(msgType, diagnosticName ? diagnosticName : "", suffix);
173 msg = ::error_helper(fmt, msg, args...);
174 emit_message(msg);
175
176 if (errorCount > maxErrorCount)
177 FATAL_ERROR("Number of errors exceeded set maximum of %1%", maxErrorCount);
178 }
179
180 unsigned getErrorCount() const { return errorCount; }
181
182 unsigned getMaxErrorCount() const { return maxErrorCount; }
184 unsigned setMaxErrorCount(unsigned newMaxCount) {
185 auto r = maxErrorCount;
186 maxErrorCount = newMaxCount;
187 return r;
188 }
189
190 unsigned getWarningCount() const { return warningCount; }
191
192 unsigned getInfoCount() const { return infoCount; }
193
196 unsigned getDiagnosticCount() const { return errorCount + warningCount + infoCount; }
197
198 void setOutputStream(std::ostream *stream) { outputstream = stream; }
199
200 std::ostream *getOutputStream() const { return outputstream; }
201
204 template <typename T>
205 void parser_error(const Util::SourceInfo &location, const T &message) {
206 errorCount++;
207 std::stringstream ss;
208 ss << message;
209
210 ParserErrorMessage msg(location, ss.str());
211 emit_message(msg);
212 }
213
220 void parser_error(const Util::InputSources *sources, const char *fmt, va_list args) {
221 errorCount++;
222
223 Util::SourcePosition position = sources->getCurrentPosition();
224 position--;
225 cstring message = Util::vprintf_format(fmt, args);
226
227 Util::SourceInfo info(sources, position);
228 ParserErrorMessage msg(info, message);
229 emit_message(msg);
230 }
231 void parser_error(const Util::InputSources *sources, const char *fmt, ...) {
232 va_list args;
233 va_start(args, fmt);
234 parser_error(sources, fmt, args);
235 va_end(args);
236 }
237
240 DiagnosticAction getDiagnosticAction(cstring diagnostic, DiagnosticAction defaultAction) {
241 // Actions for errors can never be overridden.
242 if (defaultAction == DiagnosticAction::Error) return defaultAction;
243 auto it = diagnosticActions.find(diagnostic);
244 if (it != diagnosticActions.end()) return it->second;
245 // if we're dealing with warnings and they have been globally modified
246 // (ignored or turned into errors), then return the global default
247 if (defaultAction == DiagnosticAction::Warn &&
248 defaultWarningDiagnosticAction != DiagnosticAction::Warn)
249 return defaultWarningDiagnosticAction;
250 return defaultAction;
251 }
252
254 void setDiagnosticAction(cstring diagnostic, DiagnosticAction action) {
255 diagnosticActions[diagnostic] = action;
256 }
257
259 DiagnosticAction getDefaultWarningDiagnosticAction() { return defaultWarningDiagnosticAction; }
260
262 void setDefaultWarningDiagnosticAction(DiagnosticAction action) {
263 defaultWarningDiagnosticAction = action;
264 }
265
267 DiagnosticAction getDefaultInfoDiagnosticAction() { return defaultInfoDiagnosticAction; }
268
270 void setDefaultInfoDiagnosticAction(DiagnosticAction action) {
271 defaultInfoDiagnosticAction = action;
272 }
273
274 private:
276 DiagnosticAction defaultInfoDiagnosticAction;
277
279 DiagnosticAction defaultWarningDiagnosticAction;
280
282 std::unordered_map<cstring, DiagnosticAction> diagnosticActions;
283};
284
285#endif /* LIB_ERROR_REPORTER_H_ */
cstring getName(int errorCode)
retrieve the name for errorCode
Definition error_catalog.h:125
static ErrorCatalog & getCatalog()
Return the singleton object.
Definition error_catalog.h:99
Definition error_reporter.h:44
std::ostream * outputstream
the maximum number of errors that we print before fail
Definition error_reporter.h:51
void parser_error(const Util::InputSources *sources, const char *fmt, va_list args)
Definition error_reporter.h:220
void setDefaultWarningDiagnosticAction(DiagnosticAction action)
set the default diagnostic action for calls to warning().
Definition error_reporter.h:262
void setDefaultInfoDiagnosticAction(DiagnosticAction action)
set the default diagnostic action for calls to ::info().
Definition error_reporter.h:270
std::set< std::pair< int, const Util::SourceInfo > > errorTracker
Track errors or warnings that have already been issued for a particular source location.
Definition error_reporter.h:54
const char * get_error_name(int errorCode)
retrieve the format from the error catalog
Definition error_reporter.h:78
DiagnosticAction getDiagnosticAction(cstring diagnostic, DiagnosticAction defaultAction)
Definition error_reporter.h:240
DiagnosticAction getDefaultInfoDiagnosticAction()
Definition error_reporter.h:267
bool error_reported(int err, const Util::SourceInfo source)
Definition error_reporter.h:71
virtual void emit_message(const ErrorMessage &msg)
Output the message and flush the stream.
Definition error_reporter.h:57
void parser_error(const Util::SourceInfo &location, const T &message)
Definition error_reporter.h:205
void setDiagnosticAction(cstring diagnostic, DiagnosticAction action)
Set the action to take for the given diagnostic.
Definition error_reporter.h:254
void diagnose(DiagnosticAction action, const char *diagnosticName, const char *format, const char *suffix, T... args)
Definition error_reporter.h:147
unsigned setMaxErrorCount(unsigned newMaxCount)
set maxErrorCount to a the @newMaxCount threshold and return the previous value
Definition error_reporter.h:184
DiagnosticAction getDefaultWarningDiagnosticAction()
Definition error_reporter.h:259
unsigned getDiagnosticCount() const
Definition error_reporter.h:196
Definition source_file.h:263
Definition source_file.h:126
Definition source_file.h:56
Definition cstring.h:72
Definition error_message.h:36
Definition error_message.h:64