xpcom/glue/nsDebug.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:478eb66c7268
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #ifndef nsDebug_h___
7 #define nsDebug_h___
8
9 #include "nscore.h"
10 #include "nsError.h"
11
12 #include "nsXPCOM.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/Likely.h"
15 #include <stdarg.h>
16
17 #ifdef DEBUG
18 #include "prprf.h"
19 #endif
20
21 /**
22 * Warn if the given condition is true. The condition is evaluated in both
23 * release and debug builds, and the result is an expression which can be
24 * used in subsequent expressions, such as:
25 *
26 * if (NS_WARN_IF(NS_FAILED(rv))
27 * return rv;
28 *
29 * This explicit warning and return is preferred to the NS_ENSURE_* macros
30 * which hide the warning and the return control flow.
31 *
32 * @note This is C++-only
33 */
34 #ifdef __cplusplus
35 #ifdef DEBUG
36 inline bool NS_warn_if_impl(bool condition, const char* expr, const char* file,
37 int32_t line)
38 {
39 if (MOZ_UNLIKELY(condition)) {
40 NS_DebugBreak(NS_DEBUG_WARNING, nullptr, expr, file, line);
41 }
42 return condition;
43 }
44 #define NS_WARN_IF(condition) \
45 NS_warn_if_impl(condition, #condition, __FILE__, __LINE__)
46 #else
47 #define NS_WARN_IF(condition) (bool)(condition)
48 #endif
49 #endif
50
51 /**
52 * Abort the execution of the program if the expression evaluates to
53 * false.
54 *
55 * There is no status value returned from the macro.
56 *
57 * Note that the non-debug version of this macro does <b>not</b>
58 * evaluate the expression argument. Hence side effect statements
59 * as arguments to the macro will yield improper execution in a
60 * non-debug build. For example:
61 *
62 * NS_ABORT_IF_FALSE(0 == foo++, "yikes foo should be zero");
63 *
64 * Note also that the non-debug version of this macro does <b>not</b>
65 * evaluate the message argument.
66 */
67 #ifdef DEBUG
68 #define NS_ABORT_IF_FALSE(_expr, _msg) \
69 do { \
70 if (!(_expr)) { \
71 NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_expr, __FILE__, __LINE__); \
72 } \
73 } while(0)
74 #else
75 #define NS_ABORT_IF_FALSE(_expr, _msg) do { /* nothing */ } while(0)
76 #endif
77
78 /**
79 * Warn if a given condition is false.
80 *
81 * Program execution continues past the usage of this macro.
82 *
83 * Note also that the non-debug version of this macro does <b>not</b>
84 * evaluate the message argument.
85 */
86 #ifdef DEBUG
87 #define NS_WARN_IF_FALSE(_expr,_msg) \
88 do { \
89 if (!(_expr)) { \
90 NS_DebugBreak(NS_DEBUG_WARNING, _msg, #_expr, __FILE__, __LINE__); \
91 } \
92 } while(0)
93 #else
94 #define NS_WARN_IF_FALSE(_expr, _msg) do { /* nothing */ } while(0)
95 #endif
96
97
98 /**
99 * Test an assertion for truth. If the expression is not true then
100 * trigger a program failure.
101 *
102 * Note that the non-debug version of this macro does <b>not</b>
103 * evaluate the message argument.
104 */
105 #ifdef DEBUG
106 #define NS_ASSERTION(expr, str) \
107 do { \
108 if (!(expr)) { \
109 NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
110 } \
111 } while(0)
112 #else
113 #define NS_ASSERTION(expr, str) do { /* nothing */ } while(0)
114 #endif
115
116 /**
117 * NS_PRECONDITION/POSTCONDITION are synonyms for NS_ASSERTION.
118 */
119 #define NS_PRECONDITION(expr, str) NS_ASSERTION(expr, str)
120 #define NS_POSTCONDITION(expr, str) NS_ASSERTION(expr, str)
121
122 /**
123 * This macros triggers a program failure if executed. It indicates that
124 * an attempt was made to execute some unimplemented functionality.
125 */
126 #ifdef DEBUG
127 #define NS_NOTYETIMPLEMENTED(str) \
128 NS_DebugBreak(NS_DEBUG_ASSERTION, str, "NotYetImplemented", __FILE__, __LINE__)
129 #else
130 #define NS_NOTYETIMPLEMENTED(str) do { /* nothing */ } while(0)
131 #endif
132
133 /**
134 * This macros triggers a program failure if executed. It indicates that
135 * an attempt was made to execute a codepath which should not be reachable.
136 */
137 #ifdef DEBUG
138 #define NS_NOTREACHED(str) \
139 NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Not Reached", __FILE__, __LINE__)
140 #else
141 #define NS_NOTREACHED(str) do { /* nothing */ } while(0)
142 #endif
143
144 /**
145 * Log an error message.
146 */
147 #ifdef DEBUG
148 #define NS_ERROR(str) \
149 NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Error", __FILE__, __LINE__)
150 #else
151 #define NS_ERROR(str) do { /* nothing */ } while(0)
152 #endif
153
154 /**
155 * Log a warning message.
156 */
157 #ifdef DEBUG
158 #define NS_WARNING(str) \
159 NS_DebugBreak(NS_DEBUG_WARNING, str, nullptr, __FILE__, __LINE__)
160 #else
161 #define NS_WARNING(str) do { /* nothing */ } while(0)
162 #endif
163
164 /**
165 * Trigger an debug-only abort.
166 *
167 * @see NS_RUNTIMEABORT for release-mode asserts.
168 */
169 #ifdef DEBUG
170 #define NS_ABORT() \
171 NS_DebugBreak(NS_DEBUG_ABORT, nullptr, nullptr, __FILE__, __LINE__)
172 #else
173 #define NS_ABORT() do { /* nothing */ } while(0)
174 #endif
175
176 /**
177 * Trigger a debugger breakpoint, only in debug builds.
178 */
179 #ifdef DEBUG
180 #define NS_BREAK() \
181 NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, __FILE__, __LINE__)
182 #else
183 #define NS_BREAK() do { /* nothing */ } while(0)
184 #endif
185
186 /******************************************************************************
187 ** Macros for static assertions. These are used by the sixgill tool.
188 ** When the tool is not running these macros are no-ops.
189 ******************************************************************************/
190
191 /* Avoid name collision if included with other headers defining annotations. */
192 #ifndef HAVE_STATIC_ANNOTATIONS
193 #define HAVE_STATIC_ANNOTATIONS
194
195 #ifdef XGILL_PLUGIN
196
197 #define STATIC_PRECONDITION(COND) __attribute__((precondition(#COND)))
198 #define STATIC_PRECONDITION_ASSUME(COND) __attribute__((precondition_assume(#COND)))
199 #define STATIC_POSTCONDITION(COND) __attribute__((postcondition(#COND)))
200 #define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
201 #define STATIC_INVARIANT(COND) __attribute__((invariant(#COND)))
202 #define STATIC_INVARIANT_ASSUME(COND) __attribute__((invariant_assume(#COND)))
203
204 /* Used to make identifiers for assert/assume annotations in a function. */
205 #define STATIC_PASTE2(X,Y) X ## Y
206 #define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
207
208 #define STATIC_ASSERT(COND) \
209 do { \
210 __attribute__((assert_static(#COND), unused)) \
211 int STATIC_PASTE1(assert_static_, __COUNTER__); \
212 } while(0)
213
214 #define STATIC_ASSUME(COND) \
215 do { \
216 __attribute__((assume_static(#COND), unused)) \
217 int STATIC_PASTE1(assume_static_, __COUNTER__); \
218 } while(0)
219
220 #define STATIC_ASSERT_RUNTIME(COND) \
221 do { \
222 __attribute__((assert_static_runtime(#COND), unused)) \
223 int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
224 } while(0)
225
226 #else /* XGILL_PLUGIN */
227
228 #define STATIC_PRECONDITION(COND) /* nothing */
229 #define STATIC_PRECONDITION_ASSUME(COND) /* nothing */
230 #define STATIC_POSTCONDITION(COND) /* nothing */
231 #define STATIC_POSTCONDITION_ASSUME(COND) /* nothing */
232 #define STATIC_INVARIANT(COND) /* nothing */
233 #define STATIC_INVARIANT_ASSUME(COND) /* nothing */
234
235 #define STATIC_ASSERT(COND) do { /* nothing */ } while(0)
236 #define STATIC_ASSUME(COND) do { /* nothing */ } while(0)
237 #define STATIC_ASSERT_RUNTIME(COND) do { /* nothing */ } while(0)
238
239 #endif /* XGILL_PLUGIN */
240
241 #define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
242
243 #endif /* HAVE_STATIC_ANNOTATIONS */
244
245 #ifdef XGILL_PLUGIN
246
247 /* Redefine runtime assertion macros to perform static assertions, for both
248 * debug and release builds. Don't include the original runtime assertions;
249 * this ensures the tool will consider cases where the assertion fails. */
250
251 #undef NS_PRECONDITION
252 #undef NS_ASSERTION
253 #undef NS_POSTCONDITION
254
255 #define NS_PRECONDITION(expr, str) STATIC_ASSERT_RUNTIME(expr)
256 #define NS_ASSERTION(expr, str) STATIC_ASSERT_RUNTIME(expr)
257 #define NS_POSTCONDITION(expr, str) STATIC_ASSERT_RUNTIME(expr)
258
259 #endif /* XGILL_PLUGIN */
260
261 /******************************************************************************
262 ** Macros for terminating execution when an unrecoverable condition is
263 ** reached. These need to be compiled regardless of the DEBUG flag.
264 ******************************************************************************/
265
266 /**
267 * Terminate execution <i>immediately</i>, and if possible on the current
268 * platform, in such a way that execution can't be continued by other
269 * code (e.g., by intercepting a signal).
270 */
271 #define NS_RUNTIMEABORT(msg) \
272 NS_DebugBreak(NS_DEBUG_ABORT, msg, nullptr, __FILE__, __LINE__)
273
274
275 /* Macros for checking the trueness of an expression passed in within an
276 * interface implementation. These need to be compiled regardless of the
277 * DEBUG flag. New code should use NS_WARN_IF(condition) instead!
278 * @status deprecated
279 */
280
281 #define NS_ENSURE_TRUE(x, ret) \
282 do { \
283 if (MOZ_UNLIKELY(!(x))) { \
284 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
285 return ret; \
286 } \
287 } while(0)
288
289 #define NS_ENSURE_FALSE(x, ret) \
290 NS_ENSURE_TRUE(!(x), ret)
291
292 #define NS_ENSURE_TRUE_VOID(x) \
293 do { \
294 if (MOZ_UNLIKELY(!(x))) { \
295 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
296 return; \
297 } \
298 } while(0)
299
300 #define NS_ENSURE_FALSE_VOID(x) \
301 NS_ENSURE_TRUE_VOID(!(x))
302
303 /******************************************************************************
304 ** Macros for checking results
305 ******************************************************************************/
306
307 #if defined(DEBUG) && !defined(XPCOM_GLUE_AVOID_NSPR)
308
309 #define NS_ENSURE_SUCCESS_BODY(res, ret) \
310 char *msg = PR_smprintf("NS_ENSURE_SUCCESS(%s, %s) failed with " \
311 "result 0x%X", #res, #ret, __rv); \
312 NS_WARNING(msg); \
313 PR_smprintf_free(msg);
314
315 #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
316 char *msg = PR_smprintf("NS_ENSURE_SUCCESS_VOID(%s) failed with " \
317 "result 0x%X", #res, __rv); \
318 NS_WARNING(msg); \
319 PR_smprintf_free(msg);
320
321 #else
322
323 #define NS_ENSURE_SUCCESS_BODY(res, ret) \
324 NS_WARNING("NS_ENSURE_SUCCESS(" #res ", " #ret ") failed");
325
326 #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
327 NS_WARNING("NS_ENSURE_SUCCESS_VOID(" #res ") failed");
328
329 #endif
330
331 #define NS_ENSURE_SUCCESS(res, ret) \
332 do { \
333 nsresult __rv = res; /* Don't evaluate |res| more than once */ \
334 if (NS_FAILED(__rv)) { \
335 NS_ENSURE_SUCCESS_BODY(res, ret) \
336 return ret; \
337 } \
338 } while(0)
339
340 #define NS_ENSURE_SUCCESS_VOID(res) \
341 do { \
342 nsresult __rv = res; \
343 if (NS_FAILED(__rv)) { \
344 NS_ENSURE_SUCCESS_BODY_VOID(res) \
345 return; \
346 } \
347 } while(0)
348
349 /******************************************************************************
350 ** Macros for checking state and arguments upon entering interface boundaries
351 ******************************************************************************/
352
353 #define NS_ENSURE_ARG(arg) \
354 NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG)
355
356 #define NS_ENSURE_ARG_POINTER(arg) \
357 NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER)
358
359 #define NS_ENSURE_ARG_MIN(arg, min) \
360 NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG)
361
362 #define NS_ENSURE_ARG_MAX(arg, max) \
363 NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG)
364
365 #define NS_ENSURE_ARG_RANGE(arg, min, max) \
366 NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG)
367
368 #define NS_ENSURE_STATE(state) \
369 NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED)
370
371 #define NS_ENSURE_NO_AGGREGATION(outer) \
372 NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION)
373
374 /*****************************************************************************/
375
376 #ifdef XPCOM_GLUE
377 #define NS_CheckThreadSafe(owningThread, msg)
378 #else
379 #define NS_CheckThreadSafe(owningThread, msg) \
380 if (MOZ_UNLIKELY(owningThread != PR_GetCurrentThread())) { \
381 MOZ_CRASH(msg); \
382 }
383 #endif
384
385 #ifdef MOZILLA_INTERNAL_API
386 void NS_ABORT_OOM(size_t size);
387 #else
388 inline void NS_ABORT_OOM(size_t)
389 {
390 MOZ_CRASH();
391 }
392 #endif
393
394 /* When compiling the XPCOM Glue on Windows, we pretend that it's going to
395 * be linked with a static CRT (-MT) even when it's not. This means that we
396 * cannot link to data exports from the CRT, only function exports. So,
397 * instead of referencing "stderr" directly, use fdopen.
398 */
399 #ifdef __cplusplus
400 extern "C" {
401 #endif
402
403 NS_COM_GLUE void
404 printf_stderr(const char *fmt, ...);
405
406 NS_COM_GLUE void
407 vprintf_stderr(const char *fmt, va_list args);
408
409 // fprintf with special handling for stderr to print to the console
410 NS_COM_GLUE void
411 fprintf_stderr(FILE* aFile, const char *fmt, ...);
412
413 #ifdef __cplusplus
414 }
415 #endif
416
417 #endif /* nsDebug_h___ */

mercurial