ROSE  0.11.109.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 <string>
15 #ifdef __clang_analyzer__
16 #include <cassert>
17 #endif
18 
19 // If SAWYER_NDEBUG is defined then some of the macros defined in this header become no-ops. For interoperability with the
20 // more standard NDEBUG symbol, we define SAWYER_NDEBUG if NDEBUG is defined.
21 #ifdef NDEBUG
22 #undef SAWYER_NDEBUG
23 #define SAWYER_NDEBUG
24 #endif
25 
26 namespace Sawyer { // documented elsewhere
27 
95 namespace Assert {
96 
99 SAWYER_EXPORT
100 #ifndef BOOST_WINDOWS
101 [[noreturn]]
102 #endif
103 void fail(const char *mesg, const char *expr, const std::string &note,
104  const char *filename, unsigned linenum, const char *funcname);
105 
107 typedef void (*AssertFailureHandler)(const char *mesg, const char *expr, const std::string &note,
108  const char *filename, unsigned linenum, const char *funcname);
109 
113 SAWYER_EXPORT extern AssertFailureHandler assertFailureHandler;
114 
115 } // namespace
116 } // namespace
117 
119 // These "always" macros are enabled regardless of whether SAWYER_NDEBUG is defined. Don't use them for
120 // expensive assertions.
122 
123 #define ASSERT_always_require(expr) ASSERT_always_require2(expr, "")
124 #define ASSERT_always_forbid(expr) ASSERT_always_forbid2(expr, "")
125 #define ASSERT_always_not_null(expr) ASSERT_always_not_null2(expr, "")
126 #define ASSERT_always_not_reachable(note) \
127  Sawyer::Assert::fail("reached impossible state", NULL, (note), \
128  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
129 #define ASSERT_always_not_implemented(note) \
130  Sawyer::Assert::fail("not implemented yet", NULL, (note), \
131  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
132 #define ASSERT_always_this() /*void*/
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 #else
140  #define ASSERT_always_require2(expr, note) \
141  ((expr) ? \
142  static_cast<void>(0) : \
143  Sawyer::Assert::fail("assertion failed", "required: " #expr, (note), \
144  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
145 
146  #define ASSERT_always_forbid2(expr, note) \
147  (!(expr) ? \
148  static_cast<void>(0) : \
149  Sawyer::Assert::fail("assertion failed", \
150  "forbidden: " #expr, (note), __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
151 
152  #define ASSERT_always_not_null2(expr, note) \
153  ((expr)!=NULL ? \
154  static_cast<void>(0) : \
155  Sawyer::Assert::fail("null pointer", \
156  #expr, (note), __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION))
157 #endif
158 
160 // The non-"always" macros might change behavior based on whether SAWYER_NDEBUG is defined.
162 
163 #if defined(SAWYER_NDEBUG) && !defined(__clang_analyzer__)
164 
165 #define ASSERT_require(expr) /*void*/
166 #define ASSERT_require2(expr, note) /*void*/
167 #define ASSERT_forbid(expr) /*void*/
168 #define ASSERT_forbid2(expr, note) /*void*/
169 #define ASSERT_not_null(expr) /*void*/
170 #define ASSERT_not_null2(expr, note) /*void*/
171 #define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
172 #define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
173 #define ASSERT_this() /*void*/
174 
175 #else
176 
177 #define ASSERT_require(expr) ASSERT_always_require(expr)
178 #define ASSERT_require2(expr, note) ASSERT_always_require2(expr, note)
179 #define ASSERT_forbid(expr) ASSERT_always_forbid(expr)
180 #define ASSERT_forbid2(expr, note) ASSERT_always_forbid2(expr, note)
181 #define ASSERT_not_null(expr) ASSERT_always_not_null(expr)
182 #define ASSERT_not_null2(expr, note) ASSERT_always_not_null2(expr, note)
183 #define ASSERT_not_reachable(note) ASSERT_always_not_reachable(note)
184 #define ASSERT_not_implemented(note) ASSERT_always_not_implemented(note)
185 #define ASSERT_this() /*void*/
186 
187 #endif
188 
190 // Macros recognized by some IDEs
192 
193 #define TODO(note) \
194  Sawyer::Assert::fail("not implemented yet", NULL, (note), \
195  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
196 
197 #define FIXME(note) \
198  Sawyer::Assert::fail("needs to be fixed", NULL, (note), \
199  __FILE__, __LINE__, SAWYER_PRETTY_FUNCTION)
200 
201 #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:107
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.