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