1/*
2 * Copyright (C) 2008 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#ifndef WTF_StdLibExtras_h
27#define WTF_StdLibExtras_h
28
29#include "wtf/Assertions.h"
30#include "wtf/CPU.h"
31#include "wtf/CheckedArithmetic.h"
32
33// Use this to declare and define a static local variable (static T;) so that
34//  it is leaked so that its destructors are not called at exit.
35#ifndef DEFINE_STATIC_LOCAL
36#define DEFINE_STATIC_LOCAL(type, name, arguments) \
37    static type& name = *new type arguments
38#endif
39
40// Use this to declare and define a static local pointer to a ref-counted object so that
41// it is leaked so that the object's destructors are not called at exit.
42// This macro should be used with ref-counted objects rather than DEFINE_STATIC_LOCAL macro,
43// as this macro does not lead to an extra memory allocation.
44#ifndef DEFINE_STATIC_REF
45#define DEFINE_STATIC_REF(type, name, arguments) \
46    static type* name = PassRefPtr<type>(arguments).leakRef();
47#endif
48
49// Use this macro to declare and define a debug-only global variable that may have a
50// non-trivial constructor and destructor. When building with clang, this will suppress
51// warnings about global constructors and exit-time destructors.
52#ifndef NDEBUG
53#if COMPILER(CLANG)
54#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \
55    _Pragma("clang diagnostic push") \
56    _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
57    _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
58    static type name arguments; \
59    _Pragma("clang diagnostic pop")
60#else
61#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \
62    static type name arguments;
63#endif // COMPILER(CLANG)
64#else
65#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments)
66#endif // NDEBUG
67
68/*
69 * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where
70 * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC:
71 * increases required alignment of target type.
72 *
73 * An implicit or an extra static_cast<void*> bypasses the warning.
74 * For more info see the following bugzilla entries:
75 * - https://bugs.webkit.org/show_bug.cgi?id=38045
76 * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976
77 */
78#if CPU(ARM) && COMPILER(GCC)
79template<typename Type>
80bool isPointerTypeAlignmentOkay(Type* ptr)
81{
82    return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
83}
84
85template<typename TypePtr>
86TypePtr reinterpret_cast_ptr(void* ptr)
87{
88    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
89    return reinterpret_cast<TypePtr>(ptr);
90}
91
92template<typename TypePtr>
93TypePtr reinterpret_cast_ptr(const void* ptr)
94{
95    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
96    return reinterpret_cast<TypePtr>(ptr);
97}
98#else
99template<typename Type>
100bool isPointerTypeAlignmentOkay(Type*)
101{
102    return true;
103}
104#define reinterpret_cast_ptr reinterpret_cast
105#endif
106
107namespace WTF {
108
109/*
110 * C++'s idea of a reinterpret_cast lacks sufficient cojones.
111 */
112template<typename TO, typename FROM>
113inline TO bitwise_cast(FROM from)
114{
115    COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal);
116    union {
117        FROM from;
118        TO to;
119    } u;
120    u.from = from;
121    return u.to;
122}
123
124template<typename To, typename From>
125inline To safeCast(From value)
126{
127    ASSERT(isInBounds<To>(value));
128    return static_cast<To>(value);
129}
130
131// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array.
132template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size];
133// GCC needs some help to deduce a 0 length array.
134#if COMPILER(GCC)
135template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0];
136#endif
137#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array))
138
139} // namespace WTF
140
141// This version of placement new omits a 0 check.
142enum NotNullTag { NotNull };
143inline void* operator new(size_t, NotNullTag, void* location)
144{
145    ASSERT(location);
146    return location;
147}
148
149using WTF::bitwise_cast;
150using WTF::safeCast;
151
152#endif // WTF_StdLibExtras_h
153