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