Spicy
exception.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <iostream>
6 #include <ostream>
7 #include <stdexcept>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include <hilti/rt/backtrace.h>
13 #include <hilti/rt/extension-points.h>
14 #include <hilti/rt/fmt.h>
15 
16 namespace hilti::rt {
17 
22 class Exception : public std::runtime_error {
23 public:
27  Exception(const std::string& desc);
28 
33  Exception(std::string_view desc, std::string_view location);
34 
35  Exception() : std::runtime_error("<no error>"){};
36  Exception(const Exception&) = default;
37  Exception(Exception&&) noexcept = default;
38  Exception& operator=(const Exception&) = default;
39  Exception& operator=(Exception&&) noexcept = default;
40 
41  // Empty, but required to make exception handling work between library
42  // and host application. See:
43  // http://www.toptip.ca/2012/06/c-exceptions-thrown-from-shared-library.html
44  ~Exception() override;
45 
47  auto description() const { return _description; }
48 
50  auto location() const { return _location; }
51 
56  auto backtrace() const { return _backtrace.backtrace(); }
57 
58 private:
59  Exception(const std::string& what, std::string_view desc, std::string_view location);
60 
61  std::string _description;
62  std::string _location;
63  Backtrace _backtrace;
64 };
65 
66 inline std::ostream& operator<<(std::ostream& stream, const Exception& e) { return stream << e.what(); }
67 
68 #define HILTI_EXCEPTION(name, base) \
69  class name : public ::hilti::rt::base { \
70  public: \
71  using ::hilti::rt::base::base; \
72  virtual ~name(); /* required to create vtable, see hilti::rt::Exception */ \
73  };
74 
75 #define HILTI_EXCEPTION_NS(name, ns, base) \
76  class name : public ns::base { \
77  public: \
78  using ns::base::base; \
79  virtual ~name(); /* required to create vtable, see hilti::rt::Exception */ \
80  };
81 
82 #define HILTI_EXCEPTION_IMPL(name) name::name::~name() = default;
83 
85 HILTI_EXCEPTION(RuntimeError, Exception)
86 
87 
88 HILTI_EXCEPTION(UsageError, Exception)
89 
90 
91 HILTI_EXCEPTION(RecoverableFailure, RuntimeError)
92 
93 
94 HILTI_EXCEPTION(AssertionFailure, RuntimeError)
95 
96 /*
97  * Exception triggered y the ".?" operator to signal to host applications that
98  * a struct attribute isn't set.
99  */
100 HILTI_EXCEPTION(AttributeNotSet, RuntimeError)
101 
102 
105 HILTI_EXCEPTION(DivisionByZero, RuntimeError)
106 
107 
108 HILTI_EXCEPTION(EnvironmentError, UsageError)
109 
110 
111 HILTI_EXCEPTION(ExpiredReference, RuntimeError)
112 
113 
116 HILTI_EXCEPTION(Frozen, RuntimeError)
117 
118 
119 HILTI_EXCEPTION(IllegalReference, RuntimeError)
120 
121 
122 HILTI_EXCEPTION(IndexError, RuntimeError)
123 
124 
125 HILTI_EXCEPTION(InvalidArgument, RuntimeError);
126 
128 HILTI_EXCEPTION(InvalidIterator, RuntimeError)
129 
130 
131 HILTI_EXCEPTION(InvalidValue, RuntimeError);
132 
134 HILTI_EXCEPTION(MatchStateReuse, RuntimeError)
135 
136 
137 HILTI_EXCEPTION(MissingData, RecoverableFailure);
138 
140 HILTI_EXCEPTION(NotSupported, RuntimeError)
141 
142 
143 HILTI_EXCEPTION(NullReference, RuntimeError)
144 
145 
146 HILTI_EXCEPTION(OutOfRange, RuntimeError)
147 
148 
151 HILTI_EXCEPTION(Overflow, RuntimeError)
152 
153 
154 HILTI_EXCEPTION(PatternError, RuntimeError)
155 
156 
157 HILTI_EXCEPTION(UnhandledSwitchCase, RuntimeError)
158 
159 
160 HILTI_EXCEPTION(UnicodeError, RuntimeError)
161 
162 
165 HILTI_EXCEPTION(UnsetOptional, RuntimeError)
166 
167 
170 HILTI_EXCEPTION(UnsetUnionMember, RuntimeError)
171 
172 
175 HILTI_EXCEPTION(StackSizeExceeded, RuntimeError)
176 
177 
178 class FormattingError : public RuntimeError {
179 public:
180  FormattingError(std::string desc) : RuntimeError(_sanitize(std::move(desc))) {}
181 
182 private:
183  std::string _sanitize(std::string desc) {
184  if ( auto pos = desc.find("tinyformat: "); pos != std::string::npos )
185  desc.erase(pos, 12);
186 
187  return desc;
188  }
189 };
190 
199 class WouldBlock : public std::runtime_error {
200 public:
201  using std::runtime_error::runtime_error;
202 
207  WouldBlock(const std::string& desc, const std::string& location);
208 };
209 
210 namespace exception {
211 
212 // Disables `Configuration::abort_on_exception` during its lifetime.
214 public:
217 
220  DisableAbortOnExceptions& operator=(const DisableAbortOnExceptions&) = delete;
221  DisableAbortOnExceptions& operator=(DisableAbortOnExceptions&&) noexcept = delete;
222 };
223 
225 void printUncaught(const Exception& e);
226 
228 void printUncaught(const Exception& e, std::ostream& out);
229 
231 inline std::string what(const std::exception& e) { return e.what(); }
232 
233 } // namespace exception
234 
235 namespace detail::adl {
236 inline std::string to_string(const Exception& e, adl::tag /*unused*/) { return fmt("<exception: %s>", e.what()); }
237 inline std::string to_string(const WouldBlock& e, adl::tag /*unused*/) { return fmt("<exception: %s>", e.what()); }
238 } // namespace detail::adl
239 
240 } // namespace hilti::rt
auto backtrace() const
Definition: exception.h:56
std::string to_string(T &&x)
Definition: extension-points.h:26
Definition: exception.h:199
Definition: any.h:7
auto description() const
Definition: exception.h:47
Definition: exception.h:178
Definition: backtrace.h:15
auto location() const
Definition: exception.h:50
Definition: exception.h:22
Definition: location.h:94
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
HILTI_EXCEPTION(InvalidArgument, RuntimeError)