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