1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsDebug.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,417 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsDebug_h___ 1.10 +#define nsDebug_h___ 1.11 + 1.12 +#include "nscore.h" 1.13 +#include "nsError.h" 1.14 + 1.15 +#include "nsXPCOM.h" 1.16 +#include "mozilla/Assertions.h" 1.17 +#include "mozilla/Likely.h" 1.18 +#include <stdarg.h> 1.19 + 1.20 +#ifdef DEBUG 1.21 +#include "prprf.h" 1.22 +#endif 1.23 + 1.24 +/** 1.25 + * Warn if the given condition is true. The condition is evaluated in both 1.26 + * release and debug builds, and the result is an expression which can be 1.27 + * used in subsequent expressions, such as: 1.28 + * 1.29 + * if (NS_WARN_IF(NS_FAILED(rv)) 1.30 + * return rv; 1.31 + * 1.32 + * This explicit warning and return is preferred to the NS_ENSURE_* macros 1.33 + * which hide the warning and the return control flow. 1.34 + * 1.35 + * @note This is C++-only 1.36 + */ 1.37 +#ifdef __cplusplus 1.38 +#ifdef DEBUG 1.39 +inline bool NS_warn_if_impl(bool condition, const char* expr, const char* file, 1.40 + int32_t line) 1.41 +{ 1.42 + if (MOZ_UNLIKELY(condition)) { 1.43 + NS_DebugBreak(NS_DEBUG_WARNING, nullptr, expr, file, line); 1.44 + } 1.45 + return condition; 1.46 +} 1.47 +#define NS_WARN_IF(condition) \ 1.48 + NS_warn_if_impl(condition, #condition, __FILE__, __LINE__) 1.49 +#else 1.50 +#define NS_WARN_IF(condition) (bool)(condition) 1.51 +#endif 1.52 +#endif 1.53 + 1.54 +/** 1.55 + * Abort the execution of the program if the expression evaluates to 1.56 + * false. 1.57 + * 1.58 + * There is no status value returned from the macro. 1.59 + * 1.60 + * Note that the non-debug version of this macro does <b>not</b> 1.61 + * evaluate the expression argument. Hence side effect statements 1.62 + * as arguments to the macro will yield improper execution in a 1.63 + * non-debug build. For example: 1.64 + * 1.65 + * NS_ABORT_IF_FALSE(0 == foo++, "yikes foo should be zero"); 1.66 + * 1.67 + * Note also that the non-debug version of this macro does <b>not</b> 1.68 + * evaluate the message argument. 1.69 + */ 1.70 +#ifdef DEBUG 1.71 +#define NS_ABORT_IF_FALSE(_expr, _msg) \ 1.72 + do { \ 1.73 + if (!(_expr)) { \ 1.74 + NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_expr, __FILE__, __LINE__); \ 1.75 + } \ 1.76 + } while(0) 1.77 +#else 1.78 +#define NS_ABORT_IF_FALSE(_expr, _msg) do { /* nothing */ } while(0) 1.79 +#endif 1.80 + 1.81 +/** 1.82 + * Warn if a given condition is false. 1.83 + * 1.84 + * Program execution continues past the usage of this macro. 1.85 + * 1.86 + * Note also that the non-debug version of this macro does <b>not</b> 1.87 + * evaluate the message argument. 1.88 + */ 1.89 +#ifdef DEBUG 1.90 +#define NS_WARN_IF_FALSE(_expr,_msg) \ 1.91 + do { \ 1.92 + if (!(_expr)) { \ 1.93 + NS_DebugBreak(NS_DEBUG_WARNING, _msg, #_expr, __FILE__, __LINE__); \ 1.94 + } \ 1.95 + } while(0) 1.96 +#else 1.97 +#define NS_WARN_IF_FALSE(_expr, _msg) do { /* nothing */ } while(0) 1.98 +#endif 1.99 + 1.100 + 1.101 +/** 1.102 + * Test an assertion for truth. If the expression is not true then 1.103 + * trigger a program failure. 1.104 + * 1.105 + * Note that the non-debug version of this macro does <b>not</b> 1.106 + * evaluate the message argument. 1.107 + */ 1.108 +#ifdef DEBUG 1.109 +#define NS_ASSERTION(expr, str) \ 1.110 + do { \ 1.111 + if (!(expr)) { \ 1.112 + NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \ 1.113 + } \ 1.114 + } while(0) 1.115 +#else 1.116 +#define NS_ASSERTION(expr, str) do { /* nothing */ } while(0) 1.117 +#endif 1.118 + 1.119 +/** 1.120 + * NS_PRECONDITION/POSTCONDITION are synonyms for NS_ASSERTION. 1.121 + */ 1.122 +#define NS_PRECONDITION(expr, str) NS_ASSERTION(expr, str) 1.123 +#define NS_POSTCONDITION(expr, str) NS_ASSERTION(expr, str) 1.124 + 1.125 +/** 1.126 + * This macros triggers a program failure if executed. It indicates that 1.127 + * an attempt was made to execute some unimplemented functionality. 1.128 + */ 1.129 +#ifdef DEBUG 1.130 +#define NS_NOTYETIMPLEMENTED(str) \ 1.131 + NS_DebugBreak(NS_DEBUG_ASSERTION, str, "NotYetImplemented", __FILE__, __LINE__) 1.132 +#else 1.133 +#define NS_NOTYETIMPLEMENTED(str) do { /* nothing */ } while(0) 1.134 +#endif 1.135 + 1.136 +/** 1.137 + * This macros triggers a program failure if executed. It indicates that 1.138 + * an attempt was made to execute a codepath which should not be reachable. 1.139 + */ 1.140 +#ifdef DEBUG 1.141 +#define NS_NOTREACHED(str) \ 1.142 + NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Not Reached", __FILE__, __LINE__) 1.143 +#else 1.144 +#define NS_NOTREACHED(str) do { /* nothing */ } while(0) 1.145 +#endif 1.146 + 1.147 +/** 1.148 + * Log an error message. 1.149 + */ 1.150 +#ifdef DEBUG 1.151 +#define NS_ERROR(str) \ 1.152 + NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Error", __FILE__, __LINE__) 1.153 +#else 1.154 +#define NS_ERROR(str) do { /* nothing */ } while(0) 1.155 +#endif 1.156 + 1.157 +/** 1.158 + * Log a warning message. 1.159 + */ 1.160 +#ifdef DEBUG 1.161 +#define NS_WARNING(str) \ 1.162 + NS_DebugBreak(NS_DEBUG_WARNING, str, nullptr, __FILE__, __LINE__) 1.163 +#else 1.164 +#define NS_WARNING(str) do { /* nothing */ } while(0) 1.165 +#endif 1.166 + 1.167 +/** 1.168 + * Trigger an debug-only abort. 1.169 + * 1.170 + * @see NS_RUNTIMEABORT for release-mode asserts. 1.171 + */ 1.172 +#ifdef DEBUG 1.173 +#define NS_ABORT() \ 1.174 + NS_DebugBreak(NS_DEBUG_ABORT, nullptr, nullptr, __FILE__, __LINE__) 1.175 +#else 1.176 +#define NS_ABORT() do { /* nothing */ } while(0) 1.177 +#endif 1.178 + 1.179 +/** 1.180 + * Trigger a debugger breakpoint, only in debug builds. 1.181 + */ 1.182 +#ifdef DEBUG 1.183 +#define NS_BREAK() \ 1.184 + NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, __FILE__, __LINE__) 1.185 +#else 1.186 +#define NS_BREAK() do { /* nothing */ } while(0) 1.187 +#endif 1.188 + 1.189 +/****************************************************************************** 1.190 +** Macros for static assertions. These are used by the sixgill tool. 1.191 +** When the tool is not running these macros are no-ops. 1.192 +******************************************************************************/ 1.193 + 1.194 +/* Avoid name collision if included with other headers defining annotations. */ 1.195 +#ifndef HAVE_STATIC_ANNOTATIONS 1.196 +#define HAVE_STATIC_ANNOTATIONS 1.197 + 1.198 +#ifdef XGILL_PLUGIN 1.199 + 1.200 +#define STATIC_PRECONDITION(COND) __attribute__((precondition(#COND))) 1.201 +#define STATIC_PRECONDITION_ASSUME(COND) __attribute__((precondition_assume(#COND))) 1.202 +#define STATIC_POSTCONDITION(COND) __attribute__((postcondition(#COND))) 1.203 +#define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND))) 1.204 +#define STATIC_INVARIANT(COND) __attribute__((invariant(#COND))) 1.205 +#define STATIC_INVARIANT_ASSUME(COND) __attribute__((invariant_assume(#COND))) 1.206 + 1.207 +/* Used to make identifiers for assert/assume annotations in a function. */ 1.208 +#define STATIC_PASTE2(X,Y) X ## Y 1.209 +#define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y) 1.210 + 1.211 +#define STATIC_ASSERT(COND) \ 1.212 + do { \ 1.213 + __attribute__((assert_static(#COND), unused)) \ 1.214 + int STATIC_PASTE1(assert_static_, __COUNTER__); \ 1.215 + } while(0) 1.216 + 1.217 +#define STATIC_ASSUME(COND) \ 1.218 + do { \ 1.219 + __attribute__((assume_static(#COND), unused)) \ 1.220 + int STATIC_PASTE1(assume_static_, __COUNTER__); \ 1.221 + } while(0) 1.222 + 1.223 +#define STATIC_ASSERT_RUNTIME(COND) \ 1.224 + do { \ 1.225 + __attribute__((assert_static_runtime(#COND), unused)) \ 1.226 + int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \ 1.227 + } while(0) 1.228 + 1.229 +#else /* XGILL_PLUGIN */ 1.230 + 1.231 +#define STATIC_PRECONDITION(COND) /* nothing */ 1.232 +#define STATIC_PRECONDITION_ASSUME(COND) /* nothing */ 1.233 +#define STATIC_POSTCONDITION(COND) /* nothing */ 1.234 +#define STATIC_POSTCONDITION_ASSUME(COND) /* nothing */ 1.235 +#define STATIC_INVARIANT(COND) /* nothing */ 1.236 +#define STATIC_INVARIANT_ASSUME(COND) /* nothing */ 1.237 + 1.238 +#define STATIC_ASSERT(COND) do { /* nothing */ } while(0) 1.239 +#define STATIC_ASSUME(COND) do { /* nothing */ } while(0) 1.240 +#define STATIC_ASSERT_RUNTIME(COND) do { /* nothing */ } while(0) 1.241 + 1.242 +#endif /* XGILL_PLUGIN */ 1.243 + 1.244 +#define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference()) 1.245 + 1.246 +#endif /* HAVE_STATIC_ANNOTATIONS */ 1.247 + 1.248 +#ifdef XGILL_PLUGIN 1.249 + 1.250 +/* Redefine runtime assertion macros to perform static assertions, for both 1.251 + * debug and release builds. Don't include the original runtime assertions; 1.252 + * this ensures the tool will consider cases where the assertion fails. */ 1.253 + 1.254 +#undef NS_PRECONDITION 1.255 +#undef NS_ASSERTION 1.256 +#undef NS_POSTCONDITION 1.257 + 1.258 +#define NS_PRECONDITION(expr, str) STATIC_ASSERT_RUNTIME(expr) 1.259 +#define NS_ASSERTION(expr, str) STATIC_ASSERT_RUNTIME(expr) 1.260 +#define NS_POSTCONDITION(expr, str) STATIC_ASSERT_RUNTIME(expr) 1.261 + 1.262 +#endif /* XGILL_PLUGIN */ 1.263 + 1.264 +/****************************************************************************** 1.265 +** Macros for terminating execution when an unrecoverable condition is 1.266 +** reached. These need to be compiled regardless of the DEBUG flag. 1.267 +******************************************************************************/ 1.268 + 1.269 +/** 1.270 + * Terminate execution <i>immediately</i>, and if possible on the current 1.271 + * platform, in such a way that execution can't be continued by other 1.272 + * code (e.g., by intercepting a signal). 1.273 + */ 1.274 +#define NS_RUNTIMEABORT(msg) \ 1.275 + NS_DebugBreak(NS_DEBUG_ABORT, msg, nullptr, __FILE__, __LINE__) 1.276 + 1.277 + 1.278 +/* Macros for checking the trueness of an expression passed in within an 1.279 + * interface implementation. These need to be compiled regardless of the 1.280 + * DEBUG flag. New code should use NS_WARN_IF(condition) instead! 1.281 + * @status deprecated 1.282 + */ 1.283 + 1.284 +#define NS_ENSURE_TRUE(x, ret) \ 1.285 + do { \ 1.286 + if (MOZ_UNLIKELY(!(x))) { \ 1.287 + NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \ 1.288 + return ret; \ 1.289 + } \ 1.290 + } while(0) 1.291 + 1.292 +#define NS_ENSURE_FALSE(x, ret) \ 1.293 + NS_ENSURE_TRUE(!(x), ret) 1.294 + 1.295 +#define NS_ENSURE_TRUE_VOID(x) \ 1.296 + do { \ 1.297 + if (MOZ_UNLIKELY(!(x))) { \ 1.298 + NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \ 1.299 + return; \ 1.300 + } \ 1.301 + } while(0) 1.302 + 1.303 +#define NS_ENSURE_FALSE_VOID(x) \ 1.304 + NS_ENSURE_TRUE_VOID(!(x)) 1.305 + 1.306 +/****************************************************************************** 1.307 +** Macros for checking results 1.308 +******************************************************************************/ 1.309 + 1.310 +#if defined(DEBUG) && !defined(XPCOM_GLUE_AVOID_NSPR) 1.311 + 1.312 +#define NS_ENSURE_SUCCESS_BODY(res, ret) \ 1.313 + char *msg = PR_smprintf("NS_ENSURE_SUCCESS(%s, %s) failed with " \ 1.314 + "result 0x%X", #res, #ret, __rv); \ 1.315 + NS_WARNING(msg); \ 1.316 + PR_smprintf_free(msg); 1.317 + 1.318 +#define NS_ENSURE_SUCCESS_BODY_VOID(res) \ 1.319 + char *msg = PR_smprintf("NS_ENSURE_SUCCESS_VOID(%s) failed with " \ 1.320 + "result 0x%X", #res, __rv); \ 1.321 + NS_WARNING(msg); \ 1.322 + PR_smprintf_free(msg); 1.323 + 1.324 +#else 1.325 + 1.326 +#define NS_ENSURE_SUCCESS_BODY(res, ret) \ 1.327 + NS_WARNING("NS_ENSURE_SUCCESS(" #res ", " #ret ") failed"); 1.328 + 1.329 +#define NS_ENSURE_SUCCESS_BODY_VOID(res) \ 1.330 + NS_WARNING("NS_ENSURE_SUCCESS_VOID(" #res ") failed"); 1.331 + 1.332 +#endif 1.333 + 1.334 +#define NS_ENSURE_SUCCESS(res, ret) \ 1.335 + do { \ 1.336 + nsresult __rv = res; /* Don't evaluate |res| more than once */ \ 1.337 + if (NS_FAILED(__rv)) { \ 1.338 + NS_ENSURE_SUCCESS_BODY(res, ret) \ 1.339 + return ret; \ 1.340 + } \ 1.341 + } while(0) 1.342 + 1.343 +#define NS_ENSURE_SUCCESS_VOID(res) \ 1.344 + do { \ 1.345 + nsresult __rv = res; \ 1.346 + if (NS_FAILED(__rv)) { \ 1.347 + NS_ENSURE_SUCCESS_BODY_VOID(res) \ 1.348 + return; \ 1.349 + } \ 1.350 + } while(0) 1.351 + 1.352 +/****************************************************************************** 1.353 +** Macros for checking state and arguments upon entering interface boundaries 1.354 +******************************************************************************/ 1.355 + 1.356 +#define NS_ENSURE_ARG(arg) \ 1.357 + NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG) 1.358 + 1.359 +#define NS_ENSURE_ARG_POINTER(arg) \ 1.360 + NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER) 1.361 + 1.362 +#define NS_ENSURE_ARG_MIN(arg, min) \ 1.363 + NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG) 1.364 + 1.365 +#define NS_ENSURE_ARG_MAX(arg, max) \ 1.366 + NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG) 1.367 + 1.368 +#define NS_ENSURE_ARG_RANGE(arg, min, max) \ 1.369 + NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG) 1.370 + 1.371 +#define NS_ENSURE_STATE(state) \ 1.372 + NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED) 1.373 + 1.374 +#define NS_ENSURE_NO_AGGREGATION(outer) \ 1.375 + NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION) 1.376 + 1.377 +/*****************************************************************************/ 1.378 + 1.379 +#ifdef XPCOM_GLUE 1.380 + #define NS_CheckThreadSafe(owningThread, msg) 1.381 +#else 1.382 + #define NS_CheckThreadSafe(owningThread, msg) \ 1.383 + if (MOZ_UNLIKELY(owningThread != PR_GetCurrentThread())) { \ 1.384 + MOZ_CRASH(msg); \ 1.385 + } 1.386 +#endif 1.387 + 1.388 +#ifdef MOZILLA_INTERNAL_API 1.389 +void NS_ABORT_OOM(size_t size); 1.390 +#else 1.391 +inline void NS_ABORT_OOM(size_t) 1.392 +{ 1.393 + MOZ_CRASH(); 1.394 +} 1.395 +#endif 1.396 + 1.397 +/* When compiling the XPCOM Glue on Windows, we pretend that it's going to 1.398 + * be linked with a static CRT (-MT) even when it's not. This means that we 1.399 + * cannot link to data exports from the CRT, only function exports. So, 1.400 + * instead of referencing "stderr" directly, use fdopen. 1.401 + */ 1.402 +#ifdef __cplusplus 1.403 +extern "C" { 1.404 +#endif 1.405 + 1.406 +NS_COM_GLUE void 1.407 +printf_stderr(const char *fmt, ...); 1.408 + 1.409 +NS_COM_GLUE void 1.410 +vprintf_stderr(const char *fmt, va_list args); 1.411 + 1.412 +// fprintf with special handling for stderr to print to the console 1.413 +NS_COM_GLUE void 1.414 +fprintf_stderr(FILE* aFile, const char *fmt, ...); 1.415 + 1.416 +#ifdef __cplusplus 1.417 +} 1.418 +#endif 1.419 + 1.420 +#endif /* nsDebug_h___ */