mfbt/NullPtr.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*
     8  * Implements a workaround for compilers which do not support the C++11 nullptr
     9  * constant.
    10  */
    12 #ifndef mozilla_NullPtr_h
    13 #define mozilla_NullPtr_h
    15 #if defined(__clang__)
    16 #  if !__has_extension(cxx_nullptr)
    17 #    error "clang version natively supporting nullptr is required."
    18 #  endif
    19 #  define MOZ_HAVE_CXX11_NULLPTR
    20 #elif defined(__GNUC__)
    21 #  if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
    22 #    include "mozilla/Compiler.h"
    23 #    if MOZ_GCC_VERSION_AT_LEAST(4, 6, 0)
    24 #      define MOZ_HAVE_CXX11_NULLPTR
    25 #    endif
    26 #  endif
    27 #elif defined(_MSC_VER)
    28    // The minimum supported MSVC (10, _MSC_VER 1600) supports nullptr.
    29 #  define MOZ_HAVE_CXX11_NULLPTR
    30 #endif
    32 namespace mozilla {
    34 /**
    35  * IsNullPointer<T>::value is true iff T is the type of C++11's nullptr.  If
    36  * nullptr is emulated, IsNullPointer<T>::value is false for all T.
    37  *
    38  * IsNullPointer is useful to give an argument the true decltype(nullptr) type.
    39  * decltype(nullptr) doesn't work when nullptr is emulated.  The simplest
    40  * workaround is to use template overloading and SFINAE to expose an overload
    41  * only if an argument's type is decltype(nullptr).  Some examples (that assume
    42  * namespace mozilla has been opened, for simplicity):
    43  *
    44  *   // foo(T*), foo(stuff that converts to T*), and foo(decltype(nullptr))
    45  *   // (only invoked if nullptr is true nullptr, otherwise foo(T*) is invoked)
    46  *   // but nothing else
    47  *   void foo(T*) { }
    48  *   template<typename N>
    49  *   void foo(N,
    50  *            typename EnableIf<IsNullPointer<N>::value, int>::Type dummy = 0)
    51  *   { }
    52  *
    53  *   // foo(T*) *exactly* and foo(decltype(nullptr)), nothing else
    54  *   void foo(T*) { }
    55  *   template<typename U>
    56  *   void foo(U,
    57  *            typename EnableIf<!IsNullPointer<U>::value, int>::Type dummy = 0)
    58  *   MOZ_DELETE;
    59  *
    60  * The exact details of how set up the SFINAE bits vary on a case-by-case basis.
    61  * If you need help with this (and unless you've internalized way more sadmaking
    62  * nullptr-emulation knowledge than you should have, you do), feel free to poke
    63  * the person with blame on this comment with questions.   :-)
    64  *
    65  * Ideally this would be in TypeTraits.h, but C++11 omitted std::is_null_pointer
    66  * (fixed in C++1y), so in the interests of easing a switch to <type_traits>,
    67  * this trait lives elsewhere.
    68  */
    69 template<typename T>
    70 struct IsNullPointer { static const bool value = false; };
    72 } // namespace mozilla
    74 /**
    75  * mozilla::NullptrT is a type that's sort of like decltype(nullptr).  But it
    76  * can't be identical, because emulated nullptr doesn't have a distinct type.
    77  * Only with gcc 4.4/4.5, emulated nullptr is __null, and decltype(__null) is
    78  * int or long.  But passing __null to an int/long parameter triggers
    79  * -Werror=conversion-null errors with gcc 4.5, or (depending on subsequent use
    80  * inside the overloaded function) can trigger pointer-to-integer comparison
    81  * compiler errors.  So fairly often, actually, NullptrT is *not* what you want.
    82  *
    83  * Instead, often you should use template-based overloading in concert with
    84  * SFINAE to add a nullptr overload -- see the comments by IsNullPointer.
    85  *
    86  * So when *should* you use NullptrT?  Thus far, the only truly good use seems
    87  * to be as an argument type for operator overloads (because C++ doesn't allow
    88  * operator= to have more than one argument, operator== to have more than two,
    89  * &c.).  But even in such cases, it really only works if there are no other
    90  * overloads of the operator that accept a pointer type.  If you want both T*
    91  * and nullptr_t overloads, you'll have to wait til we drop gcc 4.4/4.5 support.
    92  * (Currently b2g is the only impediment to this.)
    93  */
    94 #ifdef MOZ_HAVE_CXX11_NULLPTR
    95   // decltype does the right thing for actual nullptr.
    96   namespace mozilla {
    97   typedef decltype(nullptr) NullptrT;
    98   template<>
    99   struct IsNullPointer<decltype(nullptr)> { static const bool value = true; };
   100   }
   101 #  undef MOZ_HAVE_CXX11_NULLPTR
   102 #elif MOZ_IS_GCC
   103 #  define nullptr __null
   104   // void* sweeps up more than just nullptr, but compilers supporting true
   105   // nullptr are the majority now, so they should detect mistakes.  If you're
   106   // feeling paranoid, check/assert that your NullptrT equals nullptr.
   107   namespace mozilla { typedef void* NullptrT; }
   108 #else
   109 #  error "No compiler support for nullptr or its emulation."
   110 #endif
   112 #endif /* mozilla_NullPtr_h */

mercurial