123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef nsDebug_h___
- #define nsDebug_h___
- #include "nscore.h"
- #include "nsError.h"
- #include "nsXPCOM.h"
- #include "mozilla/Assertions.h"
- #include "mozilla/Likely.h"
- #include <stdarg.h>
- #ifdef DEBUG
- #include "prprf.h"
- #endif
- /**
- * Warn if the given condition is true. The condition is evaluated in both
- * release and debug builds, and the result is an expression which can be
- * used in subsequent expressions, such as:
- *
- * if (NS_WARN_IF(NS_FAILED(rv)) {
- * return rv;
- * }
- *
- * This explicit warning and return is preferred to the NS_ENSURE_* macros
- * which hide the warning and the return control flow.
- *
- * This macro can also be used outside of conditions just to issue a warning,
- * like so:
- *
- * Unused << NS_WARN_IF(NS_FAILED(FnWithSideEffects());
- *
- * (The |Unused <<| is necessary because of the MOZ_MUST_USE annotation.)
- *
- * However, note that the argument to this macro is evaluated in all builds. If
- * you just want a warning assertion, it is better to use NS_WARNING_ASSERTION
- * (which evaluates the condition only in debug builds) like so:
- *
- * NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "operation failed");
- *
- * @note This is C++-only
- */
- #ifdef __cplusplus
- #ifdef DEBUG
- inline MOZ_MUST_USE bool NS_warn_if_impl(bool aCondition, const char* aExpr,
- const char* aFile, int32_t aLine)
- {
- if (MOZ_UNLIKELY(aCondition)) {
- NS_DebugBreak(NS_DEBUG_WARNING, nullptr, aExpr, aFile, aLine);
- }
- return aCondition;
- }
- #define NS_WARN_IF(condition) \
- NS_warn_if_impl(condition, #condition, __FILE__, __LINE__)
- #else
- #define NS_WARN_IF(condition) (bool)(condition)
- #endif
- #endif
- /**
- * Test an assertion for truth. If the expression is not true then
- * emit a warning.
- *
- * Program execution continues past the usage of this macro.
- *
- * Note also that the non-debug version of this macro does <b>not</b>
- * evaluate the message argument.
- */
- #ifdef DEBUG
- #define NS_WARNING_ASSERTION(_expr, _msg) \
- do { \
- if (!(_expr)) { \
- NS_DebugBreak(NS_DEBUG_WARNING, _msg, #_expr, __FILE__, __LINE__); \
- } \
- } while(0)
- #else
- #define NS_WARNING_ASSERTION(_expr, _msg) do { /* nothing */ } while(0)
- #endif
- /**
- * Test an assertion for truth. If the expression is not true then
- * trigger a program failure.
- *
- * Note that the non-debug version of this macro does <b>not</b>
- * evaluate the message argument.
- */
- #ifdef DEBUG
- inline void MOZ_PretendNoReturn()
- MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS {}
- #define NS_ASSERTION(expr, str) \
- do { \
- if (!(expr)) { \
- NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } \
- } while(0)
- #else
- #define NS_ASSERTION(expr, str) do { /* nothing */ } while(0)
- #endif
- /**
- * NS_PRECONDITION/POSTCONDITION are synonyms for NS_ASSERTION.
- */
- #define NS_PRECONDITION(expr, str) NS_ASSERTION(expr, str)
- #define NS_POSTCONDITION(expr, str) NS_ASSERTION(expr, str)
- /**
- * This macros triggers a program failure if executed. It indicates that
- * an attempt was made to execute some unimplemented functionality.
- */
- #ifdef DEBUG
- #define NS_NOTYETIMPLEMENTED(str) \
- do { \
- NS_DebugBreak(NS_DEBUG_ASSERTION, str, "NotYetImplemented", __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } while(0)
- #else
- #define NS_NOTYETIMPLEMENTED(str) do { /* nothing */ } while(0)
- #endif
- /**
- * This macros triggers a program failure if executed. It indicates that
- * an attempt was made to execute a codepath which should not be reachable.
- */
- #ifdef DEBUG
- #define NS_NOTREACHED(str) \
- do { \
- NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Not Reached", __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } while(0)
- #else
- #define NS_NOTREACHED(str) do { /* nothing */ } while(0)
- #endif
- /**
- * Log an error message.
- */
- #ifdef DEBUG
- #define NS_ERROR(str) \
- do { \
- NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Error", __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } while(0)
- #else
- #define NS_ERROR(str) do { /* nothing */ } while(0)
- #endif
- /**
- * Log a warning message.
- */
- #ifdef DEBUG
- #define NS_WARNING(str) \
- NS_DebugBreak(NS_DEBUG_WARNING, str, nullptr, __FILE__, __LINE__)
- #else
- #define NS_WARNING(str) do { /* nothing */ } while(0)
- #endif
- /**
- * Trigger an debug-only abort.
- *
- * @see NS_RUNTIMEABORT for release-mode asserts.
- */
- #ifdef DEBUG
- #define NS_ABORT() \
- do { \
- NS_DebugBreak(NS_DEBUG_ABORT, nullptr, nullptr, __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } while(0)
- #else
- #define NS_ABORT() do { /* nothing */ } while(0)
- #endif
- /**
- * Trigger a debugger breakpoint, only in debug builds.
- */
- #ifdef DEBUG
- #define NS_BREAK() \
- do { \
- NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, __FILE__, __LINE__); \
- MOZ_PretendNoReturn(); \
- } while(0)
- #else
- #define NS_BREAK() do { /* nothing */ } while(0)
- #endif
- /******************************************************************************
- ** Macros for static assertions. These are used by the sixgill tool.
- ** When the tool is not running these macros are no-ops.
- ******************************************************************************/
- /* Avoid name collision if included with other headers defining annotations. */
- #ifndef HAVE_STATIC_ANNOTATIONS
- #define HAVE_STATIC_ANNOTATIONS
- #ifdef XGILL_PLUGIN
- #define STATIC_PRECONDITION(COND) __attribute__((precondition(#COND)))
- #define STATIC_PRECONDITION_ASSUME(COND) __attribute__((precondition_assume(#COND)))
- #define STATIC_POSTCONDITION(COND) __attribute__((postcondition(#COND)))
- #define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
- #define STATIC_INVARIANT(COND) __attribute__((invariant(#COND)))
- #define STATIC_INVARIANT_ASSUME(COND) __attribute__((invariant_assume(#COND)))
- /* Used to make identifiers for assert/assume annotations in a function. */
- #define STATIC_PASTE2(X,Y) X ## Y
- #define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
- #define STATIC_ASSUME(COND) \
- do { \
- __attribute__((assume_static(#COND), unused)) \
- int STATIC_PASTE1(assume_static_, __COUNTER__); \
- } while(0)
- #define STATIC_ASSERT_RUNTIME(COND) \
- do { \
- __attribute__((assert_static_runtime(#COND), unused)) \
- int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
- } while(0)
- #else /* XGILL_PLUGIN */
- #define STATIC_PRECONDITION(COND) /* nothing */
- #define STATIC_PRECONDITION_ASSUME(COND) /* nothing */
- #define STATIC_POSTCONDITION(COND) /* nothing */
- #define STATIC_POSTCONDITION_ASSUME(COND) /* nothing */
- #define STATIC_INVARIANT(COND) /* nothing */
- #define STATIC_INVARIANT_ASSUME(COND) /* nothing */
- #define STATIC_ASSUME(COND) do { /* nothing */ } while(0)
- #define STATIC_ASSERT_RUNTIME(COND) do { /* nothing */ } while(0)
- #endif /* XGILL_PLUGIN */
- #define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
- #endif /* HAVE_STATIC_ANNOTATIONS */
- /******************************************************************************
- ** Macros for terminating execution when an unrecoverable condition is
- ** reached. These need to be compiled regardless of the DEBUG flag.
- ******************************************************************************/
- /**
- * Terminate execution <i>immediately</i>, and if possible on the current
- * platform, in such a way that execution can't be continued by other
- * code (e.g., by intercepting a signal).
- */
- #define NS_RUNTIMEABORT(msg) \
- NS_DebugBreak(NS_DEBUG_ABORT, msg, nullptr, __FILE__, __LINE__)
- /* Macros for checking the trueness of an expression passed in within an
- * interface implementation. These need to be compiled regardless of the
- * DEBUG flag. New code should use NS_WARN_IF(condition) instead!
- * @status deprecated
- */
- #define NS_ENSURE_TRUE(x, ret) \
- do { \
- if (MOZ_UNLIKELY(!(x))) { \
- NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
- return ret; \
- } \
- } while(0)
- #define NS_ENSURE_FALSE(x, ret) \
- NS_ENSURE_TRUE(!(x), ret)
- #define NS_ENSURE_TRUE_VOID(x) \
- do { \
- if (MOZ_UNLIKELY(!(x))) { \
- NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
- return; \
- } \
- } while(0)
- #define NS_ENSURE_FALSE_VOID(x) \
- NS_ENSURE_TRUE_VOID(!(x))
- /******************************************************************************
- ** Macros for checking results
- ******************************************************************************/
- #if defined(DEBUG) && !defined(XPCOM_GLUE_AVOID_NSPR)
- #define NS_ENSURE_SUCCESS_BODY(res, ret) \
- char *msg = PR_smprintf("NS_ENSURE_SUCCESS(%s, %s) failed with " \
- "result 0x%X", #res, #ret, __rv); \
- NS_WARNING(msg); \
- PR_smprintf_free(msg);
- #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
- char *msg = PR_smprintf("NS_ENSURE_SUCCESS_VOID(%s) failed with " \
- "result 0x%X", #res, __rv); \
- NS_WARNING(msg); \
- PR_smprintf_free(msg);
- #else
- #define NS_ENSURE_SUCCESS_BODY(res, ret) \
- NS_WARNING("NS_ENSURE_SUCCESS(" #res ", " #ret ") failed");
- #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
- NS_WARNING("NS_ENSURE_SUCCESS_VOID(" #res ") failed");
- #endif
- #define NS_ENSURE_SUCCESS(res, ret) \
- do { \
- nsresult __rv = res; /* Don't evaluate |res| more than once */ \
- if (NS_FAILED(__rv)) { \
- NS_ENSURE_SUCCESS_BODY(res, ret) \
- return ret; \
- } \
- } while(0)
- #define NS_ENSURE_SUCCESS_VOID(res) \
- do { \
- nsresult __rv = res; \
- if (NS_FAILED(__rv)) { \
- NS_ENSURE_SUCCESS_BODY_VOID(res) \
- return; \
- } \
- } while(0)
- /******************************************************************************
- ** Macros for checking state and arguments upon entering interface boundaries
- ******************************************************************************/
- #define NS_ENSURE_ARG(arg) \
- NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG)
- #define NS_ENSURE_ARG_POINTER(arg) \
- NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER)
- #define NS_ENSURE_ARG_MIN(arg, min) \
- NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG)
- #define NS_ENSURE_ARG_MAX(arg, max) \
- NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG)
- #define NS_ENSURE_ARG_RANGE(arg, min, max) \
- NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG)
- #define NS_ENSURE_STATE(state) \
- NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED)
- #define NS_ENSURE_NO_AGGREGATION(outer) \
- NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION)
- /*****************************************************************************/
- #if (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING))) && !defined(XPCOM_GLUE_AVOID_NSPR)
- #define MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED 1
- #endif
- #ifdef XPCOM_GLUE
- #define NS_CheckThreadSafe(owningThread, msg)
- #else
- #define NS_CheckThreadSafe(owningThread, msg) \
- if (MOZ_UNLIKELY(owningThread != PR_GetCurrentThread())) { \
- MOZ_CRASH(msg); \
- }
- #endif
- #ifdef MOZILLA_INTERNAL_API
- void NS_ABORT_OOM(size_t aSize);
- #else
- inline void NS_ABORT_OOM(size_t)
- {
- MOZ_CRASH();
- }
- #endif
- typedef void (*StderrCallback)(const char* aFmt, va_list aArgs);
- /* When compiling the XPCOM Glue on Windows, we pretend that it's going to
- * be linked with a static CRT (-MT) even when it's not. This means that we
- * cannot link to data exports from the CRT, only function exports. So,
- * instead of referencing "stderr" directly, use fdopen.
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**
- * printf_stderr(...) is much like fprintf(stderr, ...), except that:
- * - it calls the callback set through set_stderr_callback
- * - on Android and Firefox OS, *instead* of printing to stderr, it
- * prints to logcat. (Newlines in the string lead to multiple lines
- * of logcat, but each function call implicitly completes a line even
- * if the string does not end with a newline.)
- * - on Windows, if a debugger is present, it calls OutputDebugString
- * in *addition* to writing to stderr
- */
- void printf_stderr(const char* aFmt, ...) MOZ_FORMAT_PRINTF(1, 2);
- /**
- * Same as printf_stderr, but taking va_list instead of varargs
- */
- void vprintf_stderr(const char* aFmt, va_list aArgs);
- /**
- * fprintf_stderr is like fprintf, except that if its file argument
- * is stderr, it invokes printf_stderr instead.
- *
- * This is useful for general debugging code that logs information to a
- * file, but that you would like to be useful on Android and Firefox OS.
- * If you use fprintf_stderr instead of fprintf in such debugging code,
- * then callers can pass stderr to get logging that works on Android and
- * Firefox OS (and also the other side-effects of using printf_stderr).
- *
- * Code that is structured this way needs to be careful not to split a
- * line of output across multiple calls to fprintf_stderr, since doing
- * so will cause it to appear in multiple lines in logcat output.
- * (Producing multiple lines at once is fine.)
- */
- void fprintf_stderr(FILE* aFile, const char* aFmt, ...) MOZ_FORMAT_PRINTF(2, 3);
- // used by the profiler to log stderr in the profiler for more
- // advanced performance debugging and display/layers visualization.
- void set_stderr_callback(StderrCallback aCallback);
- #ifdef __cplusplus
- }
- #endif
- #endif /* nsDebug_h___ */
|