LCOV - code coverage report
Current view: top level - mfbt - Assertions.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 10 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* Implementations of runtime and static assertion macros for C and C++. */
       8             : 
       9             : #ifndef mozilla_Assertions_h
      10             : #define mozilla_Assertions_h
      11             : 
      12             : #if defined(MOZILLA_INTERNAL_API) && defined(__cplusplus)
      13             : #define MOZ_DUMP_ASSERTION_STACK
      14             : #endif
      15             : 
      16             : #include "mozilla/Attributes.h"
      17             : #include "mozilla/Compiler.h"
      18             : #include "mozilla/Likely.h"
      19             : #include "mozilla/MacroArgs.h"
      20             : #include "mozilla/StaticAnalysisFunctions.h"
      21             : #include "mozilla/Types.h"
      22             : #ifdef MOZ_DUMP_ASSERTION_STACK
      23             : #include "nsTraceRefcnt.h"
      24             : #endif
      25             : 
      26             : /*
      27             :  * The crash reason set by MOZ_CRASH_ANNOTATE is consumed by the crash reporter
      28             :  * if present. It is declared here (and defined in Assertions.cpp) to make it
      29             :  * available to all code, even libraries that don't link with the crash reporter
      30             :  * directly.
      31             :  */
      32             : MOZ_BEGIN_EXTERN_C
      33             : extern MFBT_DATA const char* gMozCrashReason;
      34             : MOZ_END_EXTERN_C
      35             : 
      36             : #if !defined(DEBUG) && (defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API))
      37             : static inline void
      38             : AnnotateMozCrashReason(const char* reason)
      39             : {
      40             :   gMozCrashReason = reason;
      41             : }
      42             : #  define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__)
      43             : #else
      44             : #  define MOZ_CRASH_ANNOTATE(...) do { /* nothing */ } while (0)
      45             : #endif
      46             : 
      47             : #include <stddef.h>
      48             : #include <stdio.h>
      49             : #include <stdlib.h>
      50             : #ifdef _MSC_VER
      51             :    /*
      52             :     * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
      53             :     * further depends on <windef.h>.  We hardcode these few definitions manually
      54             :     * because those headers clutter the global namespace with a significant
      55             :     * number of undesired macros and symbols.
      56             :     */
      57             : MOZ_BEGIN_EXTERN_C
      58             : __declspec(dllimport) int __stdcall
      59             : TerminateProcess(void* hProcess, unsigned int uExitCode);
      60             : __declspec(dllimport) void* __stdcall GetCurrentProcess(void);
      61             : MOZ_END_EXTERN_C
      62             : #else
      63             : #  include <signal.h>
      64             : #endif
      65             : #ifdef ANDROID
      66             : #  include <android/log.h>
      67             : #endif
      68             : 
      69             : /*
      70             :  * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C.
      71             :  * In C++11, static_assert is provided by the compiler to the same effect.
      72             :  * This can be useful when you make certain assumptions about what must hold for
      73             :  * optimal, or even correct, behavior.  For example, you might assert that the
      74             :  * size of a struct is a multiple of the target architecture's word size:
      75             :  *
      76             :  *   struct S { ... };
      77             :  *   // C
      78             :  *   MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
      79             :  *                     "S should be a multiple of word size for efficiency");
      80             :  *   // C++11
      81             :  *   static_assert(sizeof(S) % sizeof(size_t) == 0,
      82             :  *                 "S should be a multiple of word size for efficiency");
      83             :  *
      84             :  * This macro can be used in any location where both an extern declaration and a
      85             :  * typedef could be used.
      86             :  */
      87             : #ifndef __cplusplus
      88             :    /*
      89             :     * Some of the definitions below create an otherwise-unused typedef.  This
      90             :     * triggers compiler warnings with some versions of gcc, so mark the typedefs
      91             :     * as permissibly-unused to disable the warnings.
      92             :     */
      93             : #  if defined(__GNUC__)
      94             : #    define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
      95             : #  else
      96             : #    define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */
      97             : #  endif
      98             : #  define MOZ_STATIC_ASSERT_GLUE1(x, y)          x##y
      99             : #  define MOZ_STATIC_ASSERT_GLUE(x, y)           MOZ_STATIC_ASSERT_GLUE1(x, y)
     100             : #  if defined(__SUNPRO_CC)
     101             :      /*
     102             :       * The Sun Studio C++ compiler is buggy when declaring, inside a function,
     103             :       * another extern'd function with an array argument whose length contains a
     104             :       * sizeof, triggering the error message "sizeof expression not accepted as
     105             :       * size of array parameter".  This bug (6688515, not public yet) would hit
     106             :       * defining moz_static_assert as a function, so we always define an extern
     107             :       * array for Sun Studio.
     108             :       *
     109             :       * We include the line number in the symbol name in a best-effort attempt
     110             :       * to avoid conflicts (see below).
     111             :       */
     112             : #    define MOZ_STATIC_ASSERT(cond, reason) \
     113             :        extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
     114             : #  elif defined(__COUNTER__)
     115             :      /*
     116             :       * If there was no preferred alternative, use a compiler-agnostic version.
     117             :       *
     118             :       * Note that the non-__COUNTER__ version has a bug in C++: it can't be used
     119             :       * in both |extern "C"| and normal C++ in the same translation unit.  (Alas
     120             :       * |extern "C"| isn't allowed in a function.)  The only affected compiler
     121             :       * we really care about is gcc 4.2.  For that compiler and others like it,
     122             :       * we include the line number in the function name to do the best we can to
     123             :       * avoid conflicts.  These should be rare: a conflict would require use of
     124             :       * MOZ_STATIC_ASSERT on the same line in separate files in the same
     125             :       * translation unit, *and* the uses would have to be in code with
     126             :       * different linkage, *and* the first observed use must be in C++-linkage
     127             :       * code.
     128             :       */
     129             : #    define MOZ_STATIC_ASSERT(cond, reason) \
     130             :        typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
     131             : #  else
     132             : #    define MOZ_STATIC_ASSERT(cond, reason) \
     133             :        extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
     134             : #  endif
     135             : 
     136             : #define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
     137             : #else
     138             : #define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  static_assert(!(cond) || (expr), reason)
     139             : #endif
     140             : 
     141             : MOZ_BEGIN_EXTERN_C
     142             : 
     143             : /*
     144             :  * Prints |aStr| as an assertion failure (using aFilename and aLine as the
     145             :  * location of the assertion) to the standard debug-output channel.
     146             :  *
     147             :  * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method.  This
     148             :  * method is primarily for internal use in this header, and only secondarily
     149             :  * for use in implementing release-build assertions.
     150             :  */
     151             : MOZ_MAYBE_UNUSED static MOZ_COLD MOZ_NEVER_INLINE void
     152           0 : MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename, int aLine)
     153             :   MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
     154             : {
     155             : #ifdef ANDROID
     156             :   __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
     157             :                       "Assertion failure: %s, at %s:%d\n",
     158             :                       aStr, aFilename, aLine);
     159             : #else
     160           0 :   fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
     161             : #if defined (MOZ_DUMP_ASSERTION_STACK)
     162           0 :   nsTraceRefcnt::WalkTheStack(stderr);
     163             : #endif
     164           0 :   fflush(stderr);
     165             : #endif
     166           0 : }
     167             : 
     168             : MOZ_MAYBE_UNUSED static MOZ_COLD MOZ_NEVER_INLINE void
     169           0 : MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine)
     170             :   MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
     171             : {
     172             : #ifdef ANDROID
     173             :   __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",
     174             :                       "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
     175             : #else
     176           0 :   fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
     177             : #if defined(MOZ_DUMP_ASSERTION_STACK)
     178           0 :   nsTraceRefcnt::WalkTheStack(stderr);
     179             : #endif
     180           0 :   fflush(stderr);
     181             : #endif
     182           0 : }
     183             : 
     184             : /**
     185             :  * MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH().  You should
     186             :  * call MOZ_CRASH instead.
     187             :  */
     188             : #if defined(_MSC_VER)
     189             :    /*
     190             :     * On MSVC use the __debugbreak compiler intrinsic, which produces an inline
     191             :     * (not nested in a system function) breakpoint.  This distinctively invokes
     192             :     * Breakpad without requiring system library symbols on all stack-processing
     193             :     * machines, as a nested breakpoint would require.
     194             :     *
     195             :     * We use __LINE__ to prevent the compiler from folding multiple crash sites
     196             :     * together, which would make crash reports hard to understand.
     197             :     *
     198             :     * We use TerminateProcess with the exit code aborting would generate
     199             :     * because we don't want to invoke atexit handlers, destructors, library
     200             :     * unload handlers, and so on when our process might be in a compromised
     201             :     * state.
     202             :     *
     203             :     * We don't use abort() because it'd cause Windows to annoyingly pop up the
     204             :     * process error dialog multiple times.  See bug 345118 and bug 426163.
     205             :     *
     206             :     * (Technically these are Windows requirements, not MSVC requirements.  But
     207             :     * practically you need MSVC for debugging, and we only ship builds created
     208             :     * by MSVC, so doing it this way reduces complexity.)
     209             :     */
     210             : 
     211             : static MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void MOZ_NoReturn(int aLine)
     212             : {
     213             :   *((volatile int*) NULL) = aLine;
     214             :   TerminateProcess(GetCurrentProcess(), 3);
     215             : }
     216             : 
     217             : #  define MOZ_REALLY_CRASH(line) \
     218             :      do { \
     219             :        __debugbreak(); \
     220             :        MOZ_NoReturn(line); \
     221             :      } while (0)
     222             : #else
     223             : #  ifdef __cplusplus
     224             : #    define MOZ_REALLY_CRASH(line) \
     225             :        do { \
     226             :          *((volatile int*) NULL) = line; \
     227             :          ::abort(); \
     228             :        } while (0)
     229             : #  else
     230             : #    define MOZ_REALLY_CRASH(line) \
     231             :        do { \
     232             :          *((volatile int*) NULL) = line; \
     233             :          abort(); \
     234             :        } while (0)
     235             : #  endif
     236             : #endif
     237             : 
     238             : /*
     239             :  * MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a
     240             :  * Breakpad-compatible way, in both debug and release builds.
     241             :  *
     242             :  * MOZ_CRASH is a good solution for "handling" failure cases when you're
     243             :  * unwilling or unable to handle them more cleanly -- for OOM, for likely memory
     244             :  * corruption, and so on.  It's also a good solution if you need safe behavior
     245             :  * in release builds as well as debug builds.  But if the failure is one that
     246             :  * should be debugged and fixed, MOZ_ASSERT is generally preferable.
     247             :  *
     248             :  * The optional explanation-string, if provided, must be a string literal
     249             :  * explaining why we're crashing.  This argument is intended for use with
     250             :  * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's
     251             :  * obvious why we're crashing.
     252             :  *
     253             :  * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an
     254             :  * explanation-string, we print the string to stderr.  Otherwise, we don't
     255             :  * print anything; this is because we want MOZ_CRASH to be 100% safe in release
     256             :  * builds, and it's hard to print to stderr safely when memory might have been
     257             :  * corrupted.
     258             :  */
     259             : #ifndef DEBUG
     260             : #  define MOZ_CRASH(...) \
     261             :      do { \
     262             :        MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
     263             :        MOZ_REALLY_CRASH(__LINE__); \
     264             :      } while (0)
     265             : #else
     266             : #  define MOZ_CRASH(...) \
     267             :      do { \
     268             :        MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
     269             :        MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
     270             :        MOZ_REALLY_CRASH(__LINE__); \
     271             :      } while (0)
     272             : #endif
     273             : 
     274             : /*
     275             :  * MOZ_CRASH_UNSAFE_OOL(explanation-string) can be used if the explanation
     276             :  * string cannot be a string literal (but no other processing needs to be done
     277             :  * on it). A regular MOZ_CRASH() is preferred wherever possible, as passing
     278             :  * arbitrary strings from a potentially compromised process is not without risk.
     279             :  * If the string being passed is the result of a printf-style function,
     280             :  * consider using MOZ_CRASH_UNSAFE_PRINTF instead.
     281             :  */
     282             : #ifndef DEBUG
     283             : MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
     284             : MOZ_CrashOOL(int aLine, const char* aReason);
     285             : #  define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__LINE__, reason)
     286             : #else
     287             : MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
     288             : MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason);
     289             : #  define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__FILE__, __LINE__, reason)
     290             : #endif
     291             : 
     292             : static const size_t sPrintfMaxArgs = 4;
     293             : static const size_t sPrintfCrashReasonSize = 1024;
     294             : 
     295             : #ifndef DEBUG
     296             : MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void
     297             : MOZ_CrashPrintf(int aLine, const char* aFormat, ...);
     298             : #  define MOZ_CALL_CRASH_PRINTF(format, ...) \
     299             :      MOZ_CrashPrintf(__LINE__, format, __VA_ARGS__)
     300             : #else
     301             : MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void
     302             : MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...);
     303             : #  define MOZ_CALL_CRASH_PRINTF(format, ...) \
     304             :      MOZ_CrashPrintf(__FILE__, __LINE__, format, __VA_ARGS__)
     305             : #endif
     306             : 
     307             : /*
     308             :  * MOZ_CRASH_UNSAFE_PRINTF(format, arg1 [, args]) can be used when more
     309             :  * information is desired than a string literal can supply. The caller provides
     310             :  * a printf-style format string, which must be a string literal and between
     311             :  * 1 and 4 additional arguments. A regular MOZ_CRASH() is preferred wherever
     312             :  * possible, as passing arbitrary strings to printf from a potentially
     313             :  * compromised process is not without risk.
     314             :  */
     315             : #define MOZ_CRASH_UNSAFE_PRINTF(format, ...) \
     316             :    do { \
     317             :      static_assert( \
     318             :        MOZ_ARG_COUNT(__VA_ARGS__) > 0, \
     319             :        "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? " \
     320             :        "Or maybe you want MOZ_CRASH instead?"); \
     321             :      static_assert( \
     322             :        MOZ_ARG_COUNT(__VA_ARGS__) <= sPrintfMaxArgs, \
     323             :        "Only up to 4 additional arguments are allowed!"); \
     324             :      static_assert(sizeof(format) <= sPrintfCrashReasonSize, \
     325             :        "The supplied format string is too long!"); \
     326             :      MOZ_CALL_CRASH_PRINTF("" format, __VA_ARGS__); \
     327             :    } while (0)
     328             : 
     329             : MOZ_END_EXTERN_C
     330             : 
     331             : /*
     332             :  * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
     333             :  * debug builds.  If it is, execution continues.  Otherwise, an error message
     334             :  * including the expression and the explanation-string (if provided) is printed,
     335             :  * an attempt is made to invoke any existing debugger, and execution halts.
     336             :  * MOZ_ASSERT is fatal: no recovery is possible.  Do not assert a condition
     337             :  * which can correctly be falsy.
     338             :  *
     339             :  * The optional explanation-string, if provided, must be a string literal
     340             :  * explaining the assertion.  It is intended for use with assertions whose
     341             :  * correctness or rationale is non-obvious, and for assertions where the "real"
     342             :  * condition being tested is best described prosaically.  Don't provide an
     343             :  * explanation if it's not actually helpful.
     344             :  *
     345             :  *   // No explanation needed: pointer arguments often must not be NULL.
     346             :  *   MOZ_ASSERT(arg);
     347             :  *
     348             :  *   // An explanation can be helpful to explain exactly how we know an
     349             :  *   // assertion is valid.
     350             :  *   MOZ_ASSERT(state == WAITING_FOR_RESPONSE,
     351             :  *              "given that <thingA> and <thingB>, we must have...");
     352             :  *
     353             :  *   // Or it might disambiguate multiple identical (save for their location)
     354             :  *   // assertions of the same expression.
     355             :  *   MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
     356             :  *              "we already set [[PrimitiveThis]] for this Boolean object");
     357             :  *   MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
     358             :  *              "we already set [[PrimitiveThis]] for this String object");
     359             :  *
     360             :  * MOZ_ASSERT has no effect in non-debug builds.  It is designed to catch bugs
     361             :  * *only* during debugging, not "in the field". If you want the latter, use
     362             :  * MOZ_RELEASE_ASSERT, which applies to non-debug builds as well.
     363             :  *
     364             :  * MOZ_DIAGNOSTIC_ASSERT works like MOZ_RELEASE_ASSERT in Nightly/Aurora and
     365             :  * MOZ_ASSERT in Beta/Release - use this when a condition is potentially rare
     366             :  * enough to require real user testing to hit, but is not security-sensitive.
     367             :  * This can cause user pain, so use it sparingly. If a MOZ_DIAGNOSTIC_ASSERT
     368             :  * is firing, it should promptly be converted to a MOZ_ASSERT while the failure
     369             :  * is being investigated, rather than letting users suffer.
     370             :  *
     371             :  * MOZ_DIAGNOSTIC_ASSERT_ENABLED is defined when MOZ_DIAGNOSTIC_ASSERT is like
     372             :  * MOZ_RELEASE_ASSERT rather than MOZ_ASSERT.
     373             :  */
     374             : 
     375             : /*
     376             :  * Implement MOZ_VALIDATE_ASSERT_CONDITION_TYPE, which is used to guard against
     377             :  * accidentally passing something unintended in lieu of an assertion condition.
     378             :  */
     379             : 
     380             : #ifdef __cplusplus
     381             : #  include "mozilla/TypeTraits.h"
     382             : namespace mozilla {
     383             : namespace detail {
     384             : 
     385             : template<typename T>
     386             : struct AssertionConditionType
     387             : {
     388             :   typedef typename RemoveReference<T>::Type ValueT;
     389             :   static_assert(!IsArray<ValueT>::value,
     390             :                 "Expected boolean assertion condition, got an array or a "
     391             :                 "string!");
     392             :   static_assert(!IsFunction<ValueT>::value,
     393             :                 "Expected boolean assertion condition, got a function! Did "
     394             :                 "you intend to call that function?");
     395             :   static_assert(!IsFloatingPoint<ValueT>::value,
     396             :                 "It's often a bad idea to assert that a floating-point number "
     397             :                 "is nonzero, because such assertions tend to intermittently "
     398             :                 "fail. Shouldn't your code gracefully handle this case instead "
     399             :                 "of asserting? Anyway, if you really want to do that, write an "
     400             :                 "explicit boolean condition, like !!x or x!=0.");
     401             : 
     402             :   static const bool isValid = true;
     403             : };
     404             : 
     405             : } // namespace detail
     406             : } // namespace mozilla
     407             : #  define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x) \
     408             :      static_assert(mozilla::detail::AssertionConditionType<decltype(x)>::isValid, \
     409             :                    "invalid assertion condition")
     410             : #else
     411             : #  define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x)
     412             : #endif
     413             : 
     414             : #if defined(DEBUG) || defined(MOZ_ASAN)
     415             : #  define MOZ_REPORT_ASSERTION_FAILURE(...) MOZ_ReportAssertionFailure(__VA_ARGS__)
     416             : #else
     417             : #  define MOZ_REPORT_ASSERTION_FAILURE(...) do { /* nothing */ } while (0)
     418             : #endif
     419             : 
     420             : /* First the single-argument form. */
     421             : #define MOZ_ASSERT_HELPER1(expr) \
     422             :   do { \
     423             :     MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
     424             :     if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
     425             :       MOZ_REPORT_ASSERTION_FAILURE(#expr, __FILE__, __LINE__); \
     426             :       MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ")"); \
     427             :       MOZ_REALLY_CRASH(__LINE__); \
     428             :     } \
     429             :   } while (0)
     430             : /* Now the two-argument form. */
     431             : #define MOZ_ASSERT_HELPER2(expr, explain) \
     432             :   do { \
     433             :     MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
     434             :     if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
     435             :       MOZ_REPORT_ASSERTION_FAILURE(#expr " (" explain ")", __FILE__, __LINE__); \
     436             :       MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ") (" explain ")"); \
     437             :       MOZ_REALLY_CRASH(__LINE__); \
     438             :     } \
     439             :   } while (0)
     440             : 
     441             : #define MOZ_RELEASE_ASSERT_GLUE(a, b) a b
     442             : #define MOZ_RELEASE_ASSERT(...) \
     443             :   MOZ_RELEASE_ASSERT_GLUE( \
     444             :     MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \
     445             :     (__VA_ARGS__))
     446             : 
     447             : #ifdef DEBUG
     448             : #  define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
     449             : #else
     450             : #  define MOZ_ASSERT(...) do { } while (0)
     451             : #endif /* DEBUG */
     452             : 
     453             : #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION)
     454             : #  define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
     455             : #  define MOZ_DIAGNOSTIC_ASSERT_ENABLED 1
     456             : #else
     457             : #  define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
     458             : #  ifdef DEBUG
     459             : #    define MOZ_DIAGNOSTIC_ASSERT_ENABLED 1
     460             : #  endif
     461             : #endif
     462             : 
     463             : /*
     464             :  * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
     465             :  * true.
     466             :  *
     467             :  *   MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
     468             :  *
     469             :  * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds.  It is
     470             :  * designed to catch bugs during debugging, not "in the field".
     471             :  */
     472             : #ifdef DEBUG
     473             : #  define MOZ_ASSERT_IF(cond, expr) \
     474             :      do { \
     475             :        if (cond) { \
     476             :          MOZ_ASSERT(expr); \
     477             :        } \
     478             :      } while (0)
     479             : #else
     480             : #  define MOZ_ASSERT_IF(cond, expr)  do { } while (0)
     481             : #endif
     482             : 
     483             : /*
     484             :  * MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that
     485             :  * it is undefined behavior for execution to reach this point.  No guarantees
     486             :  * are made about what will happen if this is reached at runtime.  Most code
     487             :  * should use MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE because it has extra
     488             :  * asserts.
     489             :  */
     490             : #if defined(__clang__) || defined(__GNUC__)
     491             : #  define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable()
     492             : #elif defined(_MSC_VER)
     493             : #  define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0)
     494             : #else
     495             : #  ifdef __cplusplus
     496             : #    define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort()
     497             : #  else
     498             : #    define MOZ_ASSUME_UNREACHABLE_MARKER() abort()
     499             : #  endif
     500             : #endif
     501             : 
     502             : /*
     503             :  * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE([reason]) tells the compiler that it
     504             :  * can assume that the macro call cannot be reached during execution.  This lets
     505             :  * the compiler generate better-optimized code under some circumstances, at the
     506             :  * expense of the program's behavior being undefined if control reaches the
     507             :  * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE.
     508             :  *
     509             :  * In Gecko, you probably should not use this macro outside of performance- or
     510             :  * size-critical code, because it's unsafe.  If you don't care about code size
     511             :  * or performance, you should probably use MOZ_ASSERT or MOZ_CRASH.
     512             :  *
     513             :  * SpiderMonkey is a different beast, and there it's acceptable to use
     514             :  * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE more widely.
     515             :  *
     516             :  * Note that MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE is noreturn, so it's valid
     517             :  * not to return a value following a MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE
     518             :  * call.
     519             :  *
     520             :  * Example usage:
     521             :  *
     522             :  *   enum ValueType {
     523             :  *     VALUE_STRING,
     524             :  *     VALUE_INT,
     525             :  *     VALUE_FLOAT
     526             :  *   };
     527             :  *
     528             :  *   int ptrToInt(ValueType type, void* value) {
     529             :  *   {
     530             :  *     // We know for sure that type is either INT or FLOAT, and we want this
     531             :  *     // code to run as quickly as possible.
     532             :  *     switch (type) {
     533             :  *     case VALUE_INT:
     534             :  *       return *(int*) value;
     535             :  *     case VALUE_FLOAT:
     536             :  *       return (int) *(float*) value;
     537             :  *     default:
     538             :  *       MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected ValueType");
     539             :  *     }
     540             :  *   }
     541             :  */
     542             : 
     543             : /*
     544             :  * Unconditional assert in debug builds for (assumed) unreachable code paths
     545             :  * that have a safe return without crashing in release builds.
     546             :  */
     547             : #define MOZ_ASSERT_UNREACHABLE(reason) \
     548             :    MOZ_ASSERT(false, "MOZ_ASSERT_UNREACHABLE: " reason)
     549             : 
     550             : #define MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(reason) \
     551             :    do { \
     552             :      MOZ_ASSERT_UNREACHABLE(reason); \
     553             :      MOZ_ASSUME_UNREACHABLE_MARKER(); \
     554             :    } while (0)
     555             : 
     556             : /**
     557             :  * MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
     558             :  * switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
     559             :  * debug builds, but intentionally fall through in release builds to handle
     560             :  * unexpected values.
     561             :  *
     562             :  * Why do we need MOZ_FALLTHROUGH_ASSERT in addition to MOZ_FALLTHROUGH? In
     563             :  * release builds, the MOZ_ASSERT(false) will expand to `do { } while (0)`,
     564             :  * requiring a MOZ_FALLTHROUGH annotation to suppress a -Wimplicit-fallthrough
     565             :  * warning. In debug builds, the MOZ_ASSERT(false) will expand to something like
     566             :  * `if (true) { MOZ_CRASH(); }` and the MOZ_FALLTHROUGH annotation will cause
     567             :  * a -Wunreachable-code warning. The MOZ_FALLTHROUGH_ASSERT macro breaks this
     568             :  * warning stalemate.
     569             :  *
     570             :  * // Example before MOZ_FALLTHROUGH_ASSERT:
     571             :  * switch (foo) {
     572             :  *   default:
     573             :  *     // This case wants to assert in debug builds, fall through in release.
     574             :  *     MOZ_ASSERT(false); // -Wimplicit-fallthrough warning in release builds!
     575             :  *     MOZ_FALLTHROUGH;   // but -Wunreachable-code warning in debug builds!
     576             :  *   case 5:
     577             :  *     return 5;
     578             :  * }
     579             :  *
     580             :  * // Example with MOZ_FALLTHROUGH_ASSERT:
     581             :  * switch (foo) {
     582             :  *   default:
     583             :  *     // This case asserts in debug builds, falls through in release.
     584             :  *     MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
     585             :  *   case 5:
     586             :  *     return 5;
     587             :  * }
     588             :  */
     589             : #ifdef DEBUG
     590             : #  define MOZ_FALLTHROUGH_ASSERT(reason) MOZ_CRASH("MOZ_FALLTHROUGH_ASSERT: " reason)
     591             : #else
     592             : #  define MOZ_FALLTHROUGH_ASSERT(...) MOZ_FALLTHROUGH
     593             : #endif
     594             : 
     595             : /*
     596             :  * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
     597             :  * expression, in debug builds and in release builds both.  Then, in debug
     598             :  * builds only, the value of the expression is asserted either true or false
     599             :  * using MOZ_ASSERT.
     600             :  */
     601             : #ifdef DEBUG
     602             : #  define MOZ_ALWAYS_TRUE(expr) \
     603             :      do { \
     604             :        if ((expr)) { \
     605             :          /* Do nothing. */ \
     606             :        } else { \
     607             :          MOZ_ASSERT(false, #expr); \
     608             :        } \
     609             :      } while (0)
     610             : #  define MOZ_ALWAYS_FALSE(expr) \
     611             :      do { \
     612             :        if ((expr)) { \
     613             :          MOZ_ASSERT(false, #expr); \
     614             :        } else { \
     615             :          /* Do nothing. */ \
     616             :        } \
     617             :      } while (0)
     618             : #  define MOZ_ALWAYS_OK(expr)        MOZ_ASSERT((expr).isOk())
     619             : #  define MOZ_ALWAYS_ERR(expr)       MOZ_ASSERT((expr).isErr())
     620             : #else
     621             : #  define MOZ_ALWAYS_TRUE(expr) \
     622             :      do { \
     623             :        if ((expr)) { \
     624             :           /* Silence MOZ_MUST_USE. */ \
     625             :        } \
     626             :      } while (0)
     627             : #  define MOZ_ALWAYS_FALSE(expr) \
     628             :      do { \
     629             :        if ((expr)) { \
     630             :          /* Silence MOZ_MUST_USE. */ \
     631             :        } \
     632             :      } while (0)
     633             : #  define MOZ_ALWAYS_OK(expr) \
     634             :      do { \
     635             :        if ((expr).isOk()) { \
     636             :          /* Silence MOZ_MUST_USE. */ \
     637             :        } \
     638             :      } while (0)
     639             : #  define MOZ_ALWAYS_ERR(expr) \
     640             :      do { \
     641             :        if ((expr).isErr()) { \
     642             :          /* Silence MOZ_MUST_USE. */ \
     643             :        } \
     644             :      } while (0)
     645             : #endif
     646             : 
     647             : #undef MOZ_DUMP_ASSERTION_STACK
     648             : #undef MOZ_CRASH_CRASHREPORT
     649             : 
     650             : #endif /* mozilla_Assertions_h */

Generated by: LCOV version 1.13