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