2 * Copyright (C) 2003, 2006, 2007, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef WTF_Assertions_h
27 #define WTF_Assertions_h
29 #include <wtf/Platform.h>
32 no namespaces because this file has to be includable from C and Objective-C
34 Note, this file uses many GCC extensions, but it should be compatible with
35 C, Objective C, C++, and Objective C++.
37 For non-debug builds, everything is disabled by default except for "always
38 on" logging. Defining any of the symbols explicitly prevents this from
42 #undef __STDC_FORMAT_MACROS
43 #define __STDC_FORMAT_MACROS
48 #include <wtf/ExportMacros.h>
55 /* Disable ASSERT* macros in release mode. */
56 #define ASSERTIONS_DISABLED_DEFAULT 1
58 #define ASSERTIONS_DISABLED_DEFAULT 0
61 #ifndef BACKTRACE_DISABLED
62 #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
65 #ifndef ASSERT_DISABLED
66 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
69 #ifndef ASSERT_MSG_DISABLED
70 #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
73 #ifndef ASSERT_ARG_DISABLED
74 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
77 #ifndef FATAL_DISABLED
78 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
81 #ifndef ERROR_DISABLED
82 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
86 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
89 #ifndef RELEASE_LOG_DISABLED
90 #define RELEASE_LOG_DISABLED !(USE(OS_LOG))
93 #if COMPILER(GCC_OR_CLANG)
94 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
96 #define WTF_PRETTY_FUNCTION __FUNCTION__
100 /* By default MinGW emits warnings when C99 format attributes are used, even if __USE_MINGW_ANSI_STDIO is defined */
101 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(gnu_printf, formatStringArgument, extraArguments)))
102 #elif COMPILER(GCC_OR_CLANG) && !defined(__OBJC__)
103 /* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
104 emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
105 the attribute when being used from Objective-C code in case it decides to use %@. */
106 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
108 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
112 /* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
113 #ifndef WTF_EXPORT_PRIVATE
114 #define WTF_EXPORT_PRIVATE
116 #endif // PLATFORM(IOS)
118 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
124 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
126 Use CRASH() in response to known, unrecoverable errors like out-of-memory.
127 Macro is enabled in both debug and release mode.
128 To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
130 Signals are ignored by the crash reporter on OS X so we must do better.
132 #if COMPILER(GCC_OR_CLANG) || COMPILER(MSVC)
133 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
135 #define NO_RETURN_DUE_TO_CRASH
138 typedef enum { WTFLogChannelOff, WTFLogChannelOn, WTFLogChannelOnWithAccumulation } WTFLogChannelState;
141 WTFLogChannelState state;
143 #if !RELEASE_LOG_DISABLED
144 const char* subsystem;
145 __unsafe_unretained os_log_t osLogChannel;
149 #define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
150 #define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
151 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
152 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
154 #define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
156 #define DECLARE_LOG_CHANNEL(name) \
157 extern WTFLogChannel LOG_CHANNEL(name);
159 #if !defined(DEFINE_LOG_CHANNEL)
160 #if RELEASE_LOG_DISABLED
161 #define DEFINE_LOG_CHANNEL(name, subsystem) \
162 WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name };
164 #define DEFINE_LOG_CHANNEL(name, subsystem) \
165 WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name, subsystem, OS_LOG_DEFAULT };
169 WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
170 WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
171 WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
172 WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
173 WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
174 WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
175 WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
176 WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
177 WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
178 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
179 WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
180 WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
182 WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
183 WTF_EXPORT_PRIVATE void WTFReportBacktrace();
184 WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
186 typedef void (*WTFCrashHookFunction)();
187 WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
188 WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook();
190 WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached();
192 #if CPU(X86_64) || CPU(X86)
193 #define WTFBreakpointTrap() __asm__ volatile ("int3")
194 #elif CPU(ARM_THUMB2)
195 #define WTFBreakpointTrap() __asm__ volatile ("bkpt #0")
197 #define WTFBreakpointTrap() __asm__ volatile ("brk #0")
199 #define WTFBreakpointTrap() WTFCrash() // Not implemented.
204 #if defined(NDEBUG) && OS(DARWIN)
205 // Crash with a SIGTRAP i.e EXC_BREAKPOINT.
206 // We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
207 // trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
208 #define CRASH() do { \
209 WTFBreakpointTrap(); \
210 __builtin_unreachable(); \
213 #define CRASH() WTFCrash()
216 #endif // !defined(CRASH)
218 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash();
220 #ifndef CRASH_WITH_SECURITY_IMPLICATION
221 #define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
224 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication();
232 Print a backtrace to the same location as ASSERT messages.
235 #if BACKTRACE_DISABLED
237 #define BACKTRACE() ((void)0)
241 #define BACKTRACE() do { \
242 WTFReportBacktrace(); \
247 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
249 These macros are compiled out of release builds.
250 Expressions inside them are evaluated in debug builds only.
254 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
260 #define ASSERT(assertion) ((void)0)
261 #define ASSERT_AT(assertion, file, line, function) ((void)0)
262 #define ASSERT_NOT_REACHED() ((void)0)
263 #define ASSERT_IMPLIES(condition, assertion) ((void)0)
264 #define NO_RETURN_DUE_TO_ASSERT
266 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
268 #if ENABLE(SECURITY_ASSERTIONS)
269 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
271 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
272 CRASH_WITH_SECURITY_IMPLICATION()) : \
275 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
277 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
278 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
283 #define ASSERT(assertion) do { \
284 if (!(assertion)) { \
285 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
290 #define ASSERT_AT(assertion, file, line, function) do { \
291 if (!(assertion)) { \
292 WTFReportAssertionFailure(file, line, function, #assertion); \
297 #define ASSERT_NOT_REACHED() do { \
298 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
302 #define ASSERT_IMPLIES(condition, assertion) do { \
303 if ((condition) && !(assertion)) { \
304 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition " => " #assertion); \
309 #define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
311 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
313 /* ASSERT_WITH_SECURITY_IMPLICATION
315 Failure of this assertion indicates a possible security vulnerability.
316 Class of vulnerabilities that it tests include bad casts, out of bounds
317 accesses, use-after-frees, etc. Please file a bug using the security
318 template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
321 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
323 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
324 CRASH_WITH_SECURITY_IMPLICATION()) : \
326 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
329 /* ASSERT_WITH_MESSAGE */
331 #if ASSERT_MSG_DISABLED
332 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
334 #define ASSERT_WITH_MESSAGE(assertion, ...) do { \
335 if (!(assertion)) { \
336 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
342 /* ASSERT_WITH_MESSAGE_UNUSED */
344 #if ASSERT_MSG_DISABLED
345 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
347 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
348 if (!(assertion)) { \
349 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
358 #if ASSERT_ARG_DISABLED
360 #define ASSERT_ARG(argName, assertion) ((void)0)
364 #define ASSERT_ARG(argName, assertion) do { \
365 if (!(assertion)) { \
366 WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
374 #ifndef COMPILE_ASSERT
375 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
376 /* Unlike static_assert below, this also works in plain C code. */
377 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
379 #define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
386 #define FATAL(...) ((void)0)
388 #define FATAL(...) do { \
389 WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
397 #define LOG_ERROR(...) ((void)0)
399 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
405 #define LOG(channel, ...) ((void)0)
407 #define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
413 #define LOG_VERBOSE(channel, ...) ((void)0)
415 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
420 #if RELEASE_LOG_DISABLED
421 #define RELEASE_LOG( channel, format, ...) ((void)0)
422 #define RELEASE_LOG_ERROR(channel, format, ...) LOG_ERROR(format, ##__VA_ARGS__)
424 #define RELEASE_LOG_IF( isAllowed, channel, format, ...) ((void)0)
425 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
427 #define RELEASE_LOG( channel, format, ...) os_log( LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
428 #define RELEASE_LOG_ERROR(channel, format, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
430 #define RELEASE_LOG_IF( isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG( channel, format, ##__VA_ARGS__); } while (0)
431 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
438 #define RELEASE_ASSERT(assertion) do { \
439 if (UNLIKELY(!(assertion))) \
442 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
443 #define RELEASE_ASSERT_NOT_REACHED() CRASH()
445 #define RELEASE_ASSERT(assertion) ASSERT(assertion)
446 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
447 #define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
450 /* UNREACHABLE_FOR_PLATFORM */
453 // This would be a macro except that its use of #pragma works best around
454 // a function. Hence it uses macro naming convention.
455 #pragma clang diagnostic push
456 #pragma clang diagnostic ignored "-Wmissing-noreturn"
457 static inline void UNREACHABLE_FOR_PLATFORM()
459 // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
461 RELEASE_ASSERT_NOT_REACHED();
463 #pragma clang diagnostic pop
465 #define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
469 #endif /* WTF_Assertions_h */