ROSE 2.20.0
Loading...
Searching...
No Matches
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://gitlab.com/charger7534/sawyer.git.
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
27namespace Sawyer { // documented elsewhere
28
96namespace Assert {
97
100SAWYER_EXPORT
101#ifndef BOOST_WINDOWS
102[[noreturn]]
103#endif
104void fail(const char *mesg, const char *expr, const std::string &note,
105 const char *filename, unsigned linenum, const char *funcname);
106
108typedef void (*AssertFailureHandler)(const char *mesg, const char *expr, const std::string &note,
109 const char *filename, unsigned linenum, const char *funcname);
110
114SAWYER_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
134#ifdef __clang_analyzer__
135 // The Clang analyzer doesn't recognize Sawyer::Assert::fail, but it does recognize C's assert
136 #define ASSERT_always_require2(expr, note) assert(expr)
137 #define ASSERT_always_forbid2(expr, note) assert(!(expr))
138 #define ASSERT_always_not_null2(expr, note) assert((expr) != nullptr)
139 #define ASSERT_always_this() assert(this != NULL)
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
160 #if defined(__GNUC__) && !defined(__clang__)
161 #define ROSE_ASSERT_DIAG_PUSH _Pragma("GCC diagnostic push")
162 #define ROSE_ASSERT_DIAG_POP _Pragma("GCC diagnostic pop")
163 #define ROSE_ASSERT_DIAG_IGNORED _Pragma("GCC diagnostic ignored \"-Wnonnull-compare\"")
164 #elif defined(__clang__)
165 #define ROSE_ASSERT_DIAG_PUSH _Pragma("GCC diagnostic push")
166 #define ROSE_ASSERT_DIAG_POP _Pragma("GCC diagnostic pop")
167 #define ROSE_ASSERT_DIAG_IGNORED _Pragma("GCC diagnostic ignored \"-Wtautological-undefined-compare\"")
168 #else
169 #define ROSE_ASSERT_DIAG_PUSH
170 #define ROSE_ASSERT_DIAG_POP
171 #define ROSE_ASSERT_DIAG_IGNORED
172 #endif
173
174 #define ASSERT_suppress_nonnull_compare(expr) \
175 do { \
176 ROSE_ASSERT_DIAG_PUSH \
177 ROSE_ASSERT_DIAG_IGNORED \
178 expr; \
179 ROSE_ASSERT_DIAG_POP \
180 } while (false)
181
182 #define ASSERT_always_this() \
183 ASSERT_suppress_nonnull_compare((this != NULL) ? \
184 static_cast<void>(0) : \
185 Sawyer::Assert::fail("null pointer", \
186 "this != NULL", boost::lexical_cast<std::string>(""), __FILE__, __LINE__, \
187 SAWYER_PRETTY_FUNCTION))
188#endif
189
191// The non-"always" macros might change behavior based on whether SAWYER_NDEBUG is defined.
193
194#if defined(SAWYER_NDEBUG) && !defined(__clang_analyzer__)
195
196#define ASSERT_require(expr) /*void*/
197#define ASSERT_require2(expr, note) /*void*/
198#define ASSERT_forbid(expr) /*void*/
199#define ASSERT_forbid2(expr, note) /*void*/
200#define ASSERT_not_null(expr) /*void*/
201#define ASSERT_not_null2(expr, note) /*void*/
202#define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
203#define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
204#define ASSERT_this() /*void*/
205
206#else
207
208#define ASSERT_require(expr) ASSERT_always_require(expr)
209#define ASSERT_require2(expr, note) ASSERT_always_require2(expr, note)
210#define ASSERT_forbid(expr) ASSERT_always_forbid(expr)
211#define ASSERT_forbid2(expr, note) ASSERT_always_forbid2(expr, note)
212#define ASSERT_not_null(expr) ASSERT_always_not_null(expr)
213#define ASSERT_not_null2(expr, note) ASSERT_always_not_null2(expr, note)
214#define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
215#define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
216#define ASSERT_this() ASSERT_always_this()
217
218#endif
219
221// Macros recognized by some IDEs
223
224#define TODO(note) \
225 Sawyer::Assert::fail("not implemented yet", NULL, boost::lexical_cast<std::string>(note), \
226 __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
227
228#define FIXME(note) \
229 Sawyer::Assert::fail("needs to be fixed", NULL, boost::lexical_cast<std::string>(note), \
230 __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
231
232#endif
void fail(const char *mesg, const char *expr, const std::string &note, const char *filename, unsigned linenum, const char *funcname)
Cause immediate failure.
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
AssertFailureHandler assertFailureHandler
Optional user callback to handle assertion failures.
Sawyer support library.