/work/obj-fuzz/dist/include/mozilla/OperatorNewExtensions.h
Line | Count | Source |
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 | | operator new(size_t, mozilla::NotNullTag, void* p) |
47 | 142M | { |
48 | 142M | MOZ_ASSERT(p); |
49 | 142M | return p; |
50 | 142M | } |
51 | | |
52 | | #endif // mozilla_OperatorNewExtensions_h |