ROSE  0.11.145.0
Assert.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef Sawyer_Assert_H
9 #define Sawyer_Assert_H
10 
11 #include <Sawyer/Sawyer.h>
12 
13 #include <boost/config.hpp>
14 #include <boost/lexical_cast.hpp>
15 #include <string>
16 #ifdef __clang_analyzer__
17 #include <cassert>
18 #endif
19 
20 // If SAWYER_NDEBUG is defined then some of the macros defined in this header become no-ops. For interoperability with the
21 // more standard NDEBUG symbol, we define SAWYER_NDEBUG if NDEBUG is defined.
22 #ifdef NDEBUG
23 #undef SAWYER_NDEBUG
24 #define SAWYER_NDEBUG
25 #endif
26 
27 namespace Sawyer { // documented elsewhere
28 
96 namespace Assert {
97 
100 SAWYER_EXPORT
101 #ifndef BOOST_WINDOWS
102 [[noreturn]]
103 #endif
104 void fail(const char *mesg, const char *expr, const std::string &note,
105  const char *filename, unsigned linenum, const char *funcname);
106 
108 typedef void (*AssertFailureHandler)(const char *mesg, const char *expr, const std::string &note,
109  const char *filename, unsigned linenum, const char *funcname);
110 
114 SAWYER_EXPORT extern AssertFailureHandler assertFailureHandler;
115 
116 } // namespace
117 } // namespace
118 
120 // These "always" macros are enabled regardless of whether SAWYER_NDEBUG is defined. Don't use them for
121 // expensive assertions.
123 
124 #define ASSERT_always_require(expr) ASSERT_always_require2(expr, "")
125 #define ASSERT_always_forbid(expr) ASSERT_always_forbid2(expr, "")
126 #define ASSERT_always_not_null(expr) ASSERT_always_not_null2(expr, "")
127 #define ASSERT_always_not_reachable(note) \
128  Sawyer::Assert::fail("reached impossible state", NULL, boost::lexical_cast<std::string>(note), \
129  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
130 #define ASSERT_always_not_implemented(note) \
131  Sawyer::Assert::fail("not implemented yet", NULL, boost::lexical_cast<std::string>(note), \
132  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
133 #define ASSERT_always_this() /*void*/
134 
135 #ifdef __clang_analyzer__
136  // The Clang analyzer doesn't recognize Sawyer::Assert::fail, but it does recognize C's assert
137  #define ASSERT_always_require2(expr, note) assert(expr)
138  #define ASSERT_always_forbid2(expr, note) assert(!(expr))
139  #define ASSERT_always_not_null2(expr, note) assert((expr) != nullptr)
140 #else
141  #define ASSERT_always_require2(expr, note) \
142  ((expr) ? \
143  static_cast<void>(0) : \
144  Sawyer::Assert::fail("assertion failed", "required: " #expr, boost::lexical_cast<std::string>(note), \
145  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
146 
147  #define ASSERT_always_forbid2(expr, note) \
148  (!(expr) ? \
149  static_cast<void>(0) : \
150  Sawyer::Assert::fail("assertion failed", \
151  "forbidden: " #expr, boost::lexical_cast<std::string>(note), \
152  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
153 
154  #define ASSERT_always_not_null2(expr, note) \
155  ((expr)!=NULL ? \
156  static_cast<void>(0) : \
157  Sawyer::Assert::fail("null pointer", \
158  #expr, boost::lexical_cast<std::string>(note), __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
159 #endif
160 
162 // The non-"always" macros might change behavior based on whether SAWYER_NDEBUG is defined.
164 
165 #if defined(SAWYER_NDEBUG) && !defined(__clang_analyzer__)
166 
167 #define ASSERT_require(expr) /*void*/
168 #define ASSERT_require2(expr, note) /*void*/
169 #define ASSERT_forbid(expr) /*void*/
170 #define ASSERT_forbid2(expr, note) /*void*/
171 #define ASSERT_not_null(expr) /*void*/
172 #define ASSERT_not_null2(expr, note) /*void*/
173 #define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
174 #define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
175 #define ASSERT_this() /*void*/
176 
177 #else
178 
179 #define ASSERT_require(expr) ASSERT_always_require(expr)
180 #define ASSERT_require2(expr, note) ASSERT_always_require2(expr, note)
181 #define ASSERT_forbid(expr) ASSERT_always_forbid(expr)
182 #define ASSERT_forbid2(expr, note) ASSERT_always_forbid2(expr, note)
183 #define ASSERT_not_null(expr) ASSERT_always_not_null(expr)
184 #define ASSERT_not_null2(expr, note) ASSERT_always_not_null2(expr, note)
185 #define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
186 #define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
187 #define ASSERT_this() /*void*/
188 
189 #endif
190 
192 // Macros recognized by some IDEs
194 
195 #define TODO(note) \
196  Sawyer::Assert::fail("not implemented yet", NULL, boost::lexical_cast<std::string>(note), \
197  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
198 
199 #define FIXME(note) \
200  Sawyer::Assert::fail("needs to be fixed", NULL, boost::lexical_cast<std::string>(note), \
201  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
202 
203 #endif
void(* AssertFailureHandler)(const char *mesg, const char *expr, const std::string &note, const char *filename, unsigned linenum, const char *funcname)
Type for user-defined assertion failure handler.
Definition: Assert.h:108
Name space for the entire library.
Definition: FeasiblePath.h:767
AssertFailureHandler assertFailureHandler
Optional user callback to handle assertion failures.
void fail(const char *mesg, const char *expr, const std::string &note, const char *filename, unsigned linenum, const char *funcname)
Cause immediate failure.