PandA-2024.02
exceptions.hpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
46 #ifndef EXCEPTIONS_HPP
47 #define EXCEPTIONS_HPP
48 
50 #include "config_HAVE_ASSERTS.hpp"
51 #include "config_HAVE_PRINT_STACK.hpp"
52 
54 #include <iostream>
55 #include <string>
56 #if HAVE_PRINT_STACK
57 #include <cxxabi.h>
58 #include <execinfo.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 #endif
64 
65 extern int exit_code;
66 
67 extern bool error_on_warning;
68 
77 template <class T>
78 inline T& throw_error(const T& t, const std::string& expression,
79  const char*
80 #ifndef NDEBUG
81  pp
82 #endif
83  ,
84  const char*
85 #ifndef NDEBUG
86  file
87 #endif
88  ,
89  int
90 #ifndef NDEBUG
91  line
92 #endif
93  ,
94  int code = EXIT_FAILURE)
95 {
96  exit_code = code;
97 #ifdef NDEBUG
98  throw std::string(std::string("error -> ") + expression + std::string("\n"));
99 #else
100  throw std::string(std::string("error -> ") + expression + std::string("\n\t") + std::string(pp) +
101  std::string("\n\t") + std::string(file) + std::string(":") + std::to_string(line));
102 #endif
103  static T t_local = t;
104  return t_local;
105 }
106 
110 inline void throw_warning(const std::string& expression,
111  const char*
112 #ifndef NDEBUG
113  pp
114 #endif
115  ,
116  const char*
117 #ifndef NDEBUG
118  file
119 #endif
120  ,
121  int
122 #ifndef NDEBUG
123  line
124 #endif
125 )
126 {
127 #ifdef NDEBUG
128  throw std::string(std::string("warning -> ") + expression + std::string("\n"));
129 #else
130  throw std::string(std::string("warning -> ") + expression + std::string("\n\t") + std::string(pp) +
131  std::string("\n\t") + std::string(file) + std::string(":") + std::to_string(line));
132 #endif
133 }
134 
143 template <class T>
144 inline T& throw_error(const T& t, const char* expression, const char* pp, const char* file, int line,
145  int code = EXIT_FAILURE)
146 {
147  return throw_error(t, std::string(expression), pp, file, line, code);
148 }
149 #if HAVE_PRINT_STACK
150 #define PRINT_STACK \
151  do \
152  { \
153  const size_t print_stack_max_depth = 100; \
154  size_t print_stack_stack_depth; \
155  void* print_stack_stack_addrs[print_stack_max_depth]; \
156  char** print_stack_stack_strings; \
157  \
158  char buf[256]; \
159  ssize_t readlink_res = readlink("/proc/self/exe", buf, sizeof(buf)); \
160  if(readlink_res == -1) \
161  printf("Failed command: %s\n", "readlink"); \
162  buf[readlink_res] = '\0'; \
163  std::string program(buf); \
164  print_stack_stack_depth = static_cast<size_t>(backtrace(print_stack_stack_addrs, print_stack_max_depth)); \
165  print_stack_stack_strings = \
166  backtrace_symbols(print_stack_stack_addrs, static_cast<int>(print_stack_stack_depth)); \
167  \
168  printf("Call stack\n"); \
169  \
170  for(size_t print_stack_i = 0; print_stack_i < print_stack_stack_depth; print_stack_i++) \
171  { \
172  size_t print_stack_sz = 2000; /* just a guess, template names will go much wider*/ \
173  char* print_stack_function = static_cast<char*>(malloc(print_stack_sz)); \
174  char* print_stack_address = static_cast<char*>(malloc(print_stack_sz)); \
175  char *print_stack_begin = nullptr, *print_stack_end = nullptr; \
176  size_t print_stack_first = 0, print_stack_last = 0; \
177  size_t print_stack_counter; \
178  print_stack_counter = 0; \
179  /* find the parentheses and address offset surrounding the mangled name */ \
180  for(char* print_stack_j = print_stack_stack_strings[print_stack_i]; *print_stack_j; \
181  ++print_stack_j, print_stack_counter++) \
182  { \
183  if(*print_stack_j == '(') \
184  { \
185  print_stack_begin = print_stack_j; \
186  } \
187  else if(*print_stack_j == '+') \
188  { \
189  print_stack_end = print_stack_j; \
190  } \
191  else if(*print_stack_j == '[') \
192  { \
193  print_stack_first = print_stack_counter; \
194  } \
195  else if(*print_stack_j == ']') \
196  { \
197  print_stack_last = print_stack_counter; \
198  } \
199  } \
200  if(print_stack_begin && print_stack_end) \
201  { \
202  *print_stack_begin++ = 0; \
203  *print_stack_end = 0; \
204  /* found our mangled name, now in [print_stack_begin, print_stack_end)*/ \
205  \
206  int print_stack_status; \
207  char* print_stack_ret = \
208  abi::__cxa_demangle(print_stack_begin, print_stack_function, &print_stack_sz, &print_stack_status); \
209  if(print_stack_ret) \
210  { \
211  /*return value may be a realloc() of the input*/ \
212  print_stack_function = print_stack_ret; \
213  } \
214  else \
215  { \
216  /* demangling failed, just pretend it's a C function with no args */ \
217  strncpy(print_stack_function, print_stack_begin, print_stack_sz); \
218  strncat(print_stack_function, "()", print_stack_sz); \
219  print_stack_function[print_stack_sz - 1] = 0; \
220  } \
221  printf("%s:%s\n", print_stack_stack_strings[print_stack_i], print_stack_function); \
222  if(print_stack_first && print_stack_last) \
223  { \
224  std::string print_stack_command; \
225  print_stack_command += "addr2line"; \
226  strncpy(print_stack_address, &((print_stack_stack_strings[print_stack_i])[print_stack_first + 1]), \
227  print_stack_last - print_stack_first - 1); \
228  print_stack_address[print_stack_last - print_stack_first] = '\0'; \
229  print_stack_command += " -C " + std::string(print_stack_address) + " -e " + program; \
230  int print_stack_res = std::system(print_stack_command.c_str()); \
231  if(is_failure(print_stack_res)) \
232  printf("Failed command: %s\n", print_stack_command.c_str()); \
233  } \
234  } \
235  else \
236  { \
237  /* didn't find the mangled name, just print the whole line*/ \
238  printf("%s\n", print_stack_stack_strings[print_stack_i]); \
239  if(print_stack_first && print_stack_last) \
240  { \
241  std::string print_stack_command; \
242  print_stack_command += "addr2line"; \
243  strncpy(print_stack_address, &((print_stack_stack_strings[print_stack_i])[print_stack_first + 1]), \
244  print_stack_last - print_stack_first - 1); \
245  print_stack_address[print_stack_last - print_stack_first] = '\0'; \
246  print_stack_command += " -C " + std::string(print_stack_address) + " -e " + program; \
247  int print_stack_res = std::system(print_stack_command.c_str()); \
248  if(is_failure(print_stack_res)) \
249  printf("Failed command: %s\n", print_stack_command.c_str()); \
250  } \
251  } \
252  printf("\n"); \
253  free(print_stack_function); \
254  free(print_stack_address); \
255  } \
256  free(print_stack_stack_strings); /* malloc()ed by backtrace_symbols*/ \
257  } while(0)
258 #else
259 #define PRINT_STACK
260 #endif
261 
263 #define THROW_ERROR(str_expr) throw_error(0, (str_expr), __PRETTY_FUNCTION__, __FILE__, __LINE__)
264 
266 #define THROW_ERROR_CODE(code, str_expr) \
267  do \
268  { \
269  PRINT_STACK; \
270  throw_error(0, (str_expr), __PRETTY_FUNCTION__, __FILE__, __LINE__, code); \
271  } while(0)
272 
274 #if HAVE_ASSERTS
275 #define THROW_ASSERT(cond, str_expr) \
276  do \
277  { \
278  if(cond) \
279  { \
280  ; \
281  } \
282  else \
283  { \
284  PRINT_STACK; \
285  THROW_ERROR(std::string(str_expr) + " (" + #cond + ")"); \
286  } \
287  } while(0)
288 #else
289 #define THROW_ASSERT(cond, str_expr)
290 #endif
291 #define THROW_UNREACHABLE(str_expr) \
293  do \
294  { \
295  THROW_ERROR(std::string("This point should never be reached - " + std::string(str_expr))); \
296  } while(0)
297 
300 #define THROW_WARNING(str_expr) \
301  ((error_on_warning) ? ((void)(THROW_ERROR(str_expr))) : \
302  ((void)(std::cerr << std::string("Warning: ") + (str_expr) << std::endl)))
303 
305 #define NOT_YET_IMPLEMENTED() \
306  ((error_on_warning) ? \
307  ((void)(THROW_ERROR(std::string("Not yet implemented")))) : \
308  (throw_warning((std::string("Not yet implemented")), __PRETTY_FUNCTION__, __FILE__, __LINE__)))
309 
311 #if HAVE_ASSERTS
312 #define THROW_WARNING_ASSERT(cond, str_expr) \
313  ((cond) ? (void)0 : (THROW_WARNING(std::string(str_expr) + " (" + #cond + ")")))
314 #else
315 #define THROW_WARNING_ASSERT(cond, str_expr) (void)0
316 #endif
317 
322 {
339  GRMON_EC,
342 };
343 
349 bool IsError(const int error_value);
350 
356 bool is_failure(const int error_value);
357 
358 #endif
error during profiling
Definition: exceptions.hpp:331
error during compilation
Definition: exceptions.hpp:332
bool is_failure(const int error_value)
Return true if the return value corresponds to a failure (not to an error)
Definition: exceptions.cpp:64
Not supported variable length array.
Definition: exceptions.hpp:333
malformed struct
Definition: exceptions.hpp:329
bool error_on_warning
Transform warning into errors.
bitfield not supported
Definition: exceptions.hpp:336
Node not yet supported.
Definition: exceptions.hpp:323
int exit_code
Autoheader include.
void throw_warning(const std::string &expression, const char *pp, const char *file, int line)
Prints a warning, along with information about the source code.
Definition: exceptions.hpp:110
void line(int x1, int y1, int x2, int y2, unsigned int color)
Definition: main.c:110
pointer_plus_expr not removed
Definition: exceptions.hpp:334
C pattern not supported.
Definition: exceptions.hpp:337
varargs with cross-compiler
Definition: exceptions.hpp:335
boh not yet supported
Definition: exceptions.hpp:328
Not trapped by panda torture script.
Definition: exceptions.hpp:340
task graph structure not yet supported
Definition: exceptions.hpp:327
bool IsError(const int error_value)
Return true if the return_value corresponds to an error.
Definition: exceptions.cpp:58
T & throw_error(const T &t, const std::string &expression, const char *pp, const char *file, int line, int code=EXIT_FAILURE)
Template function used to throw an exception.
Definition: exceptions.hpp:78
irreducible loops are not currently supported
Definition: exceptions.hpp:324
nested functions are not currently supported
Definition: exceptions.hpp:325
throw_error_code
Error code returned by THROW_ERROR_CODE.
Definition: exceptions.hpp:321
pragma pattern not yet supported
Definition: exceptions.hpp:326
Corrupted bitstream.
Definition: exceptions.hpp:341
error with task creation
Definition: exceptions.hpp:330

Generated on Mon Feb 12 2024 13:02:56 for PandA-2024.02 by doxygen 1.8.13