Home | History | Annotate | Download | only in wtf
      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)
     79 template<typename Type>
     80 bool isPointerTypeAlignmentOkay(Type* ptr)
     81 {
     82     return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
     83 }
     84 
     85 template<typename TypePtr>
     86 TypePtr reinterpret_cast_ptr(void* ptr)
     87 {
     88     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
     89     return reinterpret_cast<TypePtr>(ptr);
     90 }
     91 
     92 template<typename TypePtr>
     93 TypePtr reinterpret_cast_ptr(const void* ptr)
     94 {
     95     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
     96     return reinterpret_cast<TypePtr>(ptr);
     97 }
     98 #else
     99 template<typename Type>
    100 bool isPointerTypeAlignmentOkay(Type*)
    101 {
    102     return true;
    103 }
    104 #define reinterpret_cast_ptr reinterpret_cast
    105 #endif
    106 
    107 namespace WTF {
    108 
    109 /*
    110  * C++'s idea of a reinterpret_cast lacks sufficient cojones.
    111  */
    112 template<typename TO, typename FROM>
    113 inline 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 
    124 template<typename To, typename From>
    125 inline 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.
    132 template<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)
    135 template<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.
    142 enum NotNullTag { NotNull };
    143 inline void* operator new(size_t, NotNullTag, void* location)
    144 {
    145     ASSERT(location);
    146     return location;
    147 }
    148 
    149 using WTF::bitwise_cast;
    150 using WTF::safeCast;
    151 
    152 #endif // WTF_StdLibExtras_h
    153