Bug 1541509 [wpt PR 16042] - Replace generateOffer by generateAudioReceiveOnlyOffer...
[gecko.git] / mfbt / NonDereferenceable.h
blobc1dc4989efaca49a908cd18ce825765ecdfdaa6f
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 #ifndef mozilla_NonDereferenceable_h
8 #define mozilla_NonDereferenceable_h
10 /* A pointer wrapper indicating that the pointer should not be dereferenced. */
12 #include "mozilla/Attributes.h"
13 #include "mozilla/TypeTraits.h"
15 #include <cstdint>
17 // Macro indicating that a function manipulates a pointer that will not be
18 // dereferenced, and therefore there is no need to check the object.
19 #if defined(__clang__)
20 # define NO_POINTEE_CHECKS __attribute__((no_sanitize("vptr")))
21 #else
22 # define NO_POINTEE_CHECKS /* nothing */
23 #endif
25 namespace mozilla {
27 // NonDereferenceable<T> wraps a raw pointer value of type T*, but prevents
28 // dereferencing.
30 // The main use case is for pointers that referencing memory that may not
31 // contain a valid object, either because the object has already been freed, or
32 // is under active construction or destruction (and hence parts of it may be
33 // uninitialized or destructed.)
34 // Such a pointer may still be useful, e.g., for its numeric value for
35 // logging/debugging purposes, which may be accessed with `value()`.
36 // Using NonDereferenceable with such pointers will make this intent clearer,
37 // and prevent misuses.
39 // Note that NonDereferenceable is only a wrapper and is NOT an owning pointer,
40 // i.e., it will not release/free the object.
42 // NonDereferenceable allows conversions between compatible pointer types, e.g.,
43 // to navigate a class hierarchy and identify parent/sub-objects. Note that the
44 // converted pointers stay safely NonDereferenceable.
46 // Use of NonDereferenceable is required to avoid errors from sanitization tools
47 // like `clang++ -fsanitize=vptr`, and should prevent false positives while
48 // pointers are manipulated within NonDereferenceable objects.
50 template <typename T>
51 class NonDereferenceable {
52 public:
53 // Default construction with a null value.
54 NonDereferenceable() : mPtr(nullptr) {}
56 // Default copy construction and assignment.
57 NO_POINTEE_CHECKS
58 NonDereferenceable(const NonDereferenceable&) = default;
59 NO_POINTEE_CHECKS
60 NonDereferenceable<T>& operator=(const NonDereferenceable&) = default;
61 // No move operations, as we're only carrying a non-owning pointer, so
62 // copying is most efficient.
64 // Construct/assign from a T* raw pointer.
65 // A raw pointer should usually point at a valid object, however we want to
66 // leave the ability to the user to create a NonDereferenceable from any
67 // pointer. Also, strictly speaking, in a constructor or destructor, `this`
68 // points at an object still being constructed or already partially
69 // destructed, which some very sensitive sanitizers could complain about.
70 NO_POINTEE_CHECKS
71 explicit NonDereferenceable(T* aPtr) : mPtr(aPtr) {}
72 NO_POINTEE_CHECKS
73 NonDereferenceable& operator=(T* aPtr) {
74 mPtr = aPtr;
75 return *this;
78 // Construct/assign from a compatible pointer type.
79 template <typename U>
80 NO_POINTEE_CHECKS explicit NonDereferenceable(U* aOther)
81 : mPtr(static_cast<T*>(aOther)) {}
82 template <typename U>
83 NO_POINTEE_CHECKS NonDereferenceable& operator=(U* aOther) {
84 mPtr = static_cast<T*>(aOther);
85 return *this;
88 // Construct/assign from a NonDereferenceable with a compatible pointer type.
89 template <typename U>
90 NO_POINTEE_CHECKS MOZ_IMPLICIT
91 NonDereferenceable(const NonDereferenceable<U>& aOther)
92 : mPtr(static_cast<T*>(aOther.mPtr)) {}
93 template <typename U>
94 NO_POINTEE_CHECKS NonDereferenceable& operator=(
95 const NonDereferenceable<U>& aOther) {
96 mPtr = static_cast<T*>(aOther.mPtr);
97 return *this;
100 // Explicitly disallow dereference operators, so that compiler errors point
101 // at these lines:
102 T& operator*() = delete; // Cannot dereference NonDereferenceable!
103 T* operator->() = delete; // Cannot dereference NonDereferenceable!
105 // Null check.
106 NO_POINTEE_CHECKS
107 explicit operator bool() const { return !!mPtr; }
109 // Extract the pointer value, untyped.
110 NO_POINTEE_CHECKS
111 uintptr_t value() const { return reinterpret_cast<uintptr_t>(mPtr); }
113 private:
114 // Let other NonDereferenceable templates access mPtr, to permit construction/
115 // assignment from compatible pointer types.
116 template <typename>
117 friend class NonDereferenceable;
119 T* MOZ_NON_OWNING_REF mPtr;
122 } // namespace mozilla
124 #undef NO_POINTEE_CHECKS
126 #endif /* mozilla_NonDereferenceable_h */