Use C11's _Static_assert for COMPILE_ASSERT if it is available
[WebKit-https.git] / Source / JavaScriptCore / wtf / Assertions.h
1 /*
2  * Copyright (C) 2003, 2006, 2007 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 COMPUTER, 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 COMPUTER, 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 #ifndef WTF_Assertions_h
27 #define WTF_Assertions_h
28
29 /*
30    no namespaces because this file has to be includable from C and Objective-C
31
32    Note, this file uses many GCC extensions, but it should be compatible with
33    C, Objective C, C++, and Objective C++.
34
35    For non-debug builds, everything is disabled by default.
36    Defining any of the symbols explicitly prevents this from having any effect.
37    
38    MSVC7 note: variadic macro support was added in MSVC8, so for now we disable
39    those macros in MSVC7. For more info, see the MSDN document on variadic 
40    macros here:
41    
42    http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx
43 */
44
45 #include "Platform.h"
46
47 #include <stddef.h>
48
49 #if !COMPILER(MSVC)
50 #include <inttypes.h>
51 #endif
52
53 #ifdef NDEBUG
54 /* Disable ASSERT* macros in release mode. */
55 #define ASSERTIONS_DISABLED_DEFAULT 1
56 #else
57 #define ASSERTIONS_DISABLED_DEFAULT 0
58 #endif
59
60 #if COMPILER(MSVC7_OR_LOWER)
61 #define HAVE_VARIADIC_MACRO 0
62 #else
63 #define HAVE_VARIADIC_MACRO 1
64 #endif
65
66 #ifndef BACKTRACE_DISABLED
67 #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
68 #endif
69
70 #ifndef ASSERT_DISABLED
71 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
72 #endif
73
74 #ifndef ASSERT_MSG_DISABLED
75 #if HAVE(VARIADIC_MACRO)
76 #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
77 #else
78 #define ASSERT_MSG_DISABLED 1
79 #endif
80 #endif
81
82 #ifndef ASSERT_ARG_DISABLED
83 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
84 #endif
85
86 #ifndef FATAL_DISABLED
87 #if HAVE(VARIADIC_MACRO)
88 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
89 #else
90 #define FATAL_DISABLED 1
91 #endif
92 #endif
93
94 #ifndef ERROR_DISABLED
95 #if HAVE(VARIADIC_MACRO)
96 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
97 #else
98 #define ERROR_DISABLED 1
99 #endif
100 #endif
101
102 #ifndef LOG_DISABLED
103 #if HAVE(VARIADIC_MACRO)
104 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
105 #else
106 #define LOG_DISABLED 1
107 #endif
108 #endif
109
110 #if COMPILER(GCC)
111 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
112 #else
113 #define WTF_PRETTY_FUNCTION __FUNCTION__
114 #endif
115
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 #if COMPILER(GCC) && !defined(__OBJC__)
120 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
121 #else
122 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) 
123 #endif
124
125 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
126
127 #ifdef __cplusplus
128 extern "C" {
129 #endif
130
131 typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState;
132
133 typedef struct {
134     unsigned mask;
135     const char *defaultName;
136     WTFLogChannelState state;
137 } WTFLogChannel;
138
139 WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
140 WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
141 WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
142 WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
143 WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
144 WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
145 WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
146
147 WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
148 WTF_EXPORT_PRIVATE void WTFReportBacktrace();
149
150 typedef void (*WTFCrashHookFunction)();
151 WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
152 WTF_EXPORT_PRIVATE void WTFInvokeCrashHook();
153
154 #ifdef __cplusplus
155 }
156 #endif
157
158 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
159
160    Use CRASH() in response to known, unrecoverable errors like out-of-memory.
161    Macro is enabled in both debug and release mode.
162    To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
163
164    Signals are ignored by the crash reporter on OS X so we must do better.
165 */
166 #ifndef CRASH
167 #if COMPILER(CLANG)
168 #define CRASH() do { \
169     WTFReportBacktrace(); \
170     WTFInvokeCrashHook(); \
171     *(int *)(uintptr_t)0xbbadbeef = 0; \
172     __builtin_trap(); \
173 } while (false)
174 #else
175 #define CRASH() do { \
176     WTFReportBacktrace(); \
177     WTFInvokeCrashHook(); \
178     *(int *)(uintptr_t)0xbbadbeef = 0; \
179     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
180 } while (false)
181 #endif
182 #endif
183
184 #if COMPILER(CLANG)
185 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
186 #else
187 #define NO_RETURN_DUE_TO_CRASH
188 #endif
189
190
191 /* BACKTRACE
192
193   Print a backtrace to the same location as ASSERT messages.
194 */
195
196 #if BACKTRACE_DISABLED
197
198 #define BACKTRACE() ((void)0)
199
200 #else
201
202 #define BACKTRACE() do { \
203     WTFReportBacktrace(); \
204 } while(false)
205
206 #endif
207
208 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
209
210   These macros are compiled out of release builds.
211   Expressions inside them are evaluated in debug builds only.
212 */
213
214 #if OS(WINCE) && !PLATFORM(TORCHMOBILE)
215 /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
216 #include <windows.h>
217 #undef min
218 #undef max
219 #undef ERROR
220 #endif
221
222 #if OS(WINDOWS)
223 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
224 #undef ASSERT
225 #endif
226
227 #if ASSERT_DISABLED
228
229 #define ASSERT(assertion) ((void)0)
230 #define ASSERT_AT(assertion, file, line, function) ((void)0)
231 #define ASSERT_NOT_REACHED() ((void)0)
232 #define NO_RETURN_DUE_TO_ASSERT
233
234 #if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
235 template<typename T>
236 inline void assertUnused(T& x) { (void)x; }
237 #define ASSERT_UNUSED(variable, assertion) (assertUnused(variable))
238 #else
239 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
240 #endif
241
242 #else
243
244 #define ASSERT(assertion) do \
245     if (!(assertion)) { \
246         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
247         CRASH(); \
248     } \
249 while (0)
250
251 #define ASSERT_AT(assertion, file, line, function) do  \
252     if (!(assertion)) { \
253         WTFReportAssertionFailure(file, line, function, #assertion); \
254         CRASH(); \
255     } \
256 while (0)
257
258 #define ASSERT_NOT_REACHED() do { \
259     WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
260     CRASH(); \
261 } while (0)
262
263 #define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
264
265 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
266
267 #endif
268
269 /* ASSERT_WITH_MESSAGE */
270
271 #if COMPILER(MSVC7_OR_LOWER)
272 #define ASSERT_WITH_MESSAGE(assertion) ((void)0)
273 #elif ASSERT_MSG_DISABLED
274 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
275 #else
276 #define ASSERT_WITH_MESSAGE(assertion, ...) do \
277     if (!(assertion)) { \
278         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
279         CRASH(); \
280     } \
281 while (0)
282 #endif
283
284 /* ASSERT_WITH_MESSAGE_UNUSED */
285
286 #if COMPILER(MSVC7_OR_LOWER)
287 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion) ((void)0)
288 #elif ASSERT_MSG_DISABLED
289 #if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
290 template<typename T>
291 inline void assertWithMessageUnused(T& x) { (void)x; }
292 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) (assertWithMessageUnused(variable))
293 #else
294 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
295 #endif
296 #else
297 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do \
298     if (!(assertion)) { \
299         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
300         CRASH(); \
301     } \
302 while (0)
303 #endif
304                         
305                         
306 /* ASSERT_ARG */
307
308 #if ASSERT_ARG_DISABLED
309
310 #define ASSERT_ARG(argName, assertion) ((void)0)
311
312 #else
313
314 #define ASSERT_ARG(argName, assertion) do \
315     if (!(assertion)) { \
316         WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
317         CRASH(); \
318     } \
319 while (0)
320
321 #endif
322
323 /* COMPILE_ASSERT */
324 #ifndef COMPILE_ASSERT
325 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
326 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
327 #else
328 #define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1]
329 #endif
330 #endif
331
332 /* FATAL */
333
334 #if COMPILER(MSVC7_OR_LOWER)
335 #define FATAL() ((void)0)
336 #elif FATAL_DISABLED
337 #define FATAL(...) ((void)0)
338 #else
339 #define FATAL(...) do { \
340     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
341     CRASH(); \
342 } while (0)
343 #endif
344
345 /* LOG_ERROR */
346
347 #if COMPILER(MSVC7_OR_LOWER)
348 #define LOG_ERROR() ((void)0)
349 #elif ERROR_DISABLED
350 #define LOG_ERROR(...) ((void)0)
351 #else
352 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
353 #endif
354
355 /* LOG */
356
357 #if COMPILER(MSVC7_OR_LOWER)
358 #define LOG() ((void)0)
359 #elif LOG_DISABLED
360 #define LOG(channel, ...) ((void)0)
361 #else
362 #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
363 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
364 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
365 #endif
366
367 /* LOG_VERBOSE */
368
369 #if COMPILER(MSVC7_OR_LOWER)
370 #define LOG_VERBOSE(channel) ((void)0)
371 #elif LOG_DISABLED
372 #define LOG_VERBOSE(channel, ...) ((void)0)
373 #else
374 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
375 #endif
376
377 #if ENABLE(GC_VALIDATION)
378 #define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \
379     if (!(cell))\
380         CRASH();\
381     if (cell->unvalidatedStructure()->unvalidatedStructure() != cell->unvalidatedStructure()->unvalidatedStructure()->unvalidatedStructure())\
382         CRASH();\
383 } while (0)
384
385 #define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do {\
386     ASSERT_GC_OBJECT_LOOKS_VALID(object); \
387     if (!object->inherits(classInfo)) \
388         CRASH();\
389 } while (0)
390
391 #else
392 #define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { (void)cell; } while (0)
393 #define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0)
394 #endif
395
396 #if COMPILER(CLANG)
397 #define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) COMPILE_ASSERT(__has_trivial_destructor(klass), klass##_has_trivial_destructor_check)
398 #else
399 #define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass)
400 #endif
401
402 #endif /* WTF_Assertions_h */