1/*
2 * Copyright (C) 2003-2017 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)
60extern "C" void _ReadWriteBarrier(void);
61#pragma intrinsic(_ReadWriteBarrier)
62#endif
63#include <intrin.h>
64#endif
65#endif
66
67#ifdef NDEBUG
68/* Disable ASSERT* macros in release mode. */
69#define ASSERTIONS_DISABLED_DEFAULT 1
70#else
71#define ASSERTIONS_DISABLED_DEFAULT 0
72#endif
73
74#ifndef BACKTRACE_DISABLED
75#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
76#endif
77
78#ifndef ASSERT_DISABLED
79#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
80#endif
81
82#ifndef ASSERT_MSG_DISABLED
83#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
84#endif
85
86#ifndef ASSERT_ARG_DISABLED
87#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
88#endif
89
90#ifndef FATAL_DISABLED
91#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
92#endif
93
94#ifndef ERROR_DISABLED
95#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
96#endif
97
98#ifndef LOG_DISABLED
99#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
100#endif
101
102#ifndef RELEASE_LOG_DISABLED
103#define RELEASE_LOG_DISABLED !(USE(OS_LOG))
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
134extern "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
152enum class WTFLogChannelState : uint8_t { Off, On, OnWithAccumulation };
153#undef Always
154enum class WTFLogLevel : uint8_t { Always, Error, Warning, Info, Debug };
155#else
156typedef uint8_t WTFLogChannelState;
157typedef uint8_t WTFLogLevel;
158#endif
159
160typedef struct {
161 WTFLogChannelState state;
162 const char* name;
163 WTFLogLevel level;
164#if !RELEASE_LOG_DISABLED
165 const char* subsystem;
166 __unsafe_unretained os_log_t osLogChannel;
167#endif
168} WTFLogChannel;
169
170#define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
171#define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
172#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
173#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
174
175#define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
176
177#define DECLARE_LOG_CHANNEL(name) \
178 extern WTFLogChannel LOG_CHANNEL(name);
179
180#if !defined(DEFINE_LOG_CHANNEL)
181#if RELEASE_LOG_DISABLED
182#define DEFINE_LOG_CHANNEL(name, subsystem) \
183 WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1 };
184#else
185#define DEFINE_LOG_CHANNEL(name, subsystem) \
186 WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1, subsystem, OS_LOG_DEFAULT };
187#endif
188#endif
189
190WTF_EXPORT_PRIVATE void WTFReportNotImplementedYet(const char* file, int line, const char* function);
191WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
192WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
193WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
194WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
195WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
196WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
197WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
198WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
199WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
200WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
201WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
202WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
203WTF_EXPORT_PRIVATE void WTFLogWithLevel(WTFLogChannel*, WTFLogLevel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(3, 4);
204WTF_EXPORT_PRIVATE void WTFSetLogChannelLevel(WTFLogChannel*, WTFLogLevel);
205WTF_EXPORT_PRIVATE bool WTFWillLogWithLevel(WTFLogChannel*, WTFLogLevel);
206
207WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
208WTF_EXPORT_PRIVATE void WTFReportBacktrace(void);
209WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
210#if !RELEASE_LOG_DISABLED
211WTF_EXPORT_PRIVATE void WTFReleaseLogStackTrace(WTFLogChannel*);
212#endif
213
214WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached(void);
215
216#if COMPILER(MSVC)
217#define WTFBreakpointTrap() __debugbreak()
218#elif ASAN_ENABLED
219#define WTFBreakpointTrap() __builtin_trap()
220#elif CPU(X86_64) || CPU(X86)
221#define WTFBreakpointTrap() asm volatile ("int3")
222#elif CPU(ARM_THUMB2)
223#define WTFBreakpointTrap() asm volatile ("bkpt #0")
224#elif CPU(ARM64)
225#define WTFBreakpointTrap() asm volatile ("brk #0")
226#else
227#define WTFBreakpointTrap() WTFCrash() // Not implemented.
228#endif
229
230#if COMPILER(MSVC)
231#define WTFBreakpointTrapUnderConstexprContext() __debugbreak()
232#else
233#define WTFBreakpointTrapUnderConstexprContext() __builtin_trap()
234#endif
235
236#ifndef CRASH
237
238#if defined(NDEBUG) && (OS(DARWIN) || PLATFORM(PLAYSTATION))
239// Crash with a SIGTRAP i.e EXC_BREAKPOINT.
240// We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
241// trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
242#define CRASH() do { \
243 WTFBreakpointTrap(); \
244 __builtin_unreachable(); \
245} while (0)
246#define CRASH_UNDER_CONSTEXPR_CONTEXT() do { \
247 WTFBreakpointTrapUnderConstexprContext(); \
248 __builtin_unreachable(); \
249} while (0)
250#elif !ENABLE(DEVELOPER_MODE) && !OS(DARWIN)
251#ifdef __cplusplus
252#define CRASH() std::abort()
253#define CRASH_UNDER_CONSTEXPR_CONTEXT() std::abort()
254#else
255#define CRASH() abort()
256#define CRASH_UNDER_CONSTEXPR_CONTEXT() abort()
257#endif // __cplusplus
258#else
259#define CRASH() WTFCrash()
260#define CRASH_UNDER_CONSTEXPR_CONTEXT() WTFCrash()
261#endif
262
263#endif // !defined(CRASH)
264
265WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash(void);
266
267#ifndef CRASH_WITH_SECURITY_IMPLICATION
268#define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
269#endif
270
271WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication(void);
272
273#ifdef __cplusplus
274}
275#endif
276
277/* BACKTRACE
278
279 Print a backtrace to the same location as ASSERT messages.
280*/
281
282#if BACKTRACE_DISABLED
283
284#define BACKTRACE() ((void)0)
285
286#else
287
288#define BACKTRACE() do { \
289 WTFReportBacktrace(); \
290} while(false)
291
292#endif
293
294/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
295
296 These macros are compiled out of release builds.
297 Expressions inside them are evaluated in debug builds only.
298*/
299
300#if OS(WINDOWS)
301/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
302#undef ASSERT
303#endif
304
305#if ASSERT_DISABLED
306
307#define ASSERT(assertion, ...) ((void)0)
308#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ((void)0)
309#define ASSERT_AT(assertion, file, line, function) ((void)0)
310#define ASSERT_NOT_REACHED(...) ((void)0)
311#define ASSERT_NOT_IMPLEMENTED_YET() ((void)0)
312#define ASSERT_IMPLIES(condition, assertion) ((void)0)
313#define NO_RETURN_DUE_TO_ASSERT
314
315#define ASSERT_UNUSED(variable, assertion, ...) ((void)variable)
316
317#if ENABLE(SECURITY_ASSERTIONS)
318#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
319 (!(assertion) ? \
320 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
321 CRASH_WITH_SECURITY_IMPLICATION()) : \
322 (void)0)
323
324#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
325#else
326#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
327#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
328#endif
329
330#else
331
332#define ASSERT(assertion, ...) do { \
333 if (!(assertion)) { \
334 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
335 CRASH_WITH_INFO(__VA_ARGS__); \
336 } \
337} while (0)
338
339#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
340 if (!(assertion)) { \
341 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
342 CRASH_UNDER_CONSTEXPR_CONTEXT(); \
343 } \
344} while (0)
345
346#define ASSERT_AT(assertion, file, line, function) do { \
347 if (!(assertion)) { \
348 WTFReportAssertionFailure(file, line, function, #assertion); \
349 CRASH(); \
350 } \
351} while (0)
352
353#define ASSERT_NOT_REACHED(...) do { \
354 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
355 CRASH_WITH_INFO(__VA_ARGS__); \
356} while (0)
357
358#define ASSERT_NOT_IMPLEMENTED_YET() do { \
359 WTFReportNotImplementedYet(__FILE__, __LINE__, WTF_PRETTY_FUNCTION); \
360 CRASH(); \
361} while (0)
362
363#define ASSERT_IMPLIES(condition, assertion) do { \
364 if ((condition) && !(assertion)) { \
365 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition " => " #assertion); \
366 CRASH(); \
367 } \
368} while (0)
369
370#define ASSERT_UNUSED(variable, assertion, ...) ASSERT(assertion, __VA_ARGS__)
371
372#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
373
374/* ASSERT_WITH_SECURITY_IMPLICATION
375
376 Failure of this assertion indicates a possible security vulnerability.
377 Class of vulnerabilities that it tests include bad casts, out of bounds
378 accesses, use-after-frees, etc. Please file a bug using the security
379 template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
380
381*/
382#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
383 (!(assertion) ? \
384 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
385 CRASH_WITH_SECURITY_IMPLICATION()) : \
386 (void)0)
387#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
388#endif
389
390/* ASSERT_WITH_MESSAGE */
391
392#if ASSERT_MSG_DISABLED
393#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
394#else
395#define ASSERT_WITH_MESSAGE(assertion, ...) do { \
396 if (!(assertion)) { \
397 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
398 CRASH(); \
399 } \
400} while (0)
401#endif
402
403/* ASSERT_WITH_MESSAGE_UNUSED */
404
405#if ASSERT_MSG_DISABLED
406#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
407#else
408#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
409 if (!(assertion)) { \
410 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
411 CRASH(); \
412 } \
413} while (0)
414#endif
415
416
417/* ASSERT_ARG */
418
419#if ASSERT_ARG_DISABLED
420
421#define ASSERT_ARG(argName, assertion) ((void)0)
422
423#else
424
425#define ASSERT_ARG(argName, assertion) do { \
426 if (!(assertion)) { \
427 WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
428 CRASH(); \
429 } \
430} while (0)
431
432#endif
433
434/* COMPILE_ASSERT */
435#ifndef COMPILE_ASSERT
436#if COMPILER_SUPPORTS(C_STATIC_ASSERT)
437/* Unlike static_assert below, this also works in plain C code. */
438#define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
439#else
440#define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
441#endif
442#endif
443
444/* FATAL */
445
446#if FATAL_DISABLED
447#define FATAL(...) ((void)0)
448#else
449#define FATAL(...) do { \
450 WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
451 CRASH(); \
452} while (0)
453#endif
454
455/* LOG_ERROR */
456
457#if ERROR_DISABLED
458#define LOG_ERROR(...) ((void)0)
459#else
460#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
461#endif
462
463/* LOG */
464
465#if LOG_DISABLED
466#define LOG(channel, ...) ((void)0)
467#else
468#define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
469#endif
470
471/* LOG_VERBOSE */
472
473#if LOG_DISABLED
474#define LOG_VERBOSE(channel, ...) ((void)0)
475#else
476#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
477#endif
478
479/* LOG_WITH_LEVEL */
480
481#if LOG_DISABLED
482#define LOG_WITH_LEVEL(channel, level, ...) ((void)0)
483#else
484#define LOG_WITH_LEVEL(channel, level, ...) WTFLogWithLevel(&LOG_CHANNEL(channel), level, __VA_ARGS__)
485#endif
486
487/* RELEASE_LOG */
488
489#if RELEASE_LOG_DISABLED
490#define RELEASE_LOG(channel, ...) ((void)0)
491#define RELEASE_LOG_ERROR(channel, ...) LOG_ERROR(__VA_ARGS__)
492#define RELEASE_LOG_FAULT(channel, ...) LOG_ERROR(__VA_ARGS__)
493#define RELEASE_LOG_INFO(channel, ...) ((void)0)
494
495#define RELEASE_LOG_IF(isAllowed, channel, ...) ((void)0)
496#define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
497#define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) ((void)0)
498
499#define RELEASE_LOG_WITH_LEVEL(channel, level, ...) ((void)0)
500#define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, level, ...) do { if (isAllowed) RELEASE_LOG_WITH_LEVEL(channel, level, __VA_ARGS__); } while (0)
501
502#define RELEASE_LOG_STACKTRACE(channel) ((void)0)
503#else
504#define RELEASE_LOG(channel, ...) os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
505#define RELEASE_LOG_ERROR(channel, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
506#define RELEASE_LOG_FAULT(channel, ...) os_log_fault(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
507#define RELEASE_LOG_INFO(channel, ...) os_log_info(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
508
509#define RELEASE_LOG_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG( channel, __VA_ARGS__); } while (0)
510#define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
511#define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_INFO(channel, __VA_ARGS__); } while (0)
512
513#define RELEASE_LOG_WITH_LEVEL(channel, logLevel, ...) do { \
514 if (LOG_CHANNEL(channel).level >= (logLevel)) \
515 os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
516} while (0)
517
518#define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, logLevel, ...) do { \
519 if ((isAllowed) && LOG_CHANNEL(channel).level >= (logLevel)) \
520 os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
521} while (0)
522
523#define RELEASE_LOG_STACKTRACE(channel) WTFReleaseLogStackTrace(&LOG_CHANNEL(channel))
524#endif
525
526
527/* RELEASE_ASSERT */
528
529#if ASSERT_DISABLED
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#else
543#define RELEASE_ASSERT(assertion, ...) ASSERT(assertion, __VA_ARGS__)
544#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
545#define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
546#define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
547#define RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion)
548#endif
549
550#ifdef __cplusplus
551
552// 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.
553// The easiest way to fill these values per translation unit is to pass __LINE__, __FILE__, WTF_PRETTY_FUNCTION, and __COUNTER__.
554WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(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);
555WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(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);
556WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(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);
557WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3);
558WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2);
559WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1);
560WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason);
561NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter);
562
563inline void WTFCrashWithInfo(int, const char*, const char*, int)
564#if COMPILER(CLANG)
565 __attribute__((optnone))
566#endif
567{
568 CRASH();
569}
570
571namespace WTF {
572inline void isIntegralType() { }
573
574template<typename T, typename... Types>
575void isIntegralType(T, Types... types)
576{
577 static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "All types need to be integral bitwise_cast to integral type for logging");
578 isIntegralType(types...);
579}
580}
581
582inline void compilerFenceForCrash()
583{
584#if OS(WINDOWS) && !COMPILER(GCC_COMPATIBLE)
585 _ReadWriteBarrier();
586#else
587 asm volatile("" ::: "memory");
588#endif
589}
590
591#ifndef CRASH_WITH_INFO
592// This is useful if you are going to stuff data into registers before crashing. Like the crashWithInfo functions below...
593// GCC doesn't like the ##__VA_ARGS__ here since this macro is called from another macro so we just CRASH instead there.
594#if COMPILER(CLANG) || COMPILER(MSVC)
595#define CRASH_WITH_INFO(...) do { \
596 WTF::isIntegralType(__VA_ARGS__); \
597 compilerFenceForCrash(); \
598 WTFCrashWithInfo(__LINE__, __FILE__, WTF_PRETTY_FUNCTION, __COUNTER__, ##__VA_ARGS__); \
599 } while (false)
600#else
601#define CRASH_WITH_INFO(...) CRASH()
602#endif
603#endif // CRASH_WITH_INFO
604
605#ifndef CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
606#define CRASH_WITH_SECURITY_IMPLICATION_AND_INFO CRASH_WITH_INFO
607#endif // CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
608
609#else /* not __cplusplus */
610
611#ifndef CRASH_WITH_INFO
612#define CRASH_WITH_INFO() CRASH()
613#endif
614
615#endif /* __cplusplus */
616
617/* UNREACHABLE_FOR_PLATFORM */
618
619#if COMPILER(CLANG)
620// This would be a macro except that its use of #pragma works best around
621// a function. Hence it uses macro naming convention.
622IGNORE_WARNINGS_BEGIN("missing-noreturn")
623static inline void UNREACHABLE_FOR_PLATFORM()
624{
625 // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
626 // going.
627 RELEASE_ASSERT_NOT_REACHED();
628}
629IGNORE_WARNINGS_END
630#else
631#define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
632#endif
633