Line data Source code
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/. */
6 :
7 : /* A version of |operator new| that eschews mandatory null-checks. */
8 :
9 : #ifndef mozilla_OperatorNewExtensions_h
10 : #define mozilla_OperatorNewExtensions_h
11 :
12 : #include "mozilla/Assertions.h"
13 :
14 : // Credit goes to WebKit for this implementation, cf.
15 : // https://bugs.webkit.org/show_bug.cgi?id=74676
16 : namespace mozilla {
17 : enum NotNullTag {
18 : KnownNotNull,
19 : };
20 : } // namespace mozilla
21 :
22 : /*
23 : * The logic here is a little subtle. [expr.new] states that if the allocation
24 : * function being called returns null, then object initialization must not be
25 : * done, and the entirety of the new expression must return null. Non-throwing
26 : * (noexcept) functions are defined to return null to indicate failure. The
27 : * standard placement operator new is defined in such a way, and so it requires
28 : * a null check, even when that null check would be extraneous. Functions
29 : * declared without such a specification are defined to throw std::bad_alloc if
30 : * they fail, and return a non-null pointer otherwise. We compile without
31 : * exceptions, so any placement new overload we define that doesn't declare
32 : * itself as noexcept must therefore avoid generating a null check. Below is
33 : * just such an overload.
34 : *
35 : * You might think that MOZ_NONNULL might perform the same function, but
36 : * MOZ_NONNULL isn't supported on all of our compilers, and even when it is
37 : * supported, doesn't work on all the versions we support. And even keeping
38 : * those limitations in mind, we can't put MOZ_NONNULL on the global,
39 : * standardized placement new function in any event.
40 : *
41 : * We deliberately don't add MOZ_NONNULL(3) to tag |p| as non-null, to benefit
42 : * hypothetical static analyzers. Doing so makes |MOZ_ASSERT(p)|'s internal
43 : * test vacuous, and some compilers warn about such vacuous tests.
44 : */
45 : inline void*
46 2646002 : operator new(size_t, mozilla::NotNullTag, void* p)
47 : {
48 2646002 : MOZ_ASSERT(p);
49 2646002 : return p;
50 : }
51 :
52 : #endif // mozilla_OperatorNewExtensions_h
|