1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #ifndef SQUID__TEXTEXCEPTION_H
10 #define SQUID__TEXTEXCEPTION_H
11 
12 #include "base/Here.h"
13 
14 #include <stdexcept>
15 
16 class SBuf;
17 
18 /// an std::runtime_error with thrower location info
19 class TextException: public std::runtime_error
20 {
21 
22 public:
TextException(const char * message,const SourceLocation & location)23     TextException(const char *message, const SourceLocation &location):
24         std::runtime_error(message),
25         where(location)
26     {}
27 
28     TextException(SBuf message, const SourceLocation &location);
29 
30     TextException(const TextException &) = default;
31     TextException(TextException &&) = default;
32     TextException& operator=(const TextException &) = default;
33 
34     /* std::runtime_error API */
35     virtual ~TextException() throw() override;
36     virtual const char *what() const throw() override;
37 
38     /// same-location exceptions have the same ID
id()39     SourceLocationId id() const { return where.id(); }
40 
41     /// dumps the exception text into the stream
42     std::ostream &print(std::ostream &) const;
43 
44     /// code location related to the exception; usually the thrower location
45     SourceLocation where;
46 
47     // TODO: Add support for arbitrary (re)thrower-supplied details:
48     // std::tuple<Details...> details;
49 };
50 
51 /// prints active (i.e., thrown but not yet handled) exception
52 std::ostream &CurrentException(std::ostream &);
53 
54 /// legacy convenience macro; it is not difficult to type Here() now
55 #define TexcHere(msg) TextException((msg), Here())
56 
57 /// Like assert() but throws an exception instead of aborting the process
58 /// and allows the caller to specify a custom exception message.
59 #define Must2(condition, message) \
60     do { \
61         if (!(condition)) { \
62             const TextException Must_ex_((message), Here()); \
63             debugs(0, 3, Must_ex_.what()); \
64             throw Must_ex_; \
65         } \
66     } while (/*CONSTCOND*/ false)
67 
68 /// Like assert() but throws an exception instead of aborting the process.
69 #define Must(condition) Must2((condition), "check failed: " #condition)
70 
71 /// Reports and swallows all exceptions to prevent compiler warnings and runtime
72 /// errors related to throwing class destructors. Should be used for most dtors.
73 #define SWALLOW_EXCEPTIONS(code) \
74     try { \
75         code \
76     } catch (...) { \
77         debugs(0, DBG_IMPORTANT, "BUG: ignoring exception;\n" << \
78                "    bug location: " << Here() << "\n" << \
79                "    ignored exception: " << CurrentException); \
80     }
81 
82 #endif /* SQUID__TEXTEXCEPTION_H */
83 
84