P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
error_helper.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#ifndef LIB_ERROR_HELPER_H_
17#define LIB_ERROR_HELPER_H_
18
19#include <type_traits>
20
21#include <boost/format.hpp>
22
23#include "lib/cstring.h"
24#include "lib/error_message.h"
25#include "lib/source_file.h"
26#include "lib/stringify.h"
27
28namespace priv {
29
30// All these methods return std::string because this is the native format of boost::format
31// Position is printed at the beginning.
32static inline ErrorMessage error_helper(boost::format &f, ErrorMessage out) {
33 out.message = boost::str(f);
34 return out;
35}
36
37template <class... Args>
38ErrorMessage error_helper(boost::format &f, ErrorMessage out, const char *t, Args... args);
39
40template <class... Args>
41ErrorMessage error_helper(boost::format &f, ErrorMessage out, const cstring &t, Args... args);
42
43// use: ir/mau.cpp:805
44template <class... Args>
45ErrorMessage error_helper(boost::format &f, ErrorMessage out, const Util::SourceInfo &info,
46 Args... args);
47
48template <typename T, class... Args>
49auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
50 typename std::enable_if<Util::HasToString<T>::value &&
51 !std::is_base_of<Util::IHasSourceInfo, T>::value,
52 ErrorMessage>::type;
53
54template <typename T, class... Args>
55auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args... args) ->
56 typename std::enable_if<Util::HasToString<T>::value &&
57 !std::is_base_of<Util::IHasSourceInfo, T>::value,
58 ErrorMessage>::type;
59
60template <typename T, class... Args>
61auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
62 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, ErrorMessage>::type;
63
64template <typename T, class... Args>
65auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args... args) ->
66 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, ErrorMessage>::type;
67
68template <class... Args>
69ErrorMessage error_helper(boost::format &f, ErrorMessage out, const big_int *t, Args... args);
70
71template <class... Args>
72ErrorMessage error_helper(boost::format &f, ErrorMessage out, const big_int &t, Args... args);
73
74template <typename T, class... Args>
75auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
76 typename std::enable_if<std::is_arithmetic<T>::value, ErrorMessage>::type;
77
78// actual implementations
79
80template <class... Args>
81ErrorMessage error_helper(boost::format &f, ErrorMessage out, const char *t, Args... args) {
82 return error_helper(f % t, out, std::forward<Args>(args)...);
83}
84
85template <class... Args>
86ErrorMessage error_helper(boost::format &f, ErrorMessage out, const cstring &t, Args... args) {
87 return error_helper(f % t.c_str(), out, std::forward<Args>(args)...);
88}
89
90template <typename T, class... Args>
91auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
92 typename std::enable_if<Util::HasToString<T>::value &&
93 !std::is_base_of<Util::IHasSourceInfo, T>::value,
94 ErrorMessage>::type {
95 return error_helper(f % t.toString(), out, std::forward<Args>(args)...);
96}
97
98template <typename T, class... Args>
99auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args... args) ->
100 typename std::enable_if<Util::HasToString<T>::value &&
101 !std::is_base_of<Util::IHasSourceInfo, T>::value,
102 ErrorMessage>::type {
103 return error_helper(f % t->toString(), out, std::forward<Args>(args)...);
104}
105
106template <class... Args>
107ErrorMessage error_helper(boost::format &f, ErrorMessage out, const big_int *t, Args... args) {
108 return error_helper(f % t, out, std::forward<Args>(args)...);
109}
110
111template <class... Args>
112ErrorMessage error_helper(boost::format &f, ErrorMessage out, const big_int &t, Args... args) {
113 return error_helper(f % t, out, std::forward<Args>(args)...);
114}
115
116template <typename T, class... Args>
117auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
118 typename std::enable_if<std::is_arithmetic<T>::value, ErrorMessage>::type {
119 return error_helper(f % t, out, std::forward<Args>(args)...);
120}
121
122template <class... Args>
123ErrorMessage error_helper(boost::format &f, ErrorMessage out, const Util::SourceInfo &info,
124 Args... args) {
125 if (info.isValid()) out.locations.push_back(info);
126 return error_helper(f % "", out, std::forward<Args>(args)...);
127}
128
129template <typename T, class... Args>
130auto error_helper(boost::format &f, ErrorMessage out, const T *t, Args... args) ->
131 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, ErrorMessage>::type {
132 auto info = t->getSourceInfo();
133 if (info.isValid()) out.locations.push_back(info);
134 return error_helper(f % t->toString(), out, std::forward<Args>(args)...);
135}
136
137template <typename T, class... Args>
138auto error_helper(boost::format &f, ErrorMessage out, const T &t, Args... args) ->
139 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, ErrorMessage>::type {
140 auto info = t.getSourceInfo();
141 if (info.isValid()) out.locations.push_back(info);
142 return error_helper(f % t.toString(), out, std::forward<Args>(args)...);
143}
144
145} // namespace priv
146
147// Most direct invocations of error_helper usually only reduce arguments
148template <class... Args>
149ErrorMessage error_helper(boost::format &f, Args... args) {
150 ErrorMessage msg;
151 return ::priv::error_helper(f, msg, std::forward<Args>(args)...);
152}
153
154// Invoked from ErrorReporter
155template <class... Args>
156ErrorMessage error_helper(boost::format &f, ErrorMessage &msg, Args... args) {
157 return ::priv::error_helper(f, msg, std::forward<Args>(args)...);
158}
159
160// This overload exists for backwards compatibility
161template <class... Args>
162ErrorMessage error_helper(boost::format &f, const std::string &prefix, const Util::SourceInfo &info,
163 const std::string &suffix, Args... args) {
164 ErrorMessage msg(prefix, info, suffix);
165 return ::priv::error_helper(f, msg, std::forward<Args>(args)...);
166}
167
168/***********************************************************************************/
169
170static inline std::string bug_helper(boost::format &f, std::string message, std::string position,
171 std::string tail) {
172 std::string text = boost::str(f);
173 std::string result = position;
174 if (!position.empty()) result += ": ";
175 result += message + text + "\n" + tail;
176 return result;
177}
178
179template <class... Args>
180std::string bug_helper(boost::format &f, std::string message, std::string position,
181 std::string tail, const char *t, Args... args);
182
183template <class... Args>
184std::string bug_helper(boost::format &f, std::string message, std::string position,
185 std::string tail, const cstring &t, Args... args);
186
187template <class... Args>
188std::string bug_helper(boost::format &f, std::string message, std::string position,
189 std::string tail, const Util::SourceInfo &info, Args... args);
190
191template <typename T, class... Args>
192auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
193 const T &t, Args... args) ->
194 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type;
195
196template <typename T, class... Args>
197auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
198 const T *t, Args... args) ->
199 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type;
200
201template <typename T, class... Args>
202auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
203 const T *t, Args... args) ->
204 typename std::enable_if<!std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type;
205
206template <class... Args>
207std::string bug_helper(boost::format &f, std::string message, std::string position,
208 std::string tail, const big_int *t, Args... args);
209
210template <class... Args>
211std::string bug_helper(boost::format &f, std::string message, std::string position,
212 std::string tail, const big_int &t, Args... args);
213
214template <typename T, class... Args>
215auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
216 const T &t, Args... args) ->
217 typename std::enable_if<!std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type;
218
219// actual implementations
220
221template <class... Args>
222std::string bug_helper(boost::format &f, std::string message, std::string position,
223 std::string tail, const char *t, Args... args) {
224 return bug_helper(f % t, message, position, tail, std::forward<Args>(args)...);
225}
226
227template <class... Args>
228std::string bug_helper(boost::format &f, std::string message, std::string position,
229 std::string tail, const cstring &t, Args... args) {
230 return bug_helper(f % t.c_str(), message, position, tail, std::forward<Args>(args)...);
231}
232
233template <typename T, class... Args>
234auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
235 const T *t, Args... args) ->
236 typename std::enable_if<!std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type {
237 std::stringstream str;
238 str << t;
239 return bug_helper(f % str.str(), message, position, tail, std::forward<Args>(args)...);
240}
241
242template <class... Args>
243std::string bug_helper(boost::format &f, std::string message, std::string position,
244 std::string tail, const big_int *t, Args... args) {
245 return bug_helper(f % t, message, position, tail, std::forward<Args>(args)...);
246}
247
248template <class... Args>
249std::string bug_helper(boost::format &f, std::string message, std::string position,
250 std::string tail, const big_int &t, Args... args) {
251 return bug_helper(f % t, message, position, tail, std::forward<Args>(args)...);
252}
253
254template <typename T, class... Args>
255auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
256 const T &t, Args... args) ->
257 typename std::enable_if<!std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type {
258 return bug_helper(f % t, message, position, tail, std::forward<Args>(args)...);
259}
260
261template <class... Args>
262std::string bug_helper(boost::format &f, std::string message, std::string position,
263 std::string tail, const Util::SourceInfo &info, Args... args) {
264 cstring posString = info.toPositionString();
265 if (position.empty()) {
266 position = posString;
267 posString = "";
268 } else {
269 if (!posString.isNullOrEmpty()) {
270 posString += "\n";
271 }
272 }
273 return bug_helper(f % "", message, position, tail + posString + info.toSourceFragment(),
274 std::forward<Args>(args)...);
275}
276
277template <typename T, class... Args>
278auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
279 const T *t, Args... args) ->
280 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type {
281 if (t == nullptr) {
282 return bug_helper(f, message, position, tail, std::forward<Args>(args)...);
283 }
284
285 cstring posString = t->getSourceInfo().toPositionString();
286 if (position.empty()) {
287 position = posString;
288 posString = "";
289 } else {
290 if (!posString.isNullOrEmpty()) {
291 posString += "\n";
292 }
293 }
294 std::stringstream str;
295 str << t;
296 return bug_helper(f % str.str(), message, position,
297 tail + posString + t->getSourceInfo().toSourceFragment(),
298 std::forward<Args>(args)...);
299}
300
301template <typename T, class... Args>
302auto bug_helper(boost::format &f, std::string message, std::string position, std::string tail,
303 const T &t, Args... args) ->
304 typename std::enable_if<std::is_base_of<Util::IHasSourceInfo, T>::value, std::string>::type {
305 cstring posString = t.getSourceInfo().toPositionString();
306 if (position.empty()) {
307 position = posString;
308 posString = "";
309 } else {
310 if (!posString.isNullOrEmpty()) {
311 posString += "\n";
312 }
313 }
314 std::stringstream str;
315 str << t;
316 return bug_helper(f % str.str(), message, position,
317 tail + posString + t.getSourceInfo().toSourceFragment(),
318 std::forward<Args>(args)...);
319}
320
321#endif /* LIB_ERROR_HELPER_H_ */
Definition source_file.h:126
Definition cstring.h:72
Definition error_message.h:36
std::vector< Util::SourceInfo > locations
Particular formatted message.
Definition error_message.h:42
std::string message
Typically error/warning type from catalog.
Definition error_message.h:41