nsDebug.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /* -*- Mode: C++; tab-width: 8; 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. #ifndef nsDebug_h___
  6. #define nsDebug_h___
  7. #include "nscore.h"
  8. #include "nsError.h"
  9. #include "nsXPCOM.h"
  10. #include "mozilla/Assertions.h"
  11. #include "mozilla/Likely.h"
  12. #include <stdarg.h>
  13. #ifdef DEBUG
  14. #include "prprf.h"
  15. #endif
  16. /**
  17. * Warn if the given condition is true. The condition is evaluated in both
  18. * release and debug builds, and the result is an expression which can be
  19. * used in subsequent expressions, such as:
  20. *
  21. * if (NS_WARN_IF(NS_FAILED(rv)) {
  22. * return rv;
  23. * }
  24. *
  25. * This explicit warning and return is preferred to the NS_ENSURE_* macros
  26. * which hide the warning and the return control flow.
  27. *
  28. * This macro can also be used outside of conditions just to issue a warning,
  29. * like so:
  30. *
  31. * Unused << NS_WARN_IF(NS_FAILED(FnWithSideEffects());
  32. *
  33. * (The |Unused <<| is necessary because of the MOZ_MUST_USE annotation.)
  34. *
  35. * However, note that the argument to this macro is evaluated in all builds. If
  36. * you just want a warning assertion, it is better to use NS_WARNING_ASSERTION
  37. * (which evaluates the condition only in debug builds) like so:
  38. *
  39. * NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "operation failed");
  40. *
  41. * @note This is C++-only
  42. */
  43. #ifdef __cplusplus
  44. #ifdef DEBUG
  45. inline MOZ_MUST_USE bool NS_warn_if_impl(bool aCondition, const char* aExpr,
  46. const char* aFile, int32_t aLine)
  47. {
  48. if (MOZ_UNLIKELY(aCondition)) {
  49. NS_DebugBreak(NS_DEBUG_WARNING, nullptr, aExpr, aFile, aLine);
  50. }
  51. return aCondition;
  52. }
  53. #define NS_WARN_IF(condition) \
  54. NS_warn_if_impl(condition, #condition, __FILE__, __LINE__)
  55. #else
  56. #define NS_WARN_IF(condition) (bool)(condition)
  57. #endif
  58. #endif
  59. /**
  60. * Test an assertion for truth. If the expression is not true then
  61. * emit a warning.
  62. *
  63. * Program execution continues past the usage of this macro.
  64. *
  65. * Note also that the non-debug version of this macro does <b>not</b>
  66. * evaluate the message argument.
  67. */
  68. #ifdef DEBUG
  69. #define NS_WARNING_ASSERTION(_expr, _msg) \
  70. do { \
  71. if (!(_expr)) { \
  72. NS_DebugBreak(NS_DEBUG_WARNING, _msg, #_expr, __FILE__, __LINE__); \
  73. } \
  74. } while(0)
  75. #else
  76. #define NS_WARNING_ASSERTION(_expr, _msg) do { /* nothing */ } while(0)
  77. #endif
  78. /**
  79. * Test an assertion for truth. If the expression is not true then
  80. * trigger a program failure.
  81. *
  82. * Note that the non-debug version of this macro does <b>not</b>
  83. * evaluate the message argument.
  84. */
  85. #ifdef DEBUG
  86. inline void MOZ_PretendNoReturn()
  87. MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS {}
  88. #define NS_ASSERTION(expr, str) \
  89. do { \
  90. if (!(expr)) { \
  91. NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
  92. MOZ_PretendNoReturn(); \
  93. } \
  94. } while(0)
  95. #else
  96. #define NS_ASSERTION(expr, str) do { /* nothing */ } while(0)
  97. #endif
  98. /**
  99. * NS_PRECONDITION/POSTCONDITION are synonyms for NS_ASSERTION.
  100. */
  101. #define NS_PRECONDITION(expr, str) NS_ASSERTION(expr, str)
  102. #define NS_POSTCONDITION(expr, str) NS_ASSERTION(expr, str)
  103. /**
  104. * This macros triggers a program failure if executed. It indicates that
  105. * an attempt was made to execute some unimplemented functionality.
  106. */
  107. #ifdef DEBUG
  108. #define NS_NOTYETIMPLEMENTED(str) \
  109. do { \
  110. NS_DebugBreak(NS_DEBUG_ASSERTION, str, "NotYetImplemented", __FILE__, __LINE__); \
  111. MOZ_PretendNoReturn(); \
  112. } while(0)
  113. #else
  114. #define NS_NOTYETIMPLEMENTED(str) do { /* nothing */ } while(0)
  115. #endif
  116. /**
  117. * This macros triggers a program failure if executed. It indicates that
  118. * an attempt was made to execute a codepath which should not be reachable.
  119. */
  120. #ifdef DEBUG
  121. #define NS_NOTREACHED(str) \
  122. do { \
  123. NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Not Reached", __FILE__, __LINE__); \
  124. MOZ_PretendNoReturn(); \
  125. } while(0)
  126. #else
  127. #define NS_NOTREACHED(str) do { /* nothing */ } while(0)
  128. #endif
  129. /**
  130. * Log an error message.
  131. */
  132. #ifdef DEBUG
  133. #define NS_ERROR(str) \
  134. do { \
  135. NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Error", __FILE__, __LINE__); \
  136. MOZ_PretendNoReturn(); \
  137. } while(0)
  138. #else
  139. #define NS_ERROR(str) do { /* nothing */ } while(0)
  140. #endif
  141. /**
  142. * Log a warning message.
  143. */
  144. #ifdef DEBUG
  145. #define NS_WARNING(str) \
  146. NS_DebugBreak(NS_DEBUG_WARNING, str, nullptr, __FILE__, __LINE__)
  147. #else
  148. #define NS_WARNING(str) do { /* nothing */ } while(0)
  149. #endif
  150. /**
  151. * Trigger an debug-only abort.
  152. *
  153. * @see NS_RUNTIMEABORT for release-mode asserts.
  154. */
  155. #ifdef DEBUG
  156. #define NS_ABORT() \
  157. do { \
  158. NS_DebugBreak(NS_DEBUG_ABORT, nullptr, nullptr, __FILE__, __LINE__); \
  159. MOZ_PretendNoReturn(); \
  160. } while(0)
  161. #else
  162. #define NS_ABORT() do { /* nothing */ } while(0)
  163. #endif
  164. /**
  165. * Trigger a debugger breakpoint, only in debug builds.
  166. */
  167. #ifdef DEBUG
  168. #define NS_BREAK() \
  169. do { \
  170. NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, __FILE__, __LINE__); \
  171. MOZ_PretendNoReturn(); \
  172. } while(0)
  173. #else
  174. #define NS_BREAK() do { /* nothing */ } while(0)
  175. #endif
  176. /******************************************************************************
  177. ** Macros for static assertions. These are used by the sixgill tool.
  178. ** When the tool is not running these macros are no-ops.
  179. ******************************************************************************/
  180. /* Avoid name collision if included with other headers defining annotations. */
  181. #ifndef HAVE_STATIC_ANNOTATIONS
  182. #define HAVE_STATIC_ANNOTATIONS
  183. #ifdef XGILL_PLUGIN
  184. #define STATIC_PRECONDITION(COND) __attribute__((precondition(#COND)))
  185. #define STATIC_PRECONDITION_ASSUME(COND) __attribute__((precondition_assume(#COND)))
  186. #define STATIC_POSTCONDITION(COND) __attribute__((postcondition(#COND)))
  187. #define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
  188. #define STATIC_INVARIANT(COND) __attribute__((invariant(#COND)))
  189. #define STATIC_INVARIANT_ASSUME(COND) __attribute__((invariant_assume(#COND)))
  190. /* Used to make identifiers for assert/assume annotations in a function. */
  191. #define STATIC_PASTE2(X,Y) X ## Y
  192. #define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
  193. #define STATIC_ASSUME(COND) \
  194. do { \
  195. __attribute__((assume_static(#COND), unused)) \
  196. int STATIC_PASTE1(assume_static_, __COUNTER__); \
  197. } while(0)
  198. #define STATIC_ASSERT_RUNTIME(COND) \
  199. do { \
  200. __attribute__((assert_static_runtime(#COND), unused)) \
  201. int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
  202. } while(0)
  203. #else /* XGILL_PLUGIN */
  204. #define STATIC_PRECONDITION(COND) /* nothing */
  205. #define STATIC_PRECONDITION_ASSUME(COND) /* nothing */
  206. #define STATIC_POSTCONDITION(COND) /* nothing */
  207. #define STATIC_POSTCONDITION_ASSUME(COND) /* nothing */
  208. #define STATIC_INVARIANT(COND) /* nothing */
  209. #define STATIC_INVARIANT_ASSUME(COND) /* nothing */
  210. #define STATIC_ASSUME(COND) do { /* nothing */ } while(0)
  211. #define STATIC_ASSERT_RUNTIME(COND) do { /* nothing */ } while(0)
  212. #endif /* XGILL_PLUGIN */
  213. #define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
  214. #endif /* HAVE_STATIC_ANNOTATIONS */
  215. /******************************************************************************
  216. ** Macros for terminating execution when an unrecoverable condition is
  217. ** reached. These need to be compiled regardless of the DEBUG flag.
  218. ******************************************************************************/
  219. /**
  220. * Terminate execution <i>immediately</i>, and if possible on the current
  221. * platform, in such a way that execution can't be continued by other
  222. * code (e.g., by intercepting a signal).
  223. */
  224. #define NS_RUNTIMEABORT(msg) \
  225. NS_DebugBreak(NS_DEBUG_ABORT, msg, nullptr, __FILE__, __LINE__)
  226. /* Macros for checking the trueness of an expression passed in within an
  227. * interface implementation. These need to be compiled regardless of the
  228. * DEBUG flag. New code should use NS_WARN_IF(condition) instead!
  229. * @status deprecated
  230. */
  231. #define NS_ENSURE_TRUE(x, ret) \
  232. do { \
  233. if (MOZ_UNLIKELY(!(x))) { \
  234. NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  235. return ret; \
  236. } \
  237. } while(0)
  238. #define NS_ENSURE_FALSE(x, ret) \
  239. NS_ENSURE_TRUE(!(x), ret)
  240. #define NS_ENSURE_TRUE_VOID(x) \
  241. do { \
  242. if (MOZ_UNLIKELY(!(x))) { \
  243. NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  244. return; \
  245. } \
  246. } while(0)
  247. #define NS_ENSURE_FALSE_VOID(x) \
  248. NS_ENSURE_TRUE_VOID(!(x))
  249. /******************************************************************************
  250. ** Macros for checking results
  251. ******************************************************************************/
  252. #if defined(DEBUG) && !defined(XPCOM_GLUE_AVOID_NSPR)
  253. #define NS_ENSURE_SUCCESS_BODY(res, ret) \
  254. char *msg = PR_smprintf("NS_ENSURE_SUCCESS(%s, %s) failed with " \
  255. "result 0x%X", #res, #ret, __rv); \
  256. NS_WARNING(msg); \
  257. PR_smprintf_free(msg);
  258. #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
  259. char *msg = PR_smprintf("NS_ENSURE_SUCCESS_VOID(%s) failed with " \
  260. "result 0x%X", #res, __rv); \
  261. NS_WARNING(msg); \
  262. PR_smprintf_free(msg);
  263. #else
  264. #define NS_ENSURE_SUCCESS_BODY(res, ret) \
  265. NS_WARNING("NS_ENSURE_SUCCESS(" #res ", " #ret ") failed");
  266. #define NS_ENSURE_SUCCESS_BODY_VOID(res) \
  267. NS_WARNING("NS_ENSURE_SUCCESS_VOID(" #res ") failed");
  268. #endif
  269. #define NS_ENSURE_SUCCESS(res, ret) \
  270. do { \
  271. nsresult __rv = res; /* Don't evaluate |res| more than once */ \
  272. if (NS_FAILED(__rv)) { \
  273. NS_ENSURE_SUCCESS_BODY(res, ret) \
  274. return ret; \
  275. } \
  276. } while(0)
  277. #define NS_ENSURE_SUCCESS_VOID(res) \
  278. do { \
  279. nsresult __rv = res; \
  280. if (NS_FAILED(__rv)) { \
  281. NS_ENSURE_SUCCESS_BODY_VOID(res) \
  282. return; \
  283. } \
  284. } while(0)
  285. /******************************************************************************
  286. ** Macros for checking state and arguments upon entering interface boundaries
  287. ******************************************************************************/
  288. #define NS_ENSURE_ARG(arg) \
  289. NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG)
  290. #define NS_ENSURE_ARG_POINTER(arg) \
  291. NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER)
  292. #define NS_ENSURE_ARG_MIN(arg, min) \
  293. NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG)
  294. #define NS_ENSURE_ARG_MAX(arg, max) \
  295. NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG)
  296. #define NS_ENSURE_ARG_RANGE(arg, min, max) \
  297. NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG)
  298. #define NS_ENSURE_STATE(state) \
  299. NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED)
  300. #define NS_ENSURE_NO_AGGREGATION(outer) \
  301. NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION)
  302. /*****************************************************************************/
  303. #if (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING))) && !defined(XPCOM_GLUE_AVOID_NSPR)
  304. #define MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED 1
  305. #endif
  306. #ifdef XPCOM_GLUE
  307. #define NS_CheckThreadSafe(owningThread, msg)
  308. #else
  309. #define NS_CheckThreadSafe(owningThread, msg) \
  310. if (MOZ_UNLIKELY(owningThread != PR_GetCurrentThread())) { \
  311. MOZ_CRASH(msg); \
  312. }
  313. #endif
  314. #ifdef MOZILLA_INTERNAL_API
  315. void NS_ABORT_OOM(size_t aSize);
  316. #else
  317. inline void NS_ABORT_OOM(size_t)
  318. {
  319. MOZ_CRASH();
  320. }
  321. #endif
  322. typedef void (*StderrCallback)(const char* aFmt, va_list aArgs);
  323. /* When compiling the XPCOM Glue on Windows, we pretend that it's going to
  324. * be linked with a static CRT (-MT) even when it's not. This means that we
  325. * cannot link to data exports from the CRT, only function exports. So,
  326. * instead of referencing "stderr" directly, use fdopen.
  327. */
  328. #ifdef __cplusplus
  329. extern "C" {
  330. #endif
  331. /**
  332. * printf_stderr(...) is much like fprintf(stderr, ...), except that:
  333. * - it calls the callback set through set_stderr_callback
  334. * - on Android and Firefox OS, *instead* of printing to stderr, it
  335. * prints to logcat. (Newlines in the string lead to multiple lines
  336. * of logcat, but each function call implicitly completes a line even
  337. * if the string does not end with a newline.)
  338. * - on Windows, if a debugger is present, it calls OutputDebugString
  339. * in *addition* to writing to stderr
  340. */
  341. void printf_stderr(const char* aFmt, ...) MOZ_FORMAT_PRINTF(1, 2);
  342. /**
  343. * Same as printf_stderr, but taking va_list instead of varargs
  344. */
  345. void vprintf_stderr(const char* aFmt, va_list aArgs);
  346. /**
  347. * fprintf_stderr is like fprintf, except that if its file argument
  348. * is stderr, it invokes printf_stderr instead.
  349. *
  350. * This is useful for general debugging code that logs information to a
  351. * file, but that you would like to be useful on Android and Firefox OS.
  352. * If you use fprintf_stderr instead of fprintf in such debugging code,
  353. * then callers can pass stderr to get logging that works on Android and
  354. * Firefox OS (and also the other side-effects of using printf_stderr).
  355. *
  356. * Code that is structured this way needs to be careful not to split a
  357. * line of output across multiple calls to fprintf_stderr, since doing
  358. * so will cause it to appear in multiple lines in logcat output.
  359. * (Producing multiple lines at once is fine.)
  360. */
  361. void fprintf_stderr(FILE* aFile, const char* aFmt, ...) MOZ_FORMAT_PRINTF(2, 3);
  362. // used by the profiler to log stderr in the profiler for more
  363. // advanced performance debugging and display/layers visualization.
  364. void set_stderr_callback(StderrCallback aCallback);
  365. #ifdef __cplusplus
  366. }
  367. #endif
  368. #endif /* nsDebug_h___ */