OperatorNewExtensions.h 2.1 KB

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