1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PARTITION_ALLOC_POINTERS_RAW_PTR_NOOP_IMPL_H_
6 #define PARTITION_ALLOC_POINTERS_RAW_PTR_NOOP_IMPL_H_
7 
8 #include <type_traits>
9 
10 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
11 #include "partition_alloc/partition_alloc_forward.h"
12 
13 namespace base::internal {
14 
15 struct RawPtrNoOpImpl {
16   static constexpr bool kMustZeroOnConstruct = false;
17   static constexpr bool kMustZeroOnMove = false;
18   static constexpr bool kMustZeroOnDestruct = false;
19 
20   // Wraps a pointer.
21   template <typename T>
WrapRawPtrRawPtrNoOpImpl22   PA_ALWAYS_INLINE static constexpr T* WrapRawPtr(T* ptr) {
23     return ptr;
24   }
25 
26   // Notifies the allocator when a wrapped pointer is being removed or
27   // replaced.
28   template <typename T>
ReleaseWrappedPtrRawPtrNoOpImpl29   PA_ALWAYS_INLINE static constexpr void ReleaseWrappedPtr(T*) {}
30 
31   // Unwraps the pointer, while asserting that memory hasn't been freed. The
32   // function is allowed to crash on nullptr.
33   template <typename T>
SafelyUnwrapPtrForDereferenceRawPtrNoOpImpl34   PA_ALWAYS_INLINE static constexpr T* SafelyUnwrapPtrForDereference(
35       T* wrapped_ptr) {
36     return wrapped_ptr;
37   }
38 
39   // Unwraps the pointer, while asserting that memory hasn't been freed. The
40   // function must handle nullptr gracefully.
41   template <typename T>
SafelyUnwrapPtrForExtractionRawPtrNoOpImpl42   PA_ALWAYS_INLINE static constexpr T* SafelyUnwrapPtrForExtraction(
43       T* wrapped_ptr) {
44     return wrapped_ptr;
45   }
46 
47   // Unwraps the pointer, without making an assertion on whether memory was
48   // freed or not.
49   template <typename T>
UnsafelyUnwrapPtrForComparisonRawPtrNoOpImpl50   PA_ALWAYS_INLINE static constexpr T* UnsafelyUnwrapPtrForComparison(
51       T* wrapped_ptr) {
52     return wrapped_ptr;
53   }
54 
55   // Upcasts the wrapped pointer.
56   template <typename To, typename From>
UpcastRawPtrNoOpImpl57   PA_ALWAYS_INLINE static constexpr To* Upcast(From* wrapped_ptr) {
58     static_assert(std::is_convertible_v<From*, To*>,
59                   "From must be convertible to To.");
60     // Note, this cast may change the address if upcasting to base that lies
61     // in the middle of the derived object.
62     return wrapped_ptr;
63   }
64 
65   // Advance the wrapped pointer by `delta_elems`.
66   template <
67       typename T,
68       typename Z,
69       typename =
70           std::enable_if_t<partition_alloc::internal::is_offset_type<Z>, void>>
71   PA_ALWAYS_INLINE static constexpr T*
AdvanceRawPtrNoOpImpl72   Advance(T* wrapped_ptr, Z delta_elems, bool /*is_in_pointer_modification*/) {
73     return wrapped_ptr + delta_elems;
74   }
75 
76   // Retreat the wrapped pointer by `delta_elems`.
77   template <
78       typename T,
79       typename Z,
80       typename =
81           std::enable_if_t<partition_alloc::internal::is_offset_type<Z>, void>>
82   PA_ALWAYS_INLINE static constexpr T*
RetreatRawPtrNoOpImpl83   Retreat(T* wrapped_ptr, Z delta_elems, bool /*is_in_pointer_modification*/) {
84     return wrapped_ptr - delta_elems;
85   }
86 
87   template <typename T>
GetDeltaElemsRawPtrNoOpImpl88   PA_ALWAYS_INLINE static constexpr ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
89                                                             T* wrapped_ptr2) {
90     return wrapped_ptr1 - wrapped_ptr2;
91   }
92 
93   // Returns a copy of a wrapped pointer, without making an assertion on
94   // whether memory was freed or not.
95   template <typename T>
DuplicateRawPtrNoOpImpl96   PA_ALWAYS_INLINE static constexpr T* Duplicate(T* wrapped_ptr) {
97     return wrapped_ptr;
98   }
99 
100   // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used
101   // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor.
102   template <typename T>
WrapRawPtrForDuplicationRawPtrNoOpImpl103   PA_ALWAYS_INLINE static constexpr T* WrapRawPtrForDuplication(T* ptr) {
104     return ptr;
105   }
106 
107   template <typename T>
UnsafelyUnwrapPtrForDuplicationRawPtrNoOpImpl108   PA_ALWAYS_INLINE static constexpr T* UnsafelyUnwrapPtrForDuplication(
109       T* wrapped_ptr) {
110     return wrapped_ptr;
111   }
112 
113   template <typename T>
TraceRawPtrNoOpImpl114   static constexpr void Trace([[maybe_unused]] uint64_t owner_id,
115                               [[maybe_unused]] T* wrapped_ptr) {}
UntraceRawPtrNoOpImpl116   static constexpr void Untrace([[maybe_unused]] uint64_t owner_id) {}
117 
118   // This is for accounting only, used by unit tests.
IncrementSwapCountForTestRawPtrNoOpImpl119   PA_ALWAYS_INLINE static constexpr void IncrementSwapCountForTest() {}
IncrementLessCountForTestRawPtrNoOpImpl120   PA_ALWAYS_INLINE static constexpr void IncrementLessCountForTest() {}
121 };
122 
123 }  // namespace base::internal
124 
125 #endif  // PARTITION_ALLOC_POINTERS_RAW_PTR_NOOP_IMPL_H_
126