Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
      3  * Copyright (C) 2013 Google Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #ifndef WTF_Assertions_h
     28 #define WTF_Assertions_h
     29 
     30 /*
     31    No namespaces because this file has to be includable from C and Objective-C.
     32 
     33    Note, this file uses many GCC extensions, but it should be compatible with
     34    C, Objective C, C++, and Objective C++.
     35 
     36    For non-debug builds, everything is disabled by default, except for the
     37    RELEASE_ASSERT family of macros.
     38 
     39    Defining any of the symbols explicitly prevents this from having any effect.
     40 
     41 */
     42 
     43 #include "wtf/Platform.h"
     44 
     45 #include <stddef.h>
     46 
     47 #if !COMPILER(MSVC)
     48 #include <inttypes.h>
     49 #endif
     50 
     51 #include "wtf/WTFExport.h"
     52 
     53 #ifdef NDEBUG
     54 /* Disable ASSERT* macros in release mode. */
     55 #define ASSERTIONS_DISABLED_DEFAULT 1
     56 #else
     57 #define ASSERTIONS_DISABLED_DEFAULT 0
     58 #endif
     59 
     60 #ifndef BACKTRACE_DISABLED
     61 #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
     62 #endif
     63 
     64 #ifndef ASSERT_DISABLED
     65 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
     66 #endif
     67 
     68 #ifndef ASSERT_MSG_DISABLED
     69 #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
     70 #endif
     71 
     72 #ifndef ASSERT_ARG_DISABLED
     73 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
     74 #endif
     75 
     76 #ifndef FATAL_DISABLED
     77 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
     78 #endif
     79 
     80 #ifndef ERROR_DISABLED
     81 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
     82 #endif
     83 
     84 #ifndef LOG_DISABLED
     85 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
     86 #endif
     87 
     88 #if COMPILER(GCC)
     89 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
     90 #else
     91 #define WTF_PRETTY_FUNCTION __FUNCTION__
     92 #endif
     93 
     94 /* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
     95    emits a warning when %@ is used in the format string.  Until <rdar://problem/5195437> is resolved we can't include
     96    the attribute when being used from Objective-C code in case it decides to use %@. */
     97 #if COMPILER(GCC) && !defined(__OBJC__)
     98 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
     99 #else
    100 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
    101 #endif
    102 
    103 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
    104 
    105 #ifdef __cplusplus
    106 extern "C" {
    107 #endif
    108 
    109 typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState;
    110 
    111 typedef struct {
    112     unsigned mask;
    113     const char *defaultName;
    114     WTFLogChannelState state;
    115 } WTFLogChannel;
    116 
    117 WTF_EXPORT void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
    118 WTF_EXPORT void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
    119 WTF_EXPORT void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
    120 WTF_EXPORT void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
    121 WTF_EXPORT void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
    122 WTF_EXPORT void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
    123 WTF_EXPORT void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
    124 WTF_EXPORT void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
    125 
    126 WTF_EXPORT void WTFGetBacktrace(void** stack, int* size);
    127 WTF_EXPORT void WTFReportBacktrace();
    128 WTF_EXPORT void WTFPrintBacktrace(void** stack, int size);
    129 
    130 typedef void (*WTFCrashHookFunction)();
    131 WTF_EXPORT void WTFSetCrashHook(WTFCrashHookFunction);
    132 WTF_EXPORT void WTFInvokeCrashHook();
    133 WTF_EXPORT void WTFInstallReportBacktraceOnCrashHook();
    134 
    135 #ifdef __cplusplus
    136 }
    137 #endif
    138 
    139 /* IMMEDIATE_CRASH() - Like CRASH() below but crashes in the fastest, simplest possible way with no attempt at logging. */
    140 #ifndef IMMEDIATE_CRASH
    141 #if COMPILER(GCC)
    142 #define IMMEDIATE_CRASH() __builtin_trap()
    143 #else
    144 #define IMMEDIATE_CRASH() ((void(*)())0)()
    145 #endif
    146 #endif
    147 
    148 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
    149 
    150    Use CRASH() in response to known, unrecoverable errors like out-of-memory.
    151    Macro is enabled in both debug and release mode.
    152    To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
    153 
    154    Signals are ignored by the crash reporter on OS X so we must do better.
    155 */
    156 #ifndef CRASH
    157 #define CRASH() \
    158     (WTFReportBacktrace(), \
    159      WTFInvokeCrashHook(), \
    160      (*(int *)(uintptr_t)0xbbadbeef = 0), \
    161      IMMEDIATE_CRASH())
    162 #endif
    163 
    164 #if COMPILER(CLANG)
    165 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
    166 #else
    167 #define NO_RETURN_DUE_TO_CRASH
    168 #endif
    169 
    170 /* BACKTRACE
    171 
    172   Print a backtrace to the same location as ASSERT messages.
    173 */
    174 #if BACKTRACE_DISABLED
    175 
    176 #define BACKTRACE() ((void)0)
    177 
    178 #else
    179 
    180 #define BACKTRACE() do { \
    181     WTFReportBacktrace(); \
    182 } while(false)
    183 
    184 #endif
    185 
    186 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
    187 
    188   These macros are compiled out of release builds.
    189   Expressions inside them are evaluated in debug builds only.
    190 */
    191 #if OS(WINDOWS)
    192 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
    193 #undef ASSERT
    194 #endif
    195 
    196 #if ASSERT_DISABLED
    197 
    198 #define ASSERT(assertion) ((void)0)
    199 #define ASSERT_AT(assertion, file, line, function) ((void)0)
    200 #define ASSERT_NOT_REACHED() ((void)0)
    201 #define NO_RETURN_DUE_TO_ASSERT
    202 
    203 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
    204 
    205 #else
    206 
    207 #define ASSERT(assertion) \
    208     (!(assertion) ? \
    209         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
    210          CRASH()) : \
    211         (void)0)
    212 
    213 #define ASSERT_AT(assertion, file, line, function) \
    214     (!(assertion) ? \
    215         (WTFReportAssertionFailure(file, line, function, #assertion), \
    216          CRASH()) :                                                   \
    217         (void)0)
    218 
    219 #define ASSERT_NOT_REACHED() do { \
    220     WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
    221     CRASH(); \
    222 } while (0)
    223 
    224 #define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
    225 
    226 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
    227 
    228 #endif
    229 
    230 /* ASSERT_WITH_SECURITY_IMPLICATION / RELEASE_ASSERT_WITH_SECURITY_IMPLICATION
    231 
    232    Use in places where failure of the assertion indicates a possible security
    233    vulnerability. Classes of these vulnerabilities include bad casts, out of
    234    bounds accesses, use-after-frees, etc. Please be sure to file bugs for these
    235    failures using the security template:
    236       http://code.google.com/p/chromium/issues/entry?template=Security%20Bug
    237 */
    238 #ifdef ADDRESS_SANITIZER
    239 
    240 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
    241     (!(assertion) ? \
    242         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
    243          CRASH()) : \
    244         (void)0)
    245 
    246 #define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
    247 
    248 #else
    249 
    250 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT(assertion)
    251 #define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) RELEASE_ASSERT(assertion)
    252 
    253 #endif
    254 
    255 /* ASSERT_WITH_MESSAGE */
    256 
    257 #if ASSERT_MSG_DISABLED
    258 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
    259 #else
    260 #define ASSERT_WITH_MESSAGE(assertion, ...) do \
    261     if (!(assertion)) { \
    262         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
    263         CRASH(); \
    264     } \
    265 while (0)
    266 #endif
    267 
    268 /* ASSERT_WITH_MESSAGE_UNUSED */
    269 
    270 #if ASSERT_MSG_DISABLED
    271 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
    272 #else
    273 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do \
    274     if (!(assertion)) { \
    275         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
    276         CRASH(); \
    277     } \
    278 while (0)
    279 #endif
    280 
    281 /* ASSERT_ARG */
    282 
    283 #if ASSERT_ARG_DISABLED
    284 
    285 #define ASSERT_ARG(argName, assertion) ((void)0)
    286 
    287 #else
    288 
    289 #define ASSERT_ARG(argName, assertion) do \
    290     if (!(assertion)) { \
    291         WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
    292         CRASH(); \
    293     } \
    294 while (0)
    295 
    296 #endif
    297 
    298 /* COMPILE_ASSERT */
    299 #ifndef COMPILE_ASSERT
    300 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
    301 /* Unlike static_assert below, this also works in plain C code. */
    302 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
    303 #elif COMPILER_SUPPORTS(CXX_STATIC_ASSERT)
    304 #define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
    305 #else
    306 #define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1]
    307 #endif
    308 #endif
    309 
    310 /* FATAL */
    311 
    312 #if FATAL_DISABLED
    313 #define FATAL(...) ((void)0)
    314 #else
    315 #define FATAL(...) do { \
    316     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
    317     CRASH(); \
    318 } while (0)
    319 #endif
    320 
    321 /* LOG_ERROR */
    322 
    323 #if ERROR_DISABLED
    324 #define LOG_ERROR(...) ((void)0)
    325 #else
    326 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
    327 #endif
    328 
    329 /* LOG */
    330 
    331 #if LOG_DISABLED
    332 #define LOG(channel, ...) ((void)0)
    333 #else
    334 #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
    335 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
    336 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
    337 #endif
    338 
    339 /* LOG_VERBOSE */
    340 
    341 #if LOG_DISABLED
    342 #define LOG_VERBOSE(channel, ...) ((void)0)
    343 #else
    344 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
    345 #endif
    346 
    347 /* UNREACHABLE_FOR_PLATFORM */
    348 
    349 #if COMPILER(CLANG)
    350 /* This would be a macro except that its use of #pragma works best around
    351    a function. Hence it uses macro naming convention. */
    352 #pragma clang diagnostic push
    353 #pragma clang diagnostic ignored "-Wmissing-noreturn"
    354 static inline void UNREACHABLE_FOR_PLATFORM()
    355 {
    356     ASSERT_NOT_REACHED();
    357 }
    358 #pragma clang diagnostic pop
    359 #else
    360 #define UNREACHABLE_FOR_PLATFORM() ASSERT_NOT_REACHED()
    361 #endif
    362 
    363 /* RELEASE_ASSERT
    364 
    365    Use in places where failure of an assertion indicates a definite security
    366    vulnerability from which execution must not continue even in a release build.
    367    Please sure to file bugs for these failures using the security template:
    368       http://code.google.com/p/chromium/issues/entry?template=Security%20Bug
    369 */
    370 
    371 #if ASSERT_DISABLED
    372 #define RELEASE_ASSERT(assertion) (UNLIKELY(!(assertion)) ? (IMMEDIATE_CRASH()) : (void)0)
    373 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
    374 #define RELEASE_ASSERT_NOT_REACHED() IMMEDIATE_CRASH()
    375 #else
    376 #define RELEASE_ASSERT(assertion) ASSERT(assertion)
    377 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
    378 #define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
    379 #endif
    380 
    381 #endif /* WTF_Assertions_h */
    382