b1a73f0d3570b9fc11e1b91692428f06de8ac416
[WebKit.git] / Source / WTF / wtf / Assertions.h
1 /*
2  * Copyright (C) 2003-2019 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #pragma once
27
28 #include <wtf/Platform.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 "always
37    on" logging. Defining any of the symbols explicitly prevents this from
38    having any effect.
39 */
40
41 #undef __STDC_FORMAT_MACROS
42 #define __STDC_FORMAT_MACROS
43 #include <inttypes.h>
44 #include <stdarg.h>
45 #include <stdbool.h>
46 #include <stddef.h>
47 #include <stdlib.h>
48 #include <wtf/ExportMacros.h>
49
50 #if USE(OS_LOG)
51 #include <os/log.h>
52 #endif
53
54 #ifdef __cplusplus
55 #include <cstdlib>
56 #include <type_traits>
57
58 #if OS(WINDOWS)
59 #if !COMPILER(GCC_COMPATIBLE)
60 extern "C" void _ReadWriteBarrier(void);
61 #pragma intrinsic(_ReadWriteBarrier)
62 #endif
63 #include <intrin.h>
64 #endif
65 #endif
66
67 /* ASSERT_ENABLED is defined in Platform.h. */
68
69 #ifndef BACKTRACE_DISABLED
70 #define BACKTRACE_DISABLED !ASSERT_ENABLED
71 #endif
72
73 #ifndef ASSERT_MSG_DISABLED
74 #define ASSERT_MSG_DISABLED !ASSERT_ENABLED
75 #endif
76
77 #ifndef ASSERT_ARG_DISABLED
78 #define ASSERT_ARG_DISABLED !ASSERT_ENABLED
79 #endif
80
81 #ifndef FATAL_DISABLED
82 #define FATAL_DISABLED !ASSERT_ENABLED
83 #endif
84
85 #ifndef ERROR_DISABLED
86 #define ERROR_DISABLED !ASSERT_ENABLED
87 #endif
88
89 #ifndef LOG_DISABLED
90 #define LOG_DISABLED !ASSERT_ENABLED
91 #endif
92
93 #ifndef RELEASE_LOG_DISABLED
94 #define RELEASE_LOG_DISABLED !(USE(OS_LOG))
95 #endif
96
97 #if COMPILER(GCC_COMPATIBLE)
98 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
99 #else
100 #define WTF_PRETTY_FUNCTION __FUNCTION__
101 #endif
102
103 #if COMPILER(MINGW)
104 /* By default MinGW emits warnings when C99 format attributes are used, even if __USE_MINGW_ANSI_STDIO is defined */
105 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(gnu_printf, formatStringArgument, extraArguments)))
106 #elif COMPILER(GCC_COMPATIBLE) && !defined(__OBJC__)
107 /* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
108    emits a warning when %@ is used in the format string.  Until <rdar://problem/5195437> is resolved we can't include
109    the attribute when being used from Objective-C code in case it decides to use %@. */
110 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
111 #else
112 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
113 #endif
114
115 #if PLATFORM(IOS_FAMILY)
116 /* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
117 #ifndef WTF_EXPORT_PRIVATE
118 #define WTF_EXPORT_PRIVATE
119 #endif
120 #endif // PLATFORM(IOS_FAMILY)
121
122 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
123
124 #ifdef __cplusplus
125 extern "C" {
126 #endif
127
128 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
129
130    Use CRASH() in response to known, unrecoverable errors like out-of-memory.
131    Macro is enabled in both debug and release mode.
132    To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
133
134    Signals are ignored by the crash reporter on OS X so we must do better.
135 */
136 #if COMPILER(GCC_COMPATIBLE) || COMPILER(MSVC)
137 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
138 #else
139 #define NO_RETURN_DUE_TO_CRASH
140 #endif
141
142 #ifdef __cplusplus
143 enum class WTFLogChannelState : uint8_t { Off, On, OnWithAccumulation };
144 #undef Always
145 enum class WTFLogLevel : uint8_t { Always, Error, Warning, Info, Debug };
146 #else
147 typedef uint8_t WTFLogChannelState;
148 typedef uint8_t WTFLogLevel;
149 #endif
150
151 typedef struct {
152     WTFLogChannelState state;
153     const char* name;
154     WTFLogLevel level;
155 #if !RELEASE_LOG_DISABLED
156     const char* subsystem;
157     __unsafe_unretained os_log_t osLogChannel;
158 #endif
159 } WTFLogChannel;
160
161 #define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
162 #define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
163 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
164 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
165
166 #define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
167
168 #define DECLARE_LOG_CHANNEL(name) \
169     extern WTFLogChannel LOG_CHANNEL(name);
170
171 #if !defined(DEFINE_LOG_CHANNEL)
172 #if RELEASE_LOG_DISABLED
173 #define DEFINE_LOG_CHANNEL(name, subsystem) \
174     WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1 };
175 #else
176 #define DEFINE_LOG_CHANNEL(name, subsystem) \
177     WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1, subsystem, OS_LOG_DEFAULT };
178 #endif
179 #endif
180
181 WTF_EXPORT_PRIVATE void WTFReportNotImplementedYet(const char* file, int line, const char* function);
182 WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
183 WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
184 WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
185 WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
186 WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
187 WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
188 WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
189 WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
190 WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
191 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
192 WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
193 WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
194 WTF_EXPORT_PRIVATE void WTFLogWithLevel(WTFLogChannel*, WTFLogLevel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(3, 4);
195 WTF_EXPORT_PRIVATE void WTFSetLogChannelLevel(WTFLogChannel*, WTFLogLevel);
196 WTF_EXPORT_PRIVATE bool WTFWillLogWithLevel(WTFLogChannel*, WTFLogLevel);
197
198 WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
199 WTF_EXPORT_PRIVATE void WTFReportBacktrace(void);
200 WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
201 #if !RELEASE_LOG_DISABLED
202 WTF_EXPORT_PRIVATE void WTFReleaseLogStackTrace(WTFLogChannel*);
203 #endif
204
205 WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached(void);
206
207 #if COMPILER(MSVC)
208 #define WTFBreakpointTrap()  __debugbreak()
209 #elif ASAN_ENABLED
210 #define WTFBreakpointTrap()  __builtin_trap()
211 #elif CPU(X86_64) || CPU(X86)
212 #define WTFBreakpointTrap()  asm volatile ("int3")
213 #elif CPU(ARM_THUMB2)
214 #define WTFBreakpointTrap()  asm volatile ("bkpt #0")
215 #elif CPU(ARM64)
216 #define WTFBreakpointTrap()  asm volatile ("brk #0")
217 #else
218 #define WTFBreakpointTrap() WTFCrash() // Not implemented.
219 #endif
220
221 #if COMPILER(MSVC)
222 #define WTFBreakpointTrapUnderConstexprContext() __debugbreak()
223 #else
224 #define WTFBreakpointTrapUnderConstexprContext() __builtin_trap()
225 #endif
226
227 #ifndef CRASH
228
229 #if defined(NDEBUG) && (OS(DARWIN) || PLATFORM(PLAYSTATION))
230 // Crash with a SIGTRAP i.e EXC_BREAKPOINT.
231 // We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
232 // trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
233 #define CRASH() do { \
234     WTFBreakpointTrap(); \
235     __builtin_unreachable(); \
236 } while (0)
237 #define CRASH_UNDER_CONSTEXPR_CONTEXT() do { \
238     WTFBreakpointTrapUnderConstexprContext(); \
239     __builtin_unreachable(); \
240 } while (0)
241 #elif !ENABLE(DEVELOPER_MODE) && !OS(DARWIN)
242 #ifdef __cplusplus
243 #define CRASH() std::abort()
244 #define CRASH_UNDER_CONSTEXPR_CONTEXT() std::abort()
245 #else
246 #define CRASH() abort()
247 #define CRASH_UNDER_CONSTEXPR_CONTEXT() abort()
248 #endif // __cplusplus
249 #else
250 #define CRASH() WTFCrash()
251 #define CRASH_UNDER_CONSTEXPR_CONTEXT() WTFCrash()
252 #endif
253
254 #endif // !defined(CRASH)
255
256 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash(void);
257
258 #ifndef CRASH_WITH_SECURITY_IMPLICATION
259 #define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
260 #endif
261
262 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication(void);
263
264 #ifdef __cplusplus
265 }
266 #endif
267
268 /* BACKTRACE
269
270   Print a backtrace to the same location as ASSERT messages.
271 */
272
273 #if BACKTRACE_DISABLED
274
275 #define BACKTRACE() ((void)0)
276
277 #else
278
279 #define BACKTRACE() do { \
280     WTFReportBacktrace(); \
281 } while(false)
282
283 #endif
284
285 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
286
287   These macros are compiled out of release builds.
288   Expressions inside them are evaluated in debug builds only.
289 */
290
291 #if OS(WINDOWS)
292 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
293 #undef ASSERT
294 #endif
295
296 #if !ASSERT_ENABLED
297
298 #define ASSERT(assertion, ...) ((void)0)
299 #define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ((void)0)
300 #define ASSERT_AT(assertion, file, line, function) ((void)0)
301 #define ASSERT_NOT_REACHED(...) ((void)0)
302 #define ASSERT_NOT_IMPLEMENTED_YET() ((void)0)
303 #define ASSERT_IMPLIES(condition, assertion) ((void)0)
304 #define NO_RETURN_DUE_TO_ASSERT
305
306 #define ASSERT_UNUSED(variable, assertion, ...) ((void)variable)
307
308 #if ENABLE(SECURITY_ASSERTIONS)
309 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
310     (!(assertion) ? \
311         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
312          CRASH_WITH_SECURITY_IMPLICATION()) : \
313         (void)0)
314
315 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
316 #else /* not ENABLE(SECURITY_ASSERTIONS) */
317 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
318 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
319 #endif /* ENABLE(SECURITY_ASSERTIONS) */
320
321 #else /* ASSERT_ENABLED */
322
323 #define ASSERT(assertion, ...) do { \
324     if (!(assertion)) { \
325         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
326         CRASH_WITH_INFO(__VA_ARGS__); \
327     } \
328 } while (0)
329
330 #define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
331     if (!(assertion)) { \
332         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
333         CRASH_UNDER_CONSTEXPR_CONTEXT(); \
334     } \
335 } while (0)
336
337 #define ASSERT_AT(assertion, file, line, function) do { \
338     if (!(assertion)) { \
339         WTFReportAssertionFailure(file, line, function, #assertion); \
340         CRASH(); \
341     } \
342 } while (0)
343
344 #define ASSERT_NOT_REACHED(...) do { \
345     WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
346     CRASH_WITH_INFO(__VA_ARGS__); \
347 } while (0)
348
349 #define ASSERT_NOT_IMPLEMENTED_YET() do { \
350     WTFReportNotImplementedYet(__FILE__, __LINE__, WTF_PRETTY_FUNCTION); \
351     CRASH(); \
352 } while (0)
353
354 #define ASSERT_IMPLIES(condition, assertion) do { \
355     if ((condition) && !(assertion)) { \
356         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition " => " #assertion); \
357         CRASH(); \
358     } \
359 } while (0)
360
361 #define ASSERT_UNUSED(variable, assertion, ...) ASSERT(assertion, __VA_ARGS__)
362
363 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
364
365 /* ASSERT_WITH_SECURITY_IMPLICATION
366  
367    Failure of this assertion indicates a possible security vulnerability.
368    Class of vulnerabilities that it tests include bad casts, out of bounds
369    accesses, use-after-frees, etc. Please file a bug using the security
370    template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
371  
372 */
373 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
374     (!(assertion) ? \
375         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
376          CRASH_WITH_SECURITY_IMPLICATION()) : \
377         (void)0)
378 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
379
380 #endif /* ASSERT_ENABLED */
381
382 /* ASSERT_WITH_MESSAGE */
383
384 #if ASSERT_MSG_DISABLED
385 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
386 #else
387 #define ASSERT_WITH_MESSAGE(assertion, ...) do { \
388     if (!(assertion)) { \
389         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
390         CRASH(); \
391     } \
392 } while (0)
393 #endif
394
395 #ifdef __cplusplus
396 constexpr bool assertionFailureDueToUnreachableCode = false;
397 #define ASSERT_NOT_REACHED_WITH_MESSAGE(...) ASSERT_WITH_MESSAGE(assertionFailureDueToUnreachableCode, __VA_ARGS__)
398 #endif
399
400 /* ASSERT_WITH_MESSAGE_UNUSED */
401
402 #if ASSERT_MSG_DISABLED
403 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
404 #else
405 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
406     if (!(assertion)) { \
407         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
408         CRASH(); \
409     } \
410 } while (0)
411 #endif
412                         
413                         
414 /* ASSERT_ARG */
415
416 #if ASSERT_ARG_DISABLED
417
418 #define ASSERT_ARG(argName, assertion) ((void)0)
419
420 #else
421
422 #define ASSERT_ARG(argName, assertion) do { \
423     if (!(assertion)) { \
424         WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
425         CRASH(); \
426     } \
427 } while (0)
428
429 #endif
430
431 /* COMPILE_ASSERT */
432 #ifndef COMPILE_ASSERT
433 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
434 /* Unlike static_assert below, this also works in plain C code. */
435 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
436 #else
437 #define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
438 #endif
439 #endif
440
441 /* FATAL */
442
443 #if FATAL_DISABLED
444 #define FATAL(...) ((void)0)
445 #else
446 #define FATAL(...) do { \
447     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
448     CRASH(); \
449 } while (0)
450 #endif
451
452 /* LOG_ERROR */
453
454 #if ERROR_DISABLED
455 #define LOG_ERROR(...) ((void)0)
456 #else
457 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
458 #endif
459
460 /* LOG */
461
462 #if LOG_DISABLED
463 #define LOG(channel, ...) ((void)0)
464 #else
465 #define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
466 #endif
467
468 /* LOG_VERBOSE */
469
470 #if LOG_DISABLED
471 #define LOG_VERBOSE(channel, ...) ((void)0)
472 #else
473 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
474 #endif
475
476 /* LOG_WITH_LEVEL */
477
478 #if LOG_DISABLED
479 #define LOG_WITH_LEVEL(channel, level, ...) ((void)0)
480 #else
481 #define LOG_WITH_LEVEL(channel, level, ...) WTFLogWithLevel(&LOG_CHANNEL(channel), level, __VA_ARGS__)
482 #endif
483
484 /* RELEASE_LOG */
485
486 #if RELEASE_LOG_DISABLED
487 #define PUBLIC_LOG_STRING "s"
488 #define RELEASE_LOG(channel, ...) ((void)0)
489 #define RELEASE_LOG_ERROR(channel, ...) LOG_ERROR(__VA_ARGS__)
490 #define RELEASE_LOG_FAULT(channel, ...) LOG_ERROR(__VA_ARGS__)
491 #define RELEASE_LOG_INFO(channel, ...) ((void)0)
492
493 #define RELEASE_LOG_IF(isAllowed, channel, ...) ((void)0)
494 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
495 #define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) ((void)0)
496
497 #define RELEASE_LOG_WITH_LEVEL(channel, level, ...) ((void)0)
498 #define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, level, ...) do { if (isAllowed) RELEASE_LOG_WITH_LEVEL(channel, level, __VA_ARGS__); } while (0)
499
500 #define RELEASE_LOG_STACKTRACE(channel) ((void)0)
501 #else
502 #define PUBLIC_LOG_STRING "{public}s"
503 #define RELEASE_LOG(channel, ...) os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
504 #define RELEASE_LOG_ERROR(channel, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
505 #define RELEASE_LOG_FAULT(channel, ...) os_log_fault(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
506 #define RELEASE_LOG_INFO(channel, ...) os_log_info(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
507
508 #define RELEASE_LOG_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG(      channel, __VA_ARGS__); } while (0)
509 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
510 #define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_INFO(channel, __VA_ARGS__); } while (0)
511
512 #define RELEASE_LOG_WITH_LEVEL(channel, logLevel, ...) do { \
513     if (LOG_CHANNEL(channel).level >= (logLevel)) \
514         os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
515 } while (0)
516
517 #define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, logLevel, ...) do { \
518     if ((isAllowed) && LOG_CHANNEL(channel).level >= (logLevel)) \
519         os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
520 } while (0)
521
522 #define RELEASE_LOG_STACKTRACE(channel) WTFReleaseLogStackTrace(&LOG_CHANNEL(channel))
523 #endif
524
525
526 /* RELEASE_ASSERT */
527
528 #if !ASSERT_ENABLED
529
530 #define RELEASE_ASSERT(assertion, ...) do { \
531     if (UNLIKELY(!(assertion))) \
532         CRASH_WITH_INFO(__VA_ARGS__); \
533 } while (0)
534 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
535 #define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) RELEASE_ASSERT(assertion)
536 #define RELEASE_ASSERT_NOT_REACHED(...) CRASH_WITH_INFO(__VA_ARGS__)
537 #define RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
538     if (UNLIKELY(!(assertion))) { \
539         CRASH_UNDER_CONSTEXPR_CONTEXT(); \
540     } \
541 } while (0)
542
543 #else /* ASSERT_ENABLED */
544
545 #define RELEASE_ASSERT(assertion, ...) ASSERT(assertion, __VA_ARGS__)
546 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
547 #define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
548 #define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
549 #define RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion)
550
551 #endif /* ASSERT_ENABLED */
552
553 #ifdef __cplusplus
554 #define RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE(...) RELEASE_ASSERT_WITH_MESSAGE(assertionFailureDueToUnreachableCode, __VA_ARGS__)
555
556 // The combination of line, file, function, and counter should be a unique number per call to this crash. This tricks the compiler into not coalescing calls to WTFCrashWithInfo.
557 // The easiest way to fill these values per translation unit is to pass __LINE__, __FILE__, WTF_PRETTY_FUNCTION, and __COUNTER__.
558 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5, uint64_t misc6);
559 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5);
560 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4);
561 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3);
562 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2);
563 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1);
564 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason);
565 NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter);
566
567 template<typename T>
568 ALWAYS_INLINE uint64_t wtfCrashArg(T* arg) { return reinterpret_cast<uintptr_t>(arg); }
569
570 template<typename T>
571 ALWAYS_INLINE uint64_t wtfCrashArg(T arg) { return arg; }
572
573 template<typename T>
574 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason)
575 {
576     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
577 }
578
579 template<typename T, typename U>
580 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1)
581 {
582     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1));
583 }
584
585 template<typename T, typename U, typename V>
586 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2)
587 {
588     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2));
589 }
590
591 template<typename T, typename U, typename V, typename W>
592 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3)
593 {
594     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3));
595 }
596
597 template<typename T, typename U, typename V, typename W, typename X>
598 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4)
599 {
600     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4));
601 }
602
603 template<typename T, typename U, typename V, typename W, typename X, typename Y>
604 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4, Y misc5)
605 {
606     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4), wtfCrashArg(misc5));
607 }
608
609 template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
610 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4, Y misc5, Z misc6)
611 {
612     WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4), wtfCrashArg(misc5), wtfCrashArg(misc6));
613 }
614
615 inline void WTFCrashWithInfo(int, const char*, const char*, int)
616 #if COMPILER(CLANG)
617     __attribute__((optnone))
618 #endif
619 {
620     CRASH();
621 }
622
623 namespace WTF {
624 inline void isIntegralOrPointerType() { }
625
626 template<typename T, typename... Types>
627 void isIntegralOrPointerType(T, Types... types)
628 {
629     static_assert(std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value, "All types need to be bitwise_cast-able to integral type for logging");
630     isIntegralOrPointerType(types...);
631 }
632 }
633
634 inline void compilerFenceForCrash()
635 {
636 #if OS(WINDOWS) && !COMPILER(GCC_COMPATIBLE)
637     _ReadWriteBarrier();
638 #else
639     asm volatile("" ::: "memory");
640 #endif
641 }
642
643 #ifndef CRASH_WITH_INFO
644 // This is useful if you are going to stuff data into registers before crashing, like the
645 // crashWithInfo functions below.
646 #if COMPILER(CLANG) || COMPILER(MSVC)
647 #define CRASH_WITH_INFO(...) do { \
648         WTF::isIntegralOrPointerType(__VA_ARGS__); \
649         compilerFenceForCrash(); \
650         WTFCrashWithInfo(__LINE__, __FILE__, WTF_PRETTY_FUNCTION, __COUNTER__, ##__VA_ARGS__); \
651     } while (false)
652 #else
653 // GCC does not allow ##__VA_ARGS__ unless GNU extensions are enabled (--std=gnu++NN instead of
654 // --std=c++NN) and I think we don't want that, so we'll have a fallback path for GCC. Obviously
655 // this will not actually succeed at getting the desired info into registers before crashing, but
656 // it's just a fallback anyway.
657 //
658 // FIXME: When we enable C++20, we should replace ##__VA_ARGS__ with format __VA_OPT__(,) __VA_ARGS__
659 // so that we can remove this fallback.
660 inline NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(...)
661 {
662     CRASH();
663 }
664
665 // We must define this here because CRASH_WITH_INFO() is not defined as a macro.
666 // FIXME: Remove this when upgrading to C++20.
667 inline NO_RETURN_DUE_TO_CRASH void CRASH_WITH_SECURITY_IMPLICATION_AND_INFO(...)
668 {
669     CRASH();
670 }
671 #endif
672 #endif // CRASH_WITH_INFO
673
674 #ifndef CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
675 #define CRASH_WITH_SECURITY_IMPLICATION_AND_INFO CRASH_WITH_INFO
676 #endif // CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
677
678 #else /* not __cplusplus */
679
680 #ifndef CRASH_WITH_INFO
681 #define CRASH_WITH_INFO() CRASH()
682 #endif
683
684 #endif /* __cplusplus */
685
686 /* UNREACHABLE_FOR_PLATFORM */
687
688 #if COMPILER(CLANG)
689 // This would be a macro except that its use of #pragma works best around
690 // a function. Hence it uses macro naming convention.
691 IGNORE_WARNINGS_BEGIN("missing-noreturn")
692 static inline void UNREACHABLE_FOR_PLATFORM()
693 {
694     // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
695     // going.
696     RELEASE_ASSERT_NOT_REACHED();
697 }
698 IGNORE_WARNINGS_END
699 #else
700 #define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
701 #endif