xref: /aosp_15_r20/external/cronet/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 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_H_
6 #define PARTITION_ALLOC_POINTERS_RAW_PTR_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <functional>
11 #include <type_traits>
12 #include <utility>
13 
14 #include "build/build_config.h"
15 #include "partition_alloc/flags.h"
16 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
17 #include "partition_alloc/partition_alloc_base/component_export.h"
18 #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h"
19 #include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h"
20 #include "partition_alloc/partition_alloc_buildflags.h"
21 #include "partition_alloc/partition_alloc_config.h"
22 #include "partition_alloc/partition_alloc_forward.h"
23 #include "partition_alloc/pointers/instance_tracer.h"
24 #include "partition_alloc/raw_ptr_buildflags.h"
25 
26 #if BUILDFLAG(IS_WIN)
27 #include "partition_alloc/partition_alloc_base/win/win_handle_types.h"
28 #endif
29 
30 #if BUILDFLAG(USE_PARTITION_ALLOC)
31 #include "partition_alloc/partition_alloc_base/check.h"
32 // Live implementation of MiraclePtr being built.
33 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
34     BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
35 #define PA_RAW_PTR_CHECK(condition) PA_BASE_CHECK(condition)
36 #else
37 // No-op implementation of MiraclePtr being built.
38 // Note that `PA_BASE_DCHECK()` evaporates from non-DCHECK builds,
39 // minimizing impact of generated code.
40 #define PA_RAW_PTR_CHECK(condition) PA_BASE_DCHECK(condition)
41 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
42         // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
43 #else   // BUILDFLAG(USE_PARTITION_ALLOC)
44 // Without PartitionAlloc, there's no `PA_BASE_D?CHECK()` implementation
45 // available.
46 #define PA_RAW_PTR_CHECK(condition)
47 #endif  // BUILDFLAG(USE_PARTITION_ALLOC)
48 
49 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
50 #include "partition_alloc/pointers/raw_ptr_backup_ref_impl.h"
51 #elif BUILDFLAG(USE_ASAN_UNOWNED_PTR)
52 #include "partition_alloc/pointers/raw_ptr_asan_unowned_impl.h"
53 #elif BUILDFLAG(USE_HOOKABLE_RAW_PTR)
54 #include "partition_alloc/pointers/raw_ptr_hookable_impl.h"
55 #else
56 #include "partition_alloc/pointers/raw_ptr_noop_impl.h"
57 #endif
58 
59 namespace cc {
60 class Scheduler;
61 }
62 namespace base::internal {
63 class DelayTimerBase;
64 }
65 namespace base::test {
66 struct RawPtrCountingImplForTest;
67 }
68 namespace content::responsiveness {
69 class Calculator;
70 }
71 
72 namespace partition_alloc::internal {
73 
74 // NOTE: All methods should be `PA_ALWAYS_INLINE`. raw_ptr is meant to be a
75 // lightweight replacement of a raw pointer, hence performance is critical.
76 
77 // This is a bitfield representing the different flags that can be applied to a
78 // raw_ptr.
79 //
80 // Internal use only: Developers shouldn't use those values directly.
81 //
82 // Housekeeping rules: Try not to change trait values, so that numeric trait
83 // values stay constant across builds (could be useful e.g. when analyzing stack
84 // traces). A reasonable exception to this rule are `*ForTest` traits. As a
85 // matter of fact, we propose that new non-test traits are added before the
86 // `*ForTest` traits.
87 enum class RawPtrTraits : unsigned {
88   kEmpty = 0,
89 
90   // Disables dangling pointer detection, but keeps other raw_ptr protections.
91   //
92   // Don't use directly, use DisableDanglingPtrDetection or DanglingUntriaged
93   // instead.
94   kMayDangle = (1 << 0),
95 
96   // Disables any hooks, when building with BUILDFLAG(USE_HOOKABLE_RAW_PTR).
97   //
98   // Internal use only.
99   kDisableHooks = (1 << 2),
100 
101   // Pointer arithmetic is discouraged and disabled by default.
102   //
103   // Don't use directly, use AllowPtrArithmetic instead.
104   kAllowPtrArithmetic = (1 << 3),
105 
106   // This pointer has BRP disabled for experimental rewrites of containers.
107   //
108   // Don't use directly.
109   kDisableBRP = (1 << 4),
110 
111   // Uninitialized pointers are discouraged and disabled by default.
112   //
113   // Don't use directly, use AllowUninitialized instead.
114   kAllowUninitialized = (1 << 5),
115 
116   // *** ForTest traits below ***
117 
118   // Adds accounting, on top of the NoOp implementation, for test purposes.
119   // raw_ptr/raw_ref with this trait perform extra bookkeeping, e.g. to track
120   // the number of times the raw_ptr is wrapped, unwrapped, etc.
121   //
122   // Test only. Include raw_ptr_counting_impl_for_test.h in your test
123   // files when using this trait.
124   kUseCountingImplForTest = (1 << 10),
125 
126   // Helper trait that can be used to test raw_ptr's behaviour or conversions.
127   //
128   // Test only.
129   kDummyForTest = (1 << 11),
130 
131   kAllMask = kMayDangle | kDisableHooks | kAllowPtrArithmetic | kDisableBRP |
132              kAllowUninitialized | kUseCountingImplForTest | kDummyForTest,
133 };
134 // Template specialization to use |PA_DEFINE_OPERATORS_FOR_FLAGS| without
135 // |kMaxValue| declaration.
136 template <>
137 constexpr inline RawPtrTraits kAllFlags<RawPtrTraits> = RawPtrTraits::kAllMask;
138 
139 PA_DEFINE_OPERATORS_FOR_FLAGS(RawPtrTraits);
140 
141 }  // namespace partition_alloc::internal
142 
143 namespace base {
144 using partition_alloc::internal::RawPtrTraits;
145 
146 namespace raw_ptr_traits {
147 
148 // IsSupportedType<T>::value answers whether raw_ptr<T>:
149 //   1) compiles
150 //   2) is safe at runtime
151 //
152 // Templates that may end up using raw_ptr should use IsSupportedType to ensure
153 // that raw_ptr is not used with unsupported types. As an example, see how
154 // base::internal::Unretained(Ref)Wrapper uses IsSupportedType to decide whether
155 // it should use `raw_ptr<T>` or `T*`.
156 template <typename T, typename SFINAE = void>
157 struct IsSupportedType {
158   static constexpr bool value = true;
159 };
160 
161 // raw_ptr<T> is not compatible with function pointer types. Also, they don't
162 // even need the raw_ptr protection, because they don't point on heap.
163 template <typename T>
164 struct IsSupportedType<T, std::enable_if_t<std::is_function_v<T>>> {
165   static constexpr bool value = false;
166 };
167 
168 // This section excludes some types from raw_ptr<T> to avoid them from being
169 // used inside base::Unretained in performance sensitive places. These were
170 // identified from sampling profiler data. See crbug.com/1287151 for more info.
171 template <>
172 struct IsSupportedType<cc::Scheduler> {
173   static constexpr bool value = false;
174 };
175 template <>
176 struct IsSupportedType<base::internal::DelayTimerBase> {
177   static constexpr bool value = false;
178 };
179 template <>
180 struct IsSupportedType<content::responsiveness::Calculator> {
181   static constexpr bool value = false;
182 };
183 
184 #if __OBJC__
185 // raw_ptr<T> is not compatible with pointers to Objective-C classes for a
186 // multitude of reasons. They may fail to compile in many cases, and wouldn't
187 // work well with tagged pointers. Anyway, Objective-C objects have their own
188 // way of tracking lifespan, hence don't need the raw_ptr protection as much.
189 //
190 // Such pointers are detected by checking if they're convertible to |id| type.
191 template <typename T>
192 struct IsSupportedType<T, std::enable_if_t<std::is_convertible_v<T*, id>>> {
193   static constexpr bool value = false;
194 };
195 #endif  // __OBJC__
196 
197 #if BUILDFLAG(IS_WIN)
198 // raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also
199 // represent a valid pointer into a PartitionAlloc-managed region then it can
200 // lead to manipulating random memory when treating it as BackupRefPtr
201 // ref-count.  See also https://crbug.com/1262017.
202 //
203 // TODO(https://crbug.com/1262017): Cover other handle types like HANDLE,
204 // HLOCAL, HINTERNET, or HDEVINFO.  Maybe we should avoid using raw_ptr<T> when
205 // T=void (as is the case in these handle types).  OTOH, explicit,
206 // non-template-based raw_ptr<void> should be allowed.  Maybe this can be solved
207 // by having 2 traits: IsPointeeAlwaysSafe (to be used in templates) and
208 // IsPointeeUsuallySafe (to be used in the static_assert in raw_ptr).  The
209 // upside of this approach is that it will safely handle base::Bind closing over
210 // HANDLE.  The downside of this approach is that base::Bind closing over a
211 // void* pointer will not get UaF protection.
212 #define PA_WINDOWS_HANDLE_TYPE(name)       \
213   template <>                              \
214   struct IsSupportedType<name##__, void> { \
215     static constexpr bool value = false;   \
216   };
217 #include "partition_alloc/partition_alloc_base/win/win_handle_types_list.inc"
218 #undef PA_WINDOWS_HANDLE_TYPE
219 #endif
220 
221 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
222 template <RawPtrTraits Traits>
223 using UnderlyingImplForTraits = internal::RawPtrBackupRefImpl<
224     /*AllowDangling=*/partition_alloc::internal::ContainsFlags(
225         Traits,
226         RawPtrTraits::kMayDangle),
227     /*DisableBRP=*/partition_alloc::internal::ContainsFlags(
228         Traits,
229         RawPtrTraits::kDisableBRP)>;
230 
231 #elif BUILDFLAG(USE_ASAN_UNOWNED_PTR)
232 template <RawPtrTraits Traits>
233 using UnderlyingImplForTraits = internal::RawPtrAsanUnownedImpl<
234     partition_alloc::internal::ContainsFlags(Traits,
235                                              RawPtrTraits::kAllowPtrArithmetic),
236     partition_alloc::internal::ContainsFlags(Traits, RawPtrTraits::kMayDangle)>;
237 
238 #elif BUILDFLAG(USE_HOOKABLE_RAW_PTR)
239 template <RawPtrTraits Traits>
240 using UnderlyingImplForTraits = internal::RawPtrHookableImpl<
241     /*EnableHooks=*/!partition_alloc::internal::ContainsFlags(
242         Traits,
243         RawPtrTraits::kDisableHooks)>;
244 
245 #else
246 template <RawPtrTraits Traits>
247 using UnderlyingImplForTraits = internal::RawPtrNoOpImpl;
248 #endif
249 
250 constexpr bool IsPtrArithmeticAllowed([[maybe_unused]] RawPtrTraits Traits) {
251 #if BUILDFLAG(ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK)
252   return partition_alloc::internal::ContainsFlags(
253       Traits, RawPtrTraits::kAllowPtrArithmetic);
254 #else
255   return true;
256 #endif
257 }
258 
259 // ImplForTraits is the struct that implements raw_ptr functions. Think of
260 // raw_ptr as a thin wrapper, that directs calls to ImplForTraits. ImplForTraits
261 // may be different from UnderlyingImplForTraits, because it may select a
262 // test impl instead.
263 template <RawPtrTraits Traits>
264 using ImplForTraits =
265     std::conditional_t<partition_alloc::internal::ContainsFlags(
266                            Traits,
267                            RawPtrTraits::kUseCountingImplForTest),
268                        test::RawPtrCountingImplForTest,
269                        UnderlyingImplForTraits<Traits>>;
270 
271 // `kTypeTraits` is a customization interface to accosiate `T` with some
272 // `RawPtrTraits`. Users may create specialization of this variable
273 // to enable some traits by default.
274 // Note that specialization must be declared before the first use that would
275 // cause implicit instantiation of `raw_ptr` or `raw_ref`, in every translation
276 // unit where such use occurs.
277 template <typename T, typename SFINAE = void>
278 constexpr inline auto kTypeTraits = RawPtrTraits::kEmpty;
279 
280 }  // namespace raw_ptr_traits
281 
282 // `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
283 // over raw pointers. See the documentation for details:
284 // https://source.chromium.org/chromium/chromium/src/+/main:base/memory/raw_ptr.md
285 //
286 // raw_ptr<T> is marked as [[gsl::Pointer]] which allows the compiler to catch
287 // some bugs where the raw_ptr holds a dangling pointer to a temporary object.
288 // However the [[gsl::Pointer]] analysis expects that such types do not have a
289 // non-default move constructor/assignment. Thus, it's possible to get an error
290 // where the pointer is not actually dangling, and have to work around the
291 // compiler. We have not managed to construct such an example in Chromium yet.
292 template <typename T, RawPtrTraits PointerTraits = RawPtrTraits::kEmpty>
293 class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
294  public:
295   // Users may specify `RawPtrTraits` via raw_ptr's second template parameter
296   // `PointerTraits`, or specialization of `raw_ptr_traits::kTypeTraits<T>`.
297   constexpr static auto Traits = PointerTraits | raw_ptr_traits::kTypeTraits<T>;
298   using Impl = typename raw_ptr_traits::ImplForTraits<Traits>;
299   // Needed to make gtest Pointee matcher work with raw_ptr.
300   using element_type = T;
301   using DanglingType = raw_ptr<T, Traits | RawPtrTraits::kMayDangle>;
302 
303 #if !BUILDFLAG(USE_PARTITION_ALLOC)
304   // See comment at top about `PA_RAW_PTR_CHECK()`.
305   static_assert(std::is_same_v<Impl, internal::RawPtrNoOpImpl>);
306 #endif  // !BUILDFLAG(USE_PARTITION_ALLOC)
307 
308   static_assert(partition_alloc::internal::AreValidFlags(Traits),
309                 "Unknown raw_ptr trait(s)");
310   static_assert(raw_ptr_traits::IsSupportedType<T>::value,
311                 "raw_ptr<T> doesn't work with this kind of pointee type T");
312 
313   static constexpr bool kZeroOnConstruct =
314       Impl::kMustZeroOnConstruct || (BUILDFLAG(RAW_PTR_ZERO_ON_CONSTRUCT) &&
315                                      !partition_alloc::internal::ContainsFlags(
316                                          Traits,
317                                          RawPtrTraits::kAllowUninitialized));
318   static constexpr bool kZeroOnMove =
319       Impl::kMustZeroOnMove || BUILDFLAG(RAW_PTR_ZERO_ON_MOVE);
320   static constexpr bool kZeroOnDestruct =
321       Impl::kMustZeroOnDestruct || BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT);
322 
323 // A non-trivial default ctor is required for complex implementations (e.g.
324 // BackupRefPtr), or even for NoOpImpl when zeroing is requested.
325 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||                           \
326     BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) || \
327     BUILDFLAG(RAW_PTR_ZERO_ON_CONSTRUCT)
328   PA_ALWAYS_INLINE constexpr raw_ptr() noexcept {
329     if constexpr (kZeroOnConstruct) {
330       wrapped_ptr_ = nullptr;
331     }
332   }
333 #else
334   // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_|
335   // uninitialized).
336   PA_ALWAYS_INLINE constexpr raw_ptr() noexcept = default;
337   static_assert(!kZeroOnConstruct);
338 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
339         // BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) ||
340         // BUILDFLAG(RAW_PTR_ZERO_ON_CONSTRUCT)
341 
342 // A non-trivial copy ctor and assignment operator are required for complex
343 // implementations (e.g. BackupRefPtr). Unlike the blocks around, we don't need
344 // these for NoOpImpl even when zeroing is requested; better to keep them
345 // trivial.
346 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
347     BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR)
348   PA_ALWAYS_INLINE constexpr raw_ptr(const raw_ptr& p) noexcept
349       : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {
350     Impl::Trace(tracer_.owner_id(), p.wrapped_ptr_);
351   }
352 
353   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(const raw_ptr& p) noexcept {
354     // Duplicate before releasing, in case the pointer is assigned to itself.
355     //
356     // Unlike the move version of this operator, don't add |this != &p| branch,
357     // for performance reasons. Self-assignment is rare, so unconditionally
358     // calling `Duplicate()` is almost certainly cheaper than adding an
359     // additional branch, even if always correctly predicted.
360     T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
361     Impl::ReleaseWrappedPtr(wrapped_ptr_);
362     Impl::Untrace(tracer_.owner_id());
363     wrapped_ptr_ = new_ptr;
364     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
365     return *this;
366   }
367 #else
368   PA_ALWAYS_INLINE raw_ptr(const raw_ptr&) noexcept = default;
369   PA_ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
370 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
371         // BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR)
372 
373 // A non-trivial move ctor and assignment operator are required for complex
374 // implementations (e.g. BackupRefPtr), or even for NoOpImpl when zeroing is
375 // requested.
376 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||                           \
377     BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) || \
378     BUILDFLAG(RAW_PTR_ZERO_ON_MOVE)
379   PA_ALWAYS_INLINE constexpr raw_ptr(raw_ptr&& p) noexcept {
380     wrapped_ptr_ = p.wrapped_ptr_;
381     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
382     if constexpr (kZeroOnMove) {
383       p.wrapped_ptr_ = nullptr;
384       Impl::Untrace(p.tracer_.owner_id());
385     }
386   }
387   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(raw_ptr&& p) noexcept {
388     // Unlike the the copy version of this operator, this branch is necessary
389     // for correctness.
390     if (PA_LIKELY(this != &p)) {
391       Impl::ReleaseWrappedPtr(wrapped_ptr_);
392       Impl::Untrace(tracer_.owner_id());
393       wrapped_ptr_ = p.wrapped_ptr_;
394       Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
395       if constexpr (kZeroOnMove) {
396         p.wrapped_ptr_ = nullptr;
397         Impl::Untrace(p.tracer_.owner_id());
398       }
399     }
400     return *this;
401   }
402 #else
403   PA_ALWAYS_INLINE raw_ptr(raw_ptr&&) noexcept = default;
404   PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
405   static_assert(!kZeroOnMove);
406 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
407         // BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) ||
408         // BUILDFLAG(RAW_PTR_ZERO_ON_MOVE)
409 
410 // A non-trivial default dtor is required for complex implementations (e.g.
411 // BackupRefPtr), or even for NoOpImpl when zeroing is requested.
412 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||                           \
413     BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) || \
414     BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT)
415   PA_ALWAYS_INLINE PA_CONSTEXPR_DTOR ~raw_ptr() noexcept {
416     Impl::ReleaseWrappedPtr(wrapped_ptr_);
417     Impl::Untrace(tracer_.owner_id());
418     // Work around external issues where raw_ptr is used after destruction.
419     if constexpr (kZeroOnDestruct) {
420       wrapped_ptr_ = nullptr;
421     }
422   }
423 #else
424   PA_ALWAYS_INLINE ~raw_ptr() noexcept = default;
425   static_assert(!kZeroOnDestruct);
426 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
427         // BUILDFLAG(USE_ASAN_UNOWNED_PTR) || BUILDFLAG(USE_HOOKABLE_RAW_PTR) ||
428         // BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT)
429 
430   // Cross-kind copy constructor.
431   // Move is not supported as different traits may use different ref-counts, so
432   // let move operations degrade to copy, which handles it well.
433   template <RawPtrTraits PassedTraits,
434             typename = std::enable_if_t<Traits != PassedTraits>>
435   PA_ALWAYS_INLINE constexpr explicit raw_ptr(
436       const raw_ptr<T, PassedTraits>& p) noexcept
437       : wrapped_ptr_(Impl::WrapRawPtrForDuplication(
438             raw_ptr_traits::ImplForTraits<raw_ptr<T, PassedTraits>::Traits>::
439                 UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_))) {
440     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
441     // Limit cross-kind conversions only to cases where `kMayDangle` gets added,
442     // because that's needed for ExtractAsDangling() and Unretained(Ref)Wrapper.
443     // Use a static_assert, instead of disabling via SFINAE, so that the
444     // compiler catches other conversions. Otherwise the implicit
445     // `raw_ptr<T> -> T* -> raw_ptr<>` route will be taken.
446     static_assert(Traits == (raw_ptr<T, PassedTraits>::Traits |
447                              RawPtrTraits::kMayDangle));
448   }
449 
450   // Cross-kind assignment.
451   // Move is not supported as different traits may use different ref-counts, so
452   // let move operations degrade to copy, which handles it well.
453   template <RawPtrTraits PassedTraits,
454             typename = std::enable_if_t<Traits != PassedTraits>>
455   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(
456       const raw_ptr<T, PassedTraits>& p) noexcept {
457     // Limit cross-kind assignments only to cases where `kMayDangle` gets added,
458     // because that's needed for ExtractAsDangling() and Unretained(Ref)Wrapper.
459     // Use a static_assert, instead of disabling via SFINAE, so that the
460     // compiler catches other conversions. Otherwise the implicit
461     // `raw_ptr<T> -> T* -> raw_ptr<>` route will be taken.
462     static_assert(Traits == (raw_ptr<T, PassedTraits>::Traits |
463                              RawPtrTraits::kMayDangle));
464 
465     Impl::ReleaseWrappedPtr(wrapped_ptr_);
466     Impl::Untrace(tracer_.owner_id());
467     wrapped_ptr_ = Impl::WrapRawPtrForDuplication(
468         raw_ptr_traits::ImplForTraits<raw_ptr<T, PassedTraits>::Traits>::
469             UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_));
470     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
471     return *this;
472   }
473 
474   // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
475   // Ignore kZeroOnConstruct, because here the caller explicitly wishes to
476   // initialize with nullptr.
477   // NOLINTNEXTLINE(google-explicit-constructor)
478   PA_ALWAYS_INLINE constexpr raw_ptr(std::nullptr_t) noexcept
479       : wrapped_ptr_(nullptr) {}
480 
481   // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
482   // NOLINTNEXTLINE(google-explicit-constructor)
483   PA_ALWAYS_INLINE constexpr raw_ptr(T* p) noexcept
484       : wrapped_ptr_(Impl::WrapRawPtr(p)) {
485     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
486   }
487 
488   // Deliberately implicit in order to support implicit upcast.
489   template <typename U,
490             typename = std::enable_if_t<
491                 std::is_convertible_v<U*, T*> &&
492                 !std::is_void_v<typename std::remove_cv<T>::type>>>
493   // NOLINTNEXTLINE(google-explicit-constructor)
494   PA_ALWAYS_INLINE constexpr raw_ptr(const raw_ptr<U, Traits>& ptr) noexcept
495       : wrapped_ptr_(
496             Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {
497     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
498   }
499   // Deliberately implicit in order to support implicit upcast.
500   template <typename U,
501             typename = std::enable_if_t<
502                 std::is_convertible_v<U*, T*> &&
503                 !std::is_void_v<typename std::remove_cv<T>::type>>>
504   // NOLINTNEXTLINE(google-explicit-constructor)
505   PA_ALWAYS_INLINE constexpr raw_ptr(raw_ptr<U, Traits>&& ptr) noexcept
506       : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
507     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
508     if constexpr (kZeroOnMove) {
509       ptr.wrapped_ptr_ = nullptr;
510       Impl::Untrace(ptr.tracer_.owner_id());
511     }
512   }
513 
514   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(std::nullptr_t) noexcept {
515     Impl::ReleaseWrappedPtr(wrapped_ptr_);
516     Impl::Untrace(tracer_.owner_id());
517     wrapped_ptr_ = nullptr;
518     return *this;
519   }
520   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(T* p) noexcept {
521     Impl::ReleaseWrappedPtr(wrapped_ptr_);
522     Impl::Untrace(tracer_.owner_id());
523     wrapped_ptr_ = Impl::WrapRawPtr(p);
524     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
525     return *this;
526   }
527 
528   // Upcast assignment
529   template <typename U,
530             typename = std::enable_if_t<
531                 std::is_convertible_v<U*, T*> &&
532                 !std::is_void_v<typename std::remove_cv<T>::type>>>
533   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(
534       const raw_ptr<U, Traits>& ptr) noexcept {
535     // Make sure that pointer isn't assigned to itself (look at raw_ptr address,
536     // not its contained pointer value). The comparison is only needed when they
537     // are the same type, otherwise they can't be the same raw_ptr object.
538 #if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
539     if constexpr (std::is_same_v<raw_ptr, std::decay_t<decltype(ptr)>>) {
540       PA_RAW_PTR_CHECK(this != &ptr);
541     }
542 #endif
543     Impl::ReleaseWrappedPtr(wrapped_ptr_);
544     Impl::Untrace(tracer_.owner_id());
545     wrapped_ptr_ =
546         Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_));
547     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
548     return *this;
549   }
550   template <typename U,
551             typename = std::enable_if_t<
552                 std::is_convertible_v<U*, T*> &&
553                 !std::is_void_v<typename std::remove_cv<T>::type>>>
554   PA_ALWAYS_INLINE constexpr raw_ptr& operator=(
555       raw_ptr<U, Traits>&& ptr) noexcept {
556     // Make sure that pointer isn't assigned to itself (look at raw_ptr address,
557     // not its contained pointer value). The comparison is only needed when they
558     // are the same type, otherwise they can't be the same raw_ptr object.
559 #if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
560     if constexpr (std::is_same_v<raw_ptr, std::decay_t<decltype(ptr)>>) {
561       PA_RAW_PTR_CHECK(this != &ptr);
562     }
563 #endif
564     Impl::ReleaseWrappedPtr(wrapped_ptr_);
565     Impl::Untrace(tracer_.owner_id());
566     wrapped_ptr_ = Impl::template Upcast<T, U>(ptr.wrapped_ptr_);
567     Impl::Trace(tracer_.owner_id(), wrapped_ptr_);
568     if constexpr (kZeroOnMove) {
569       ptr.wrapped_ptr_ = nullptr;
570       Impl::Untrace(ptr.tracer_.owner_id());
571     }
572     return *this;
573   }
574 
575   // Avoid using. The goal of raw_ptr is to be as close to raw pointer as
576   // possible, so use it only if absolutely necessary (e.g. for const_cast).
577   PA_ALWAYS_INLINE constexpr T* get() const { return GetForExtraction(); }
578 
579   // You may use |raw_ptr<T>::AsEphemeralRawAddr()| to obtain |T**| or |T*&|
580   // from |raw_ptr<T>|, as long as you follow these requirements:
581   // - DO NOT carry T**/T*& obtained via AsEphemeralRawAddr() out of
582   //   expression.
583   // - DO NOT use raw_ptr or T**/T*& multiple times within an expression.
584   //
585   // https://chromium.googlesource.com/chromium/src/+/main/base/memory/raw_ptr.md#in_out-arguments-need-to-be-refactored
586   class EphemeralRawAddr {
587    public:
588     EphemeralRawAddr(const EphemeralRawAddr&) = delete;
589     EphemeralRawAddr& operator=(const EphemeralRawAddr&) = delete;
590     void* operator new(size_t) = delete;
591     void* operator new(size_t, void*) = delete;
592     PA_ALWAYS_INLINE PA_CONSTEXPR_DTOR ~EphemeralRawAddr() { original = copy; }
593 
594     PA_ALWAYS_INLINE constexpr T** operator&() && PA_LIFETIME_BOUND {
595       return &copy;
596     }
597     // NOLINTNEXTLINE(google-explicit-constructor)
598     PA_ALWAYS_INLINE constexpr operator T*&() && PA_LIFETIME_BOUND {
599       return copy;
600     }
601 
602    private:
603     friend class raw_ptr;
604     PA_ALWAYS_INLINE constexpr explicit EphemeralRawAddr(raw_ptr& ptr)
605         : copy(ptr.get()), original(ptr) {}
606     T* copy;
607     raw_ptr& original;  // Original pointer.
608   };
609   PA_ALWAYS_INLINE PA_CONSTEXPR_DTOR EphemeralRawAddr AsEphemeralRawAddr() & {
610     return EphemeralRawAddr(*this);
611   }
612 
613   PA_ALWAYS_INLINE constexpr explicit operator bool() const {
614     return !!wrapped_ptr_;
615   }
616 
617   template <typename U = T,
618             typename = std::enable_if_t<
619                 !std::is_void_v<typename std::remove_cv<U>::type>>>
620   PA_ALWAYS_INLINE constexpr U& operator*() const {
621     return *GetForDereference();
622   }
623   PA_ALWAYS_INLINE constexpr T* operator->() const {
624     return GetForDereference();
625   }
626 
627   // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
628   // NOLINTNEXTLINE(google-explicit-constructor)
629   PA_ALWAYS_INLINE constexpr operator T*() const { return GetForExtraction(); }
630   template <typename U>
631   PA_ALWAYS_INLINE constexpr explicit operator U*() const {
632     // This operator may be invoked from static_cast, meaning the types may not
633     // be implicitly convertible, hence the need for static_cast here.
634     return static_cast<U*>(GetForExtraction());
635   }
636 
637   PA_ALWAYS_INLINE constexpr raw_ptr& operator++() {
638     static_assert(
639         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
640         "cannot increment raw_ptr unless AllowPtrArithmetic trait is present.");
641     wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1, true);
642     return *this;
643   }
644   PA_ALWAYS_INLINE constexpr raw_ptr& operator--() {
645     static_assert(
646         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
647         "cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.");
648     wrapped_ptr_ = Impl::Retreat(wrapped_ptr_, 1, true);
649     return *this;
650   }
651   PA_ALWAYS_INLINE constexpr raw_ptr operator++(int /* post_increment */) {
652     static_assert(
653         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
654         "cannot increment raw_ptr unless AllowPtrArithmetic trait is present.");
655     raw_ptr result = *this;
656     ++(*this);
657     return result;
658   }
659   PA_ALWAYS_INLINE constexpr raw_ptr operator--(int /* post_decrement */) {
660     static_assert(
661         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
662         "cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.");
663     raw_ptr result = *this;
664     --(*this);
665     return result;
666   }
667   template <
668       typename Z,
669       typename = std::enable_if_t<partition_alloc::internal::is_offset_type<Z>>>
670   PA_ALWAYS_INLINE constexpr raw_ptr& operator+=(Z delta_elems) {
671     static_assert(
672         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
673         "cannot increment raw_ptr unless AllowPtrArithmetic trait is present.");
674     wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems, true);
675     return *this;
676   }
677   template <
678       typename Z,
679       typename = std::enable_if_t<partition_alloc::internal::is_offset_type<Z>>>
680   PA_ALWAYS_INLINE constexpr raw_ptr& operator-=(Z delta_elems) {
681     static_assert(
682         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
683         "cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.");
684     wrapped_ptr_ = Impl::Retreat(wrapped_ptr_, delta_elems, true);
685     return *this;
686   }
687 
688   template <typename Z,
689             typename U = T,
690             typename = std::enable_if_t<
691                 !std::is_void_v<typename std::remove_cv<U>::type> &&
692                 partition_alloc::internal::is_offset_type<Z>>>
693   PA_ALWAYS_INLINE constexpr U& operator[](Z delta_elems) const {
694     static_assert(
695         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
696         "cannot index raw_ptr unless AllowPtrArithmetic trait is present.");
697     // Call SafelyUnwrapPtrForDereference() to simulate what GetForDereference()
698     // does, but without creating a temporary.
699     return *Impl::SafelyUnwrapPtrForDereference(
700         Impl::Advance(wrapped_ptr_, delta_elems, false));
701   }
702 
703   // Do not disable operator+() and operator-().
704   // They provide OOB checks, which prevent from assigning an arbitrary value to
705   // raw_ptr, leading BRP to modifying arbitrary memory thinking it's ref-count.
706   // Keep them enabled, which may be blocked later when attempting to apply the
707   // += or -= operation, when disabled. In the absence of operators +/-, the
708   // compiler is free to implicitly convert to the underlying T* representation
709   // and perform ordinary pointer arithmetic, thus invalidating the purpose
710   // behind disabling them.
711   //
712   // For example, disabling these when `!is_offset_type<Z>` would remove the
713   // operators for Z=uint64_t on 32-bit systems. The compiler instead would
714   // generate code that converts `raw_ptr<T>` to `T*` and adds uint64_t to that,
715   // bypassing the OOB protection entirely.
716   template <typename Z>
717   PA_ALWAYS_INLINE friend constexpr raw_ptr operator+(const raw_ptr& p,
718                                                       Z delta_elems) {
719     // Don't check `is_offset_type<Z>` here, as existence of `Advance` is
720     // already gated on that, and we'd get double errors.
721     static_assert(
722         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
723         "cannot add to raw_ptr unless AllowPtrArithmetic trait is present.");
724     raw_ptr result = Impl::Advance(p.wrapped_ptr_, delta_elems, false);
725     return result;
726   }
727   template <typename Z>
728   PA_ALWAYS_INLINE friend constexpr raw_ptr operator+(Z delta_elems,
729                                                       const raw_ptr& p) {
730     return p + delta_elems;
731   }
732   template <typename Z>
733   PA_ALWAYS_INLINE friend constexpr raw_ptr operator-(const raw_ptr& p,
734                                                       Z delta_elems) {
735     // Don't check `is_offset_type<Z>` here, as existence of `Retreat` is
736     // already gated on that, and we'd get double errors.
737     static_assert(raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
738                   "cannot subtract from raw_ptr unless AllowPtrArithmetic "
739                   "trait is present.");
740     raw_ptr result = Impl::Retreat(p.wrapped_ptr_, delta_elems, false);
741     return result;
742   }
743 
744   // The "Do not disable operator+() and operator-()" comment above doesn't
745   // apply to the delta operator-() below.
746   PA_ALWAYS_INLINE friend constexpr ptrdiff_t operator-(const raw_ptr& p1,
747                                                         const raw_ptr& p2) {
748     static_assert(
749         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
750         "cannot subtract raw_ptrs unless AllowPtrArithmetic trait is present.");
751     return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
752   }
753   PA_ALWAYS_INLINE friend constexpr ptrdiff_t operator-(T* p1,
754                                                         const raw_ptr& p2) {
755     static_assert(
756         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
757         "cannot subtract raw_ptrs unless AllowPtrArithmetic trait is present.");
758     return Impl::GetDeltaElems(p1, p2.wrapped_ptr_);
759   }
760   PA_ALWAYS_INLINE friend constexpr ptrdiff_t operator-(const raw_ptr& p1,
761                                                         T* p2) {
762     static_assert(
763         raw_ptr_traits::IsPtrArithmeticAllowed(Traits),
764         "cannot subtract raw_ptrs unless AllowPtrArithmetic trait is present.");
765     return Impl::GetDeltaElems(p1.wrapped_ptr_, p2);
766   }
767 
768   // Stop referencing the underlying pointer and free its memory. Compared to
769   // raw delete calls, this avoids the raw_ptr to be temporarily dangling
770   // during the free operation, which will lead to taking the slower path that
771   // involves quarantine.
772   PA_ALWAYS_INLINE constexpr void ClearAndDelete() noexcept {
773     delete GetForExtractionAndReset();
774   }
775   PA_ALWAYS_INLINE constexpr void ClearAndDeleteArray() noexcept {
776     delete[] GetForExtractionAndReset();
777   }
778 
779   // Clear the underlying pointer and return another raw_ptr instance
780   // that is allowed to dangle.
781   // This can be useful in cases such as:
782   // ```
783   //  ptr.ExtractAsDangling()->SelfDestroy();
784   // ```
785   // ```
786   //  c_style_api_do_something_and_destroy(ptr.ExtractAsDangling());
787   // ```
788   // NOTE, avoid using this method as it indicates an error-prone memory
789   // ownership pattern. If possible, use smart pointers like std::unique_ptr<>
790   // instead of raw_ptr<>.
791   // If you have to use it, avoid saving the return value in a long-lived
792   // variable (or worse, a field)! It's meant to be used as a temporary, to be
793   // passed into a cleanup & freeing function, and destructed at the end of the
794   // statement.
795   PA_ALWAYS_INLINE constexpr DanglingType ExtractAsDangling() noexcept {
796     DanglingType res(std::move(*this));
797     // Not all implementation clear the source pointer on move. Furthermore,
798     // even for implemtantions that do, cross-kind conversions (that add
799     // kMayDangle) fall back to a copy, instead of move. So do it here just in
800     // case. Should be cheap.
801     operator=(nullptr);
802     return res;
803   }
804 
805   // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t.
806   // Strictly speaking, it is not necessary to provide these: the compiler can
807   // use the conversion operator implicitly to allow comparisons to fall back to
808   // comparisons between raw pointers. However, `operator T*`/`operator U*` may
809   // perform safety checks with a higher runtime cost, so to avoid this, provide
810   // explicit comparison operators for all combinations of parameters.
811 
812   // Comparisons between `raw_ptr`s. This unusual declaration and separate
813   // definition below is because `GetForComparison()` is a private method. The
814   // more conventional approach of defining a comparison operator between
815   // `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
816   // because a comparison operator defined inline would not be allowed to call
817   // `raw_ptr<U>`'s private `GetForComparison()` method.
818   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
819   friend constexpr bool operator==(const raw_ptr<U, R1>& lhs,
820                                    const raw_ptr<V, R2>& rhs);
821   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
822   friend constexpr bool operator!=(const raw_ptr<U, R1>& lhs,
823                                    const raw_ptr<V, R2>& rhs);
824   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
825   friend constexpr bool operator<(const raw_ptr<U, R1>& lhs,
826                                   const raw_ptr<V, R2>& rhs);
827   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
828   friend constexpr bool operator>(const raw_ptr<U, R1>& lhs,
829                                   const raw_ptr<V, R2>& rhs);
830   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
831   friend constexpr bool operator<=(const raw_ptr<U, R1>& lhs,
832                                    const raw_ptr<V, R2>& rhs);
833   template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
834   friend constexpr bool operator>=(const raw_ptr<U, R1>& lhs,
835                                    const raw_ptr<V, R2>& rhs);
836 
837   // Comparisons with U*. These operators also handle the case where the RHS is
838   // T*.
839   template <typename U>
840   PA_ALWAYS_INLINE friend constexpr bool operator==(const raw_ptr& lhs,
841                                                     U* rhs) {
842     return lhs.GetForComparison() == rhs;
843   }
844   template <typename U>
845   PA_ALWAYS_INLINE friend constexpr bool operator!=(const raw_ptr& lhs,
846                                                     U* rhs) {
847     return !(lhs == rhs);
848   }
849   template <typename U>
850   PA_ALWAYS_INLINE friend constexpr bool operator==(U* lhs,
851                                                     const raw_ptr& rhs) {
852     return rhs == lhs;  // Reverse order to call the operator above.
853   }
854   template <typename U>
855   PA_ALWAYS_INLINE friend constexpr bool operator!=(U* lhs,
856                                                     const raw_ptr& rhs) {
857     return rhs != lhs;  // Reverse order to call the operator above.
858   }
859   template <typename U>
860   PA_ALWAYS_INLINE friend constexpr bool operator<(const raw_ptr& lhs, U* rhs) {
861     return lhs.GetForComparison() < rhs;
862   }
863   template <typename U>
864   PA_ALWAYS_INLINE friend constexpr bool operator<=(const raw_ptr& lhs,
865                                                     U* rhs) {
866     return lhs.GetForComparison() <= rhs;
867   }
868   template <typename U>
869   PA_ALWAYS_INLINE friend constexpr bool operator>(const raw_ptr& lhs, U* rhs) {
870     return lhs.GetForComparison() > rhs;
871   }
872   template <typename U>
873   PA_ALWAYS_INLINE friend constexpr bool operator>=(const raw_ptr& lhs,
874                                                     U* rhs) {
875     return lhs.GetForComparison() >= rhs;
876   }
877   template <typename U>
878   PA_ALWAYS_INLINE friend constexpr bool operator<(U* lhs, const raw_ptr& rhs) {
879     return lhs < rhs.GetForComparison();
880   }
881   template <typename U>
882   PA_ALWAYS_INLINE friend constexpr bool operator<=(U* lhs,
883                                                     const raw_ptr& rhs) {
884     return lhs <= rhs.GetForComparison();
885   }
886   template <typename U>
887   PA_ALWAYS_INLINE friend constexpr bool operator>(U* lhs, const raw_ptr& rhs) {
888     return lhs > rhs.GetForComparison();
889   }
890   template <typename U>
891   PA_ALWAYS_INLINE friend constexpr bool operator>=(U* lhs,
892                                                     const raw_ptr& rhs) {
893     return lhs >= rhs.GetForComparison();
894   }
895 
896   // Comparisons with `std::nullptr_t`.
897   PA_ALWAYS_INLINE friend constexpr bool operator==(const raw_ptr& lhs,
898                                                     std::nullptr_t) {
899     return !lhs;
900   }
901   PA_ALWAYS_INLINE friend constexpr bool operator!=(const raw_ptr& lhs,
902                                                     std::nullptr_t) {
903     return !!lhs;  // Use !! otherwise the costly implicit cast will be used.
904   }
905   PA_ALWAYS_INLINE friend constexpr bool operator==(std::nullptr_t,
906                                                     const raw_ptr& rhs) {
907     return !rhs;
908   }
909   PA_ALWAYS_INLINE friend constexpr bool operator!=(std::nullptr_t,
910                                                     const raw_ptr& rhs) {
911     return !!rhs;  // Use !! otherwise the costly implicit cast will be used.
912   }
913 
914   PA_ALWAYS_INLINE friend constexpr void swap(raw_ptr& lhs,
915                                               raw_ptr& rhs) noexcept {
916     Impl::IncrementSwapCountForTest();
917     std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_);
918   }
919 
920   PA_ALWAYS_INLINE void ReportIfDangling() const noexcept {
921 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
922     Impl::ReportIfDangling(wrapped_ptr_);
923 #endif
924   }
925 
926  private:
927   // This getter is meant for situations where the pointer is meant to be
928   // dereferenced. It is allowed to crash on nullptr (it may or may not),
929   // because it knows that the caller will crash on nullptr.
930   PA_ALWAYS_INLINE constexpr T* GetForDereference() const {
931     return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_);
932   }
933   // This getter is meant for situations where the raw pointer is meant to be
934   // extracted outside of this class, but not necessarily with an intention to
935   // dereference. It mustn't crash on nullptr.
936   PA_ALWAYS_INLINE constexpr T* GetForExtraction() const {
937     return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
938   }
939   // This getter is meant *only* for situations where the pointer is meant to be
940   // compared (guaranteeing no dereference or extraction outside of this class).
941   // Any verifications can and should be skipped for performance reasons.
942   PA_ALWAYS_INLINE constexpr T* GetForComparison() const {
943     return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_);
944   }
945 
946   PA_ALWAYS_INLINE constexpr T* GetForExtractionAndReset() {
947     T* ptr = GetForExtraction();
948     operator=(nullptr);
949     return ptr;
950   }
951 
952   T* wrapped_ptr_;
953   PA_NO_UNIQUE_ADDRESS internal::InstanceTracer tracer_;
954 
955   template <typename U, base::RawPtrTraits R>
956   friend class raw_ptr;
957 };
958 
959 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
960 PA_ALWAYS_INLINE constexpr bool operator==(const raw_ptr<U, Traits1>& lhs,
961                                            const raw_ptr<V, Traits2>& rhs) {
962   return lhs.GetForComparison() == rhs.GetForComparison();
963 }
964 
965 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
966 PA_ALWAYS_INLINE constexpr bool operator!=(const raw_ptr<U, Traits1>& lhs,
967                                            const raw_ptr<V, Traits2>& rhs) {
968   return !(lhs == rhs);
969 }
970 
971 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
972 PA_ALWAYS_INLINE constexpr bool operator<(const raw_ptr<U, Traits1>& lhs,
973                                           const raw_ptr<V, Traits2>& rhs) {
974   return lhs.GetForComparison() < rhs.GetForComparison();
975 }
976 
977 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
978 PA_ALWAYS_INLINE constexpr bool operator>(const raw_ptr<U, Traits1>& lhs,
979                                           const raw_ptr<V, Traits2>& rhs) {
980   return lhs.GetForComparison() > rhs.GetForComparison();
981 }
982 
983 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
984 PA_ALWAYS_INLINE constexpr bool operator<=(const raw_ptr<U, Traits1>& lhs,
985                                            const raw_ptr<V, Traits2>& rhs) {
986   return lhs.GetForComparison() <= rhs.GetForComparison();
987 }
988 
989 template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
990 PA_ALWAYS_INLINE constexpr bool operator>=(const raw_ptr<U, Traits1>& lhs,
991                                            const raw_ptr<V, Traits2>& rhs) {
992   return lhs.GetForComparison() >= rhs.GetForComparison();
993 }
994 
995 template <typename T>
996 struct IsRawPtr : std::false_type {};
997 
998 template <typename T, RawPtrTraits Traits>
999 struct IsRawPtr<raw_ptr<T, Traits>> : std::true_type {};
1000 
1001 template <typename T>
1002 inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
1003 
1004 template <typename T>
1005 inline constexpr bool IsRawPtrMayDangleV = false;
1006 
1007 template <typename T, RawPtrTraits Traits>
1008 inline constexpr bool IsRawPtrMayDangleV<raw_ptr<T, Traits>> =
1009     partition_alloc::internal::ContainsFlags(Traits, RawPtrTraits::kMayDangle);
1010 
1011 // Template helpers for working with T* or raw_ptr<T>.
1012 template <typename T>
1013 struct IsRawPointerHelper : std::false_type {};
1014 
1015 template <typename T>
1016 struct IsRawPointerHelper<T*> : std::true_type {};
1017 
1018 template <typename T, RawPtrTraits Traits>
1019 struct IsRawPointerHelper<raw_ptr<T, Traits>> : std::true_type {};
1020 
1021 template <typename T>
1022 inline constexpr bool IsRawPointer = IsRawPointerHelper<T>::value;
1023 
1024 template <typename T>
1025 struct RemoveRawPointer {
1026   using type = T;
1027 };
1028 
1029 template <typename T>
1030 struct RemoveRawPointer<T*> {
1031   using type = T;
1032 };
1033 
1034 template <typename T, RawPtrTraits Traits>
1035 struct RemoveRawPointer<raw_ptr<T, Traits>> {
1036   using type = T;
1037 };
1038 
1039 template <typename T>
1040 using RemoveRawPointerT = typename RemoveRawPointer<T>::type;
1041 
1042 }  // namespace base
1043 
1044 using base::raw_ptr;
1045 
1046 // DisableDanglingPtrDetection option for raw_ptr annotates
1047 // "intentional-and-safe" dangling pointers. It is meant to be used at the
1048 // margin, only if there is no better way to re-architecture the code.
1049 //
1050 // Usage:
1051 // raw_ptr<T, DisableDanglingPtrDetection> dangling_ptr;
1052 //
1053 // When using it, please provide a justification about what guarantees that it
1054 // will never be dereferenced after becoming dangling.
1055 constexpr inline auto DisableDanglingPtrDetection =
1056     base::RawPtrTraits::kMayDangle;
1057 
1058 // See `docs/dangling_ptr.md`
1059 // Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
1060 // occurrences are meant to be removed. See https://crbug.com/1291138.
1061 constexpr inline auto DanglingUntriaged = base::RawPtrTraits::kMayDangle;
1062 
1063 // Unlike DanglingUntriaged, this annotates raw_ptrs that are known to
1064 // dangle only occasionally on the CQ.
1065 //
1066 // These were found from CQ runs and analysed in this dashboard:
1067 // https://docs.google.com/spreadsheets/d/1k12PQOG4y1-UEV9xDfP1F8FSk4cVFywafEYHmzFubJ8/
1068 //
1069 // This is not meant to be added manually. You can ignore this flag.
1070 constexpr inline auto FlakyDanglingUntriaged = base::RawPtrTraits::kMayDangle;
1071 
1072 // Dangling raw_ptr that is more likely to cause UAF: its memory was freed in
1073 // one task, and the raw_ptr was released in a different one.
1074 //
1075 // This is not meant to be added manually. You can ignore this flag.
1076 constexpr inline auto AcrossTasksDanglingUntriaged =
1077     base::RawPtrTraits::kMayDangle;
1078 
1079 // The use of pointer arithmetic with raw_ptr is strongly discouraged and
1080 // disabled by default. Usually a container like span<> should be used
1081 // instead of the raw_ptr.
1082 constexpr inline auto AllowPtrArithmetic =
1083     base::RawPtrTraits::kAllowPtrArithmetic;
1084 
1085 // The use of uninitialized pointers is strongly discouraged. raw_ptrs will
1086 // be initialized to nullptr by default in all cases when building against
1087 // Chromium. However, third-party projects built in a standalone manner may
1088 // wish to opt out where possible. One way to do this is via buildflags,
1089 // thus affecting all raw_ptrs, but a finer-grained mechanism is the use
1090 // of the kAllowUninitialized trait.
1091 //
1092 // Note that opting out may not always be effective, given that algorithms
1093 // like BackupRefPtr require nullptr initializaion for correctness and thus
1094 // silently enforce it.
1095 constexpr inline auto AllowUninitialized =
1096     base::RawPtrTraits::kAllowUninitialized;
1097 
1098 // This flag is used to tag a subset of dangling pointers. Similarly to
1099 // DanglingUntriaged, those pointers are known to be dangling. However, we also
1100 // detected that those raw_ptr's were never released (either by calling
1101 // raw_ptr's destructor or by resetting its value), which can ultimately put
1102 // pressure on the BRP quarantine.
1103 //
1104 // This is not meant to be added manually. You can ignore this flag.
1105 constexpr inline auto LeakedDanglingUntriaged = base::RawPtrTraits::kMayDangle;
1106 
1107 // Temporary introduced alias in the context of rewriting std::vector<T*> into
1108 // std::vector<raw_ptr<T>> and in order to temporarily bypass the dangling ptr
1109 // checks on the CQ. This alias will be removed gradually after the cl lands and
1110 // will be replaced by DanglingUntriaged where necessary.
1111 constexpr inline auto VectorExperimental = base::RawPtrTraits::kMayDangle;
1112 
1113 // Temporary alias introduced in the context of rewriting std::set<T*> into
1114 // std::set<raw_ptr<T>> and in order to temporarily bypass the dangling ptr
1115 // checks on the CQ. This alias will be removed gradually after the rewrite cl
1116 // lands and will be replaced by DanglingUntriaged where necessary.
1117 constexpr inline auto SetExperimental = base::RawPtrTraits::kMayDangle;
1118 
1119 // Temporary alias introduced in the context of rewriting more containers and in
1120 // order to temporarily bypass the dangling ptr checks on the CQ. This alias
1121 // will be removed gradually after the rewrite cl lands and will be replaced by
1122 // DanglingUntriaged where necessary.
1123 constexpr inline auto CtnExperimental = base::RawPtrTraits::kMayDangle;
1124 
1125 // Public verson used in callbacks arguments when it is known that they might
1126 // receive dangling pointers. In any other cases, please
1127 // use one of:
1128 // - raw_ptr<T, DanglingUntriaged>
1129 // - raw_ptr<T, DisableDanglingPtrDetection>
1130 template <typename T, base::RawPtrTraits Traits = base::RawPtrTraits::kEmpty>
1131 using MayBeDangling = base::raw_ptr<T, Traits | base::RawPtrTraits::kMayDangle>;
1132 
1133 namespace std {
1134 
1135 // Override so set/map lookups do not create extra raw_ptr. This also allows
1136 // dangling pointers to be used for lookup.
1137 template <typename T, base::RawPtrTraits Traits>
1138 struct less<raw_ptr<T, Traits>> {
1139   using Impl = typename raw_ptr<T, Traits>::Impl;
1140   using is_transparent = void;
1141 
1142   bool operator()(const raw_ptr<T, Traits>& lhs,
1143                   const raw_ptr<T, Traits>& rhs) const {
1144     Impl::IncrementLessCountForTest();
1145     return lhs < rhs;
1146   }
1147 
1148   bool operator()(T* lhs, const raw_ptr<T, Traits>& rhs) const {
1149     Impl::IncrementLessCountForTest();
1150     return lhs < rhs;
1151   }
1152 
1153   bool operator()(const raw_ptr<T, Traits>& lhs, T* rhs) const {
1154     Impl::IncrementLessCountForTest();
1155     return lhs < rhs;
1156   }
1157 };
1158 
1159 template <typename T, base::RawPtrTraits Traits>
1160 struct hash<raw_ptr<T, Traits>> {
1161   typedef raw_ptr<T, Traits> argument_type;
1162   typedef std::size_t result_type;
1163   result_type operator()(argument_type const& ptr) const {
1164     return hash<T*>()(ptr.get());
1165   }
1166 };
1167 
1168 // Define for cases where raw_ptr<T> holds a pointer to an array of type T.
1169 // This is consistent with definition of std::iterator_traits<T*>.
1170 // Algorithms like std::binary_search need that.
1171 template <typename T, base::RawPtrTraits Traits>
1172 struct iterator_traits<raw_ptr<T, Traits>> {
1173   using difference_type = ptrdiff_t;
1174   using value_type = std::remove_cv_t<T>;
1175   using pointer = T*;
1176   using reference = T&;
1177   using iterator_category = std::random_access_iterator_tag;
1178 };
1179 
1180 // Specialize std::pointer_traits. The latter is required to obtain the
1181 // underlying raw pointer in the std::to_address(pointer) overload.
1182 // Implementing the pointer_traits is the standard blessed way to customize
1183 // `std::to_address(pointer)` in C++20 [3].
1184 //
1185 // [1] https://wg21.link/pointer.traits.optmem
1186 
1187 template <typename T, ::base::RawPtrTraits Traits>
1188 struct pointer_traits<::raw_ptr<T, Traits>> {
1189   using pointer = ::raw_ptr<T, Traits>;
1190   using element_type = T;
1191   using difference_type = ptrdiff_t;
1192 
1193   template <typename U>
1194   using rebind = ::raw_ptr<U, Traits>;
1195 
1196   static constexpr pointer pointer_to(element_type& r) noexcept {
1197     return pointer(&r);
1198   }
1199 
1200   static constexpr element_type* to_address(pointer p) noexcept {
1201     return p.get();
1202   }
1203 };
1204 
1205 }  // namespace std
1206 
1207 #endif  // PARTITION_ALLOC_POINTERS_RAW_PTR_H_
1208