gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Exception related solutions removed and new LEMON_DEBUG macro
0 2 0
default
2 files changed with 102 insertions and 368 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -27,71 +27,6 @@
27 27

	
28 28
namespace lemon {
29 29

	
30
  /// @{
31

	
32
  ///\e
33
  class AssertionFailedError : public LogicError {
34
  protected:
35
    const char *_assertion;
36
    const char *_file;
37
    int _line;
38
    const char *_function;
39
    const char *_message;
40

	
41
    mutable ExceptionMember<std::string> _message_holder;
42
  public:
43
    ///\e
44
    AssertionFailedError(const char *file, int line, const char *function,
45
			 const char *msg, const char *assertion = 0) :
46
      _assertion(assertion), _file(file), _line(line), 
47
      _function(function), _message(msg) {}
48

	
49
    ///\e
50
    const char* assertion() const { return _assertion; }
51
    ///\e
52
    const char* message() const { return _message; }
53
    ///\e
54
    const char* file() const { return _file; }
55
    ///\e
56
    const char* function() const { return _function; }
57
    ///\e
58
    int line() const { return _line; }
59

	
60

	
61
    virtual const char* what() const throw() {
62
      try {
63
	std::ostringstream ostr;
64
	ostr << _file << ":" << _line << ": ";
65
	if (_function)
66
	  ostr << _function << ": ";
67
	ostr << _message;
68
	if (_assertion)
69
	   ostr << " (assertion '" << _assertion << "' failed)";
70
	_message_holder.set(ostr.str());
71
	return ostr.str().c_str();
72
      }
73
      catch(...) {}
74
      if( _message_holder.valid() ) return _message_holder.get().c_str();
75
      return "lemon::AssertionFailedError";
76
    }
77
    virtual ~AssertionFailedError() throw() {}
78
  };
79

	
80

	
81
  inline void assert_fail_log(const char *file, int line,
82
			      const char *function,
83
			      const std::exception& exception, 
84
			      const char *assertion)
85
  {
86
    std::cerr << file << ":" << line << ": ";
87
    if (function)
88
      std::cerr << function << ": ";
89
    std::cerr << exception.what();
90
    if (assertion)
91
      std::cerr << " (assertion '" << assertion << "' failed)";
92
    std::cerr << std::endl;
93
  }
94

	
95 30
  inline void assert_fail_log(const char *file, int line, const char *function,
96 31
			      const char *message, const char *assertion)
97 32
  {
... ...
@@ -104,21 +39,6 @@
104 39
    std::cerr << std::endl;
105 40
  }
106 41

	
107
  inline void assert_fail_log(const char *file, int line, const char *function, 
108
			      const std::string& message, const char *assertion)
109
  {
110
    assert_fail_log(file, line, function, message.c_str(), assertion);
111
  }
112

	
113
  inline void assert_fail_abort(const char *file, int line, 
114
				const char *function,
115
				const std::exception& exception,
116
				const char *assertion)
117
  {
118
    assert_fail_log(file, line, function, exception, assertion);
119
    std::abort();
120
  }
121

	
122 42
  inline void assert_fail_abort(const char *file, int line,
123 43
				const char *function, const char* message,
124 44
				const char *assertion)
... ...
@@ -127,86 +47,37 @@
127 47
    std::abort();
128 48
  }
129 49

	
130
  inline void assert_fail_abort(const char *file, int line, 
131
				const char *function, 
132
				const std::string& message,
133
				const char *assertion)
134
  {
135
    assert_fail_log(file, line, function, message.c_str(), assertion);
136
    std::abort();
50
  namespace _assert_bits {
51
    
52
    
53
    inline const char* cstringify(const std::string& str) {
54
      return str.c_str();
55
    }
56

	
57
    inline const char* cstringify(const char* str) {
58
      return str;
59
    }    
137 60
  }
61
}
138 62

	
139
  inline void assert_fail_error(const char *file, int line, 
140
				  const char *function,
141
				  const std::exception& exception,
142
				  const char *assertion)
143
  {
144
    throw AssertionFailedError(file, line, function, 
145
			       exception.what(), assertion);
146
  }
147

	
148
  inline void assert_fail_error(const char *file, int line,
149
				  const char *function, const char *message,
150
				  const char *assertion)
151
  {
152
    throw AssertionFailedError(file, line, function, message, assertion);
153
  }
154

	
155
  inline void assert_fail_error(const char *file, int line,
156
				  const char *function, 
157
				  const std::string& message,
158
				  const char *assertion)
159
  {
160
    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
161
  }
162

	
163
  template <typename Exception>
164
  inline void assert_fail_exception(const char *, int, const char *,
165
				    const Exception& exception,
166
				    const char *, const std::exception* = 
167
				    static_cast<const Exception*>(0))
168
  {
169
    throw exception;
170
  }
171

	
172
  inline void assert_fail_exception(const char *file, int line,
173
				    const char *function, const char *message,
174
				    const char *assertion)
175
  {
176
    throw AssertionFailedError(file, line, function, message, assertion);
177
  }
178

	
179
  inline void assert_fail_exception(const char *file, int line, 
180
				    const char *function, 
181
				    const std::string& message,
182
				    const char *assertion)
183
  {
184
    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
185
  }
186

	
187
/// @}
188

	
189
}
190 63
#endif // LEMON_ASSERT_H
191 64

	
192 65
#undef LEMON_ASSERT
193 66
#undef LEMON_FIXME
67
#undef LEMON_DEBUG
194 68

	
195 69
#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
196 70
  (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
197
  (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
198
  (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +		\
199 71
  (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
200 72
#error "LEMON assertion system is not set properly"
201 73
#endif
202 74

	
203 75
#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
204 76
     (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
205
     (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
206
     (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +	\
207 77
     (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
208 78
     defined(LEMON_ENABLE_ASSERTS)) &&			\
209
  defined(LEMON_DISABLE_ASSERTS)
79
  (defined(LEMON_DISABLE_ASSERTS) ||			\
80
   defined(NDEBUG))
210 81
#error "LEMON assertion system is not set properly"
211 82
#endif
212 83

	
... ...
@@ -217,26 +88,20 @@
217 88
#elif defined LEMON_ASSERT_ABORT
218 89
#  undef LEMON_ASSERT_HANDLER
219 90
#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
220
#elif defined LEMON_ASSERT_ERROR
221
#  undef LEMON_ASSERT_HANDLER
222
#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
223
#elif defined LEMON_ASSERT_EXCEPTION
224
#  undef LEMON_ASSERT_HANDLER
225
#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
226 91
#elif defined LEMON_ASSERT_CUSTOM
227 92
#  undef LEMON_ASSERT_HANDLER
228 93
#  ifndef LEMON_CUSTOM_ASSERT_HANDLER
229 94
#    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
230 95
#  endif
231 96
#  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
232
#elif defined LEMON_ENABLE_ASSERTS
97
#elif defined LEMON_DISABLE_ASSERTS
233 98
#  undef LEMON_ASSERT_HANDLER
99
#elif defined NDEBUG
100
#  undef LEMON_ASSERT_HANDLER
101
#else
234 102
#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
235
#else
236
#  undef LEMON_ASSERT_HANDLER
237 103
#endif
238 104

	
239

	
240 105
#ifndef LEMON_FUNCTION_NAME
241 106
#  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
242 107
#endif
... ...
@@ -247,24 +112,24 @@
247 112
///
248 113
/// \brief Macro for assertion with customizable message
249 114
///
250
/// Macro for assertion with customizable message.  
251
/// \param exp An expression that must be convertible to \c bool.
252
/// If it is \c false, then an assertion is raised. The concrete
253
/// behaviour depends on the settings of the assertion system.
254
/// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
255
/// a <tt>const std::exception&</tt> parameter, which can be used to
256
/// provide information about the circumstances of the failed assertion.
115
/// Macro for assertion with customizable message.  \param exp An
116
/// expression that must be convertible to \c bool.  If it is \c
117
/// false, then an assertion is raised. The concrete behaviour depends
118
/// on the settings of the assertion system.  \param msg A <tt>const
119
/// char*</tt> parameter, which can be used to provide information
120
/// about the circumstances of the failed assertion.
257 121
///
258
/// The assertions are disabled in the default behaviour.
259
/// You can enable them with the following code:
122
/// The assertions are enabled in the default behaviour.
123
/// You can disable them with the following code:
260 124
/// \code
261
/// #define LEMON_ENABLE_ASSERTS
125
/// #define LEMON_DISABLE_ASSERTS
262 126
/// \endcode
263 127
/// or with compilation parameters:
264 128
/// \code
265
/// g++ -DLEMON_ENABLE_ASSERTS
266
/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
129
/// g++ -DLEMON_DISABLE_ASSERTS
130
/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
267 131
/// \endcode
132
/// The checking is also disabled when the standard macro \c NDEBUG is defined.
268 133
/// 
269 134
/// The LEMON assertion system has a wide range of customization
270 135
/// properties. As a default behaviour the failed assertion prints a
... ...
@@ -274,38 +139,22 @@
274 139
///
275 140
/// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
276 141
///   message to the standard error and continues the execution.
277
/// - \c LEMON_ASSERT_ABORT This mode is similar to the
278
///   \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
279
///   behaviour mode when the assertions are enabled with
280
///   \c LEMON_ENABLE_ASSERTS.
281
/// - \c LEMON_ASSERT_ERROR The assertion throws an
282
///   \ref lemon::AssertionFailedError "AssertionFailedError".
283
///   If the \c msg parameter is an exception, then the result of the
284
///   \ref lemon::Exception::what() "what()" member function is passed
285
///   as error message.
286
/// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an
287
///   exception, then it raised directly (solving that the exception
288
///   can not be thrown polymorphically), otherwise an \ref
289
///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
290
///   the given parameters.
142
/// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
143
///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
144
///   behaviour.
291 145
/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
292
///   functions. Three overloaded functions should be defined with the
293
///   following parameter lists:
146
///   function.
294 147
///   \code
295 148
///     void custom_assert_handler(const char* file, int line, const char* function,
296 149
///                                const char* message, const char* assertion);
297
///     void custom_assert_handler(const char* file, int line, const char* function,
298
///                                const std::string& message, const char* assertion);
299
///     void custom_assert_handler(const char* file, int line, const char* function,
300
///                                const std::exception& message, const char* assertion);
301 150
///   \endcode
302
///   The name of the functions should be defined as the \c
151
///   The name of the function should be defined as the \c
303 152
///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
304 153
///   \code
305 154
///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
306 155
///   \endcode
307
///   Whenever an assertion is occured, one of the custom assertion
308
///   handlers is called with appropiate parameters.
156
///   Whenever an assertion is occured, the custom assertion
157
///   handler is called with appropiate parameters.
309 158
///
310 159
/// The assertion mode can also be changed within one compilation unit.
311 160
/// If the macros are redefined with other settings and the
... ...
@@ -315,8 +164,7 @@
315 164
  (static_cast<void> (!!(exp) ? 0 : (					\
316 165
    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
317 166
			 LEMON_FUNCTION_NAME,				\
318
			 msg, #exp), 0)))
319

	
167
			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
320 168

	
321 169
/// \ingroup exceptions
322 170
///
... ...
@@ -327,26 +175,80 @@
327 175
/// \code
328 176
///   LEMON_ASSERT(false, msg);
329 177
/// \endcode
178
///
179
/// \see LEMON_ASSERT 
330 180
#  define LEMON_FIXME(msg)						\
331
       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
332
			     "FIXME: " msg, static_cast<const char*>(0)))
181
  (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
182
			::lemon::_assert_bits::cstringify(msg),		\
183
			static_cast<const char*>(0)))
184

	
185
/// \ingroup exceptions
186
///
187
/// \brief Macro for internal assertions
188
///
189
/// Macro for internal assertions, it is used in the library to check
190
/// the consistency of results of algorithms, several pre- and
191
/// postconditions and invariants. The checking is disabled by
192
/// default, but it can be turned on with the macro \c
193
/// LEMON_ENABLE_DEBUG.
194
/// \code
195
/// #define LEMON_ENABLE_DEBUG
196
/// \endcode
197
/// or with compilation parameters:
198
/// \code
199
/// g++ -DLEMON_ENABLE_DEBUG
200
/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
201
/// \endcode
202
///
203
/// This macro works like the \c LEMON_ASSERT macro, therefore the
204
/// current behaviour depends on the settings of \c LEMON_ASSERT
205
/// macro.
206
///
207
/// \see LEMON_ASSERT 
208
#  define LEMON_DEBUG(exp, msg)						\
209
  (static_cast<void> (!!(exp) ? 0 : (					\
210
    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
211
			 LEMON_FUNCTION_NAME,				\
212
			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
333 213

	
334 214
#else
335 215

	
336 216
#  ifndef LEMON_ASSERT_HANDLER
337 217
#    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
338 218
#    define LEMON_FIXME(msg) (static_cast<void>(0))
219
#    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
339 220
#  else
340
#    define LEMON_ASSERT(exp, msg)                 \
341
       (static_cast<void> (!!(exp) ? 0 : (         \
342
         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
343
                              LEMON_FUNCTION_NAME, \
344
                              msg, #exp), 0)))
345
#    define LEMON_FIXME(msg) \
221
#    define LEMON_ASSERT(exp, msg)					\
222
       (static_cast<void> (!!(exp) ? 0 : (				\
223
        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
224
			     LEMON_FUNCTION_NAME,			\
225
			     ::lemon::_assert_bits::cstringify(msg),	\
226
			     #exp), 0)))
227
#    define LEMON_FIXME(msg)						\
346 228
       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
347
			     "FIXME: " msg,  static_cast<const char*>(0)))
229
			     ::lemon::_assert_bits::cstringify(msg),	\
230
			     static_cast<const char*>(0)))
231

	
232
#    if LEMON_ENABLE_DEBUG
233
#      define LEMON_DEBUG(exp, msg)
234
         (static_cast<void> (!!(exp) ? 0 : (         \
235
           LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
236
                                LEMON_FUNCTION_NAME, \
237
				::lemon::_assert_bits::cstringify(msg),	\
238
				#exp), 0)))
239
#    else
240
#      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
241
#    endif
348 242
#  endif
349 243

	
350 244
#endif
351 245

	
246
#ifdef DOXYGEN
352 247

	
248

	
249
#else
250

	
251

	
252
#endif
253

	
254

	
Ignore white space 6 line context
... ...
@@ -39,165 +39,21 @@
39 39
  LEMON_ASSERT(true, "This is a fault message");
40 40
}
41 41

	
42
void no_assertion_exception_disable() {
43
  LEMON_ASSERT(true, Exception());
44
}
45

	
46 42
void assertion_text_disable() {
47 43
  LEMON_ASSERT(false, "This is a fault message");
48 44
}
49 45

	
50
void assertion_exception_disable() {
51
  LEMON_ASSERT(false, Exception());
52
}
53

	
54 46
void fixme_disable() {
55 47
  LEMON_FIXME("fixme_disable() is fixme!");
56 48
}
57 49

	
58 50
void check_assertion_disable() {
59 51
  no_assertion_text_disable();
60
  no_assertion_exception_disable();
61
  assertion_exception_disable();
62 52
  assertion_text_disable();
63 53
  fixme_disable();
64 54
}
65 55
#undef LEMON_DISABLE_ASSERTS
66 56

	
67

	
68
#define LEMON_ASSERT_ERROR
69
#include <lemon/assert.h>
70

	
71
void no_assertion_text_error() {
72
  LEMON_ASSERT(true, "This is a fault message");
73
}
74

	
75
void no_assertion_exception_error() {
76
  LEMON_ASSERT(true, Exception());
77
}
78

	
79
void assertion_text_error() {
80
  LEMON_ASSERT(false, "This is a fault message");
81
}
82

	
83
void assertion_exception_error() {
84
  LEMON_ASSERT(false, Exception());
85
}
86

	
87
void fixme_error() {
88
  LEMON_FIXME("fixme_error() is fixme!");
89
}
90

	
91
void check_assertion_error() {
92
  no_assertion_text_error();
93
  no_assertion_exception_error();
94
  try {
95
    assertion_exception_error();
96
    check(false, "Assertion error");
97
  } catch (const AssertionFailedError& e) {
98
  }
99

	
100
  try {
101
    assertion_text_error();
102
    check(false, "Assertion error");
103
  } catch (const AssertionFailedError& e) {
104
  }
105

	
106
  try {
107
    fixme_error();
108
    check(false, "Assertion error");
109
  } catch (const AssertionFailedError& e) {
110
  }
111
}
112
#undef LEMON_ASSERT_ERROR
113

	
114
#define LEMON_ASSERT_EXCEPTION
115
#include <lemon/assert.h>
116

	
117
void no_assertion_text_exception() {
118
  LEMON_ASSERT(true, "This is a fault message");
119
}
120

	
121
void no_assertion_exception_exception() {
122
  LEMON_ASSERT(true, Exception());
123
}
124

	
125
void assertion_text_exception() {
126
  LEMON_ASSERT(false, "This is a fault message");
127
}
128

	
129
void assertion_exception_exception() {
130
  LEMON_ASSERT(false, Exception());
131
}
132

	
133
void fixme_exception() {
134
  LEMON_FIXME("fixme_exception() is fixme!");
135
}
136

	
137
void check_assertion_exception() {
138
  no_assertion_text_exception();
139
  no_assertion_exception_exception();
140
  try {
141
    assertion_exception_exception();
142
    check(false, "Assertion error");
143
  } catch (const Exception& e) {
144
  }
145

	
146
  try {
147
    assertion_text_exception();
148
    check(false, "Assertion error");
149
  } catch (const AssertionFailedError& e) {
150
  }
151

	
152
  try {
153
    assertion_text_exception();
154
    check(false, "Assertion error");
155
  } catch (const AssertionFailedError& e) {
156
  }
157

	
158
  try {
159
    fixme_exception();
160
    check(false, "Assertion error");
161
  } catch (const AssertionFailedError& e) {
162
  }
163
}
164
#undef LEMON_ASSERT_EXCEPTION
165

	
166
#define LEMON_ASSERT_LOG
167

	
168
#include <lemon/assert.h>
169

	
170
void no_assertion_text_log() {
171
  LEMON_ASSERT(true, "This is a fault message");
172
}
173

	
174
void no_assertion_exception_log() {
175
  LEMON_ASSERT(true, Exception());
176
}
177

	
178
void assertion_text_log() {
179
  LEMON_ASSERT(false, "This is a fault message");
180
}
181

	
182
void assertion_exception_log() {
183
  LEMON_ASSERT(false, Exception());
184
}
185

	
186
void fixme_log() {
187
  LEMON_FIXME("fixme_log() is fixme!");
188
}
189

	
190
void check_assertion_log() {
191
  no_assertion_text_log();
192
  no_assertion_exception_log();
193
  std::cerr << "The next 3 failure messages are expected: " << std::endl;
194
  assertion_exception_log();
195
  assertion_text_log();
196
  fixme_log();
197
  std::cerr << "End of expected error messages" << std::endl;
198
}
199
#undef LEMON_ASSERT_LOG
200

	
201 57
#define LEMON_ASSERT_CUSTOM
202 58

	
203 59
static int cnt = 0;
... ...
@@ -206,17 +62,6 @@
206 62
  ++cnt;
207 63
}
208 64

	
209
void my_assert_handler(const char*, int, const char*, 
210
		       const std::exception&, const char*) {
211
  ++cnt;
212
}
213

	
214
void my_assert_handler(const char*, int, const char*, 
215
		       const std::string&, const char*) {
216
  ++cnt;
217
}
218

	
219

	
220 65
#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler
221 66
#include <lemon/assert.h>
222 67

	
... ...
@@ -224,29 +69,19 @@
224 69
  LEMON_ASSERT(true, "This is a fault message");
225 70
}
226 71

	
227
void no_assertion_exception_custom() {
228
  LEMON_ASSERT(true, Exception());
229
}
230

	
231 72
void assertion_text_custom() {
232 73
  LEMON_ASSERT(false, "This is a fault message");
233 74
}
234 75

	
235
void assertion_exception_custom() {
236
  LEMON_ASSERT(false, Exception());
237
}
238

	
239 76
void fixme_custom() {
240 77
  LEMON_FIXME("fixme_custom() is fixme!");
241 78
}
242 79

	
243 80
void check_assertion_custom() {
244 81
  no_assertion_text_custom();
245
  no_assertion_exception_custom();
246
  assertion_exception_custom();
247 82
  assertion_text_custom();
248 83
  fixme_custom();
249
  check(cnt == 3, "The custom assert handler does not work");
84
  check(cnt == 2, "The custom assert handler does not work");
250 85
}
251 86

	
252 87
#undef LEMON_ASSERT_CUSTOM
... ...
@@ -254,9 +89,6 @@
254 89

	
255 90
int main() {
256 91
  check_assertion_disable();
257
  check_assertion_error();
258
  check_assertion_exception();
259
  check_assertion_log();
260 92
  check_assertion_custom();
261 93

	
262 94
  return 0;
0 comments (0 inline)