1 // Copyright 2022 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 #include "partition_alloc/pointers/raw_ref.h"
6
7 #include <functional>
8 #include <type_traits>
9
10 #include "base/memory/raw_ptr.h"
11 #include "base/test/gtest_util.h"
12 #include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h"
13 #include "partition_alloc/partition_alloc_buildflags.h"
14 #include "partition_alloc/pointers/raw_ptr_counting_impl_for_test.h"
15 #include "partition_alloc/pointers/raw_ptr_test_support.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
18 #include "base/debug/asan_service.h"
19 #include "base/memory/raw_ptr_asan_service.h"
20 #endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
21
22 namespace {
23
24 class BaseClass {};
25 class SubClass : public BaseClass {};
26
27 // raw_ref just defers to the superclass for implementations, so it
28 // can't add more data types.
29 static_assert(sizeof(raw_ref<int>) == sizeof(raw_ptr<int>));
30
31 // Since it can't hold null, raw_ref is not default-constructible.
32 static_assert(!std::is_default_constructible_v<raw_ref<int>>);
33 static_assert(!std::is_default_constructible_v<raw_ref<const int>>);
34
35 // A mutable reference can only be constructed from a mutable lvalue reference.
36 static_assert(!std::is_constructible_v<raw_ref<int>, const int>);
37 static_assert(!std::is_constructible_v<raw_ref<int>, int>);
38 static_assert(!std::is_constructible_v<raw_ref<int>, const int&>);
39 static_assert(std::is_constructible_v<raw_ref<int>, int&>);
40 static_assert(!std::is_constructible_v<raw_ref<int>, const int*>);
41 static_assert(!std::is_constructible_v<raw_ref<int>, int*>);
42 static_assert(!std::is_constructible_v<raw_ref<int>, const int&&>);
43 static_assert(!std::is_constructible_v<raw_ref<int>, int&&>);
44 // Same for assignment.
45 static_assert(!std::is_assignable_v<raw_ref<int>, const int>);
46 static_assert(!std::is_assignable_v<raw_ref<int>, int>);
47 static_assert(!std::is_assignable_v<raw_ref<int>, const int&>);
48 static_assert(std::is_assignable_v<raw_ref<int>, int&>);
49 static_assert(!std::is_assignable_v<raw_ref<int>, const int*>);
50 static_assert(!std::is_assignable_v<raw_ref<int>, int*>);
51 static_assert(!std::is_assignable_v<raw_ref<int>, const int&&>);
52 static_assert(!std::is_assignable_v<raw_ref<int>, int&&>);
53
54 // A const reference can be constructed from a const or mutable lvalue
55 // reference.
56 static_assert(!std::is_constructible_v<raw_ref<const int>, const int>);
57 static_assert(!std::is_constructible_v<raw_ref<const int>, int>);
58 static_assert(std::is_constructible_v<raw_ref<const int>, const int&>);
59 static_assert(std::is_constructible_v<raw_ref<const int>, int&>);
60 static_assert(!std::is_constructible_v<raw_ref<const int>, const int*>);
61 static_assert(!std::is_constructible_v<raw_ref<const int>, int*>);
62 static_assert(!std::is_constructible_v<raw_ref<const int>, const int&&>);
63 static_assert(!std::is_constructible_v<raw_ref<const int>, int&&>);
64 // Same for assignment.
65 static_assert(!std::is_assignable_v<raw_ref<const int>, const int>);
66 static_assert(!std::is_assignable_v<raw_ref<const int>, int>);
67 static_assert(std::is_assignable_v<raw_ref<const int>, const int&>);
68 static_assert(std::is_assignable_v<raw_ref<const int>, int&>);
69 static_assert(!std::is_assignable_v<raw_ref<const int>, const int*>);
70 static_assert(!std::is_assignable_v<raw_ref<const int>, int*>);
71 static_assert(!std::is_assignable_v<raw_ref<const int>, const int&&>);
72 static_assert(!std::is_assignable_v<raw_ref<const int>, int&&>);
73
74 // Same trivial operations (or not) as raw_ptr<T>.
75 static_assert(std::is_trivially_constructible_v<raw_ref<int>, const int&> ==
76 std::is_trivially_constructible_v<raw_ptr<int>, const int&>);
77 static_assert(std::is_trivially_destructible_v<raw_ref<int>> ==
78 std::is_trivially_destructible_v<raw_ptr<int>>);
79 // But constructing from another raw_ref must check if it's internally null
80 // (which indicates use-after-move).
81 static_assert(!std::is_trivially_move_constructible_v<raw_ref<int>>);
82 static_assert(!std::is_trivially_move_assignable_v<raw_ref<int>>);
83 static_assert(!std::is_trivially_copy_constructible_v<raw_ref<int>>);
84 static_assert(!std::is_trivially_copy_assignable_v<raw_ref<int>>);
85
86 // A raw_ref can be copied or moved.
87 static_assert(std::is_move_constructible_v<raw_ref<int>>);
88 static_assert(std::is_copy_constructible_v<raw_ref<int>>);
89 static_assert(std::is_move_assignable_v<raw_ref<int>>);
90 static_assert(std::is_copy_assignable_v<raw_ref<int>>);
91
92 // A SubClass can be converted to a BaseClass.
93 static_assert(std::is_constructible_v<raw_ref<BaseClass>, raw_ref<SubClass>>);
94 static_assert(
95 std::is_constructible_v<raw_ref<BaseClass>, const raw_ref<SubClass>&>);
96 static_assert(std::is_constructible_v<raw_ref<BaseClass>, raw_ref<SubClass>&&>);
97 static_assert(std::is_assignable_v<raw_ref<BaseClass>, raw_ref<SubClass>>);
98 static_assert(
99 std::is_assignable_v<raw_ref<BaseClass>, const raw_ref<SubClass>&>);
100 static_assert(std::is_assignable_v<raw_ref<BaseClass>, raw_ref<SubClass>&&>);
101 // A BaseClass can't be implicitly downcasted.
102 static_assert(!std::is_constructible_v<raw_ref<SubClass>, raw_ref<BaseClass>>);
103 static_assert(
104 !std::is_constructible_v<raw_ref<SubClass>, const raw_ref<BaseClass>&>);
105 static_assert(
106 !std::is_constructible_v<raw_ref<SubClass>, raw_ref<BaseClass>&&>);
107 static_assert(!std::is_assignable_v<raw_ref<SubClass>, raw_ref<BaseClass>>);
108 static_assert(
109 !std::is_assignable_v<raw_ref<SubClass>, const raw_ref<BaseClass>&>);
110 static_assert(!std::is_assignable_v<raw_ref<SubClass>, raw_ref<BaseClass>&&>);
111
112 // A raw_ref<BaseClass> can be constructed directly from a SubClass.
113 static_assert(std::is_constructible_v<raw_ref<BaseClass>, SubClass&>);
114 static_assert(std::is_assignable_v<raw_ref<BaseClass>, SubClass&>);
115 static_assert(std::is_constructible_v<raw_ref<const BaseClass>, SubClass&>);
116 static_assert(std::is_assignable_v<raw_ref<const BaseClass>, SubClass&>);
117 static_assert(
118 std::is_constructible_v<raw_ref<const BaseClass>, const SubClass&>);
119 static_assert(std::is_assignable_v<raw_ref<const BaseClass>, const SubClass&>);
120 // But a raw_ref<SubClass> can't be constructed from an implicit downcast from a
121 // BaseClass.
122 static_assert(!std::is_constructible_v<raw_ref<SubClass>, BaseClass&>);
123 static_assert(!std::is_assignable_v<raw_ref<SubClass>, BaseClass&>);
124 static_assert(!std::is_constructible_v<raw_ref<const SubClass>, BaseClass&>);
125 static_assert(!std::is_assignable_v<raw_ref<const SubClass>, BaseClass&>);
126 static_assert(
127 !std::is_constructible_v<raw_ref<const SubClass>, const BaseClass&>);
128 static_assert(!std::is_assignable_v<raw_ref<const SubClass>, const BaseClass&>);
129
130 // A mutable reference can be converted to const reference.
131 static_assert(std::is_constructible_v<raw_ref<const int>, raw_ref<int>>);
132 static_assert(std::is_assignable_v<raw_ref<const int>, raw_ref<int>>);
133 // A const reference can't be converted to mutable.
134 static_assert(!std::is_constructible_v<raw_ref<int>, raw_ref<const int>>);
135 static_assert(!std::is_assignable_v<raw_ref<int>, raw_ref<const int>>);
136
137 // The deref operator gives the internal reference.
138 static_assert(std::is_same_v<int&, decltype(*std::declval<raw_ref<int>>())>);
139 static_assert(
140 std::is_same_v<int&, decltype(*std::declval<const raw_ref<int>>())>);
141 static_assert(std::is_same_v<int&, decltype(*std::declval<raw_ref<int>&>())>);
142 static_assert(
143 std::is_same_v<int&, decltype(*std::declval<const raw_ref<int>&>())>);
144 static_assert(std::is_same_v<int&, decltype(*std::declval<raw_ref<int>&&>())>);
145 static_assert(
146 std::is_same_v<int&, decltype(*std::declval<const raw_ref<int>&&>())>);
147 // A const T is always returned as const.
148 static_assert(
149 std::is_same_v<const int&, decltype(*std::declval<raw_ref<const int>>())>);
150
151 // The arrow operator gives a (non-null) pointer to the internal reference.
152 static_assert(
153 std::is_same_v<int*, decltype(std::declval<raw_ref<int>>().operator->())>);
154 static_assert(
155 std::is_same_v<const int*,
156 decltype(std::declval<raw_ref<const int>>().operator->())>);
157
158 // Verify that raw_ref is a literal type, and its entire interface is constexpr.
159 //
160 // Constexpr destructors were introduced in C++20. PartitionAlloc's minimum
161 // supported C++ version is C++17, so raw_ref is not a literal type in C++17.
162 // Thus we only test for constexpr in C++20.
163 #if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
__anonf4a252480202() 164 static_assert([]() constexpr {
165 struct IntBase {};
166 struct Int : public IntBase {
167 int i = 0;
168 };
169
170 Int* i = new Int();
171 {
172 raw_ref<Int> r(*i); // raw_ref(T&)
173 r = *i; // operator=(T&)
174 raw_ref<Int> r2(r); // raw_ref(const raw_ref&)
175 raw_ref<Int> r3(std::move(r2)); // raw_ref(raw_ref&&)
176 r2 = r; // operator=(const raw_ref&)
177 r3 = std::move(r2); // operator=(raw_ref&&)
178 r2 = r; // Reset after move.
179 [[maybe_unused]] raw_ref<IntBase> r5(
180 r2); // raw_ref(const raw_ref<Convertible>&)
181 [[maybe_unused]] raw_ref<IntBase> r6(
182 std::move(r2)); // raw_ref(raw_ref<Convertible>&&)
183 r2 = r; // Reset after move.
184 r5 = r2; // operator=(const raw_ref<Convertible>&)
185 r6 = std::move(r2); // operator=(raw_ref<Convertible>&&)
186 raw_ref<Int>::from_ptr(i); // from_ptr(T*)
187 (*r).i += 1; // operator*()
188 r.get().i += 1; // get()
189 r->i += 1; // operator->()
190 r2 = r; // Reset after move.
191 swap(r, r2); // swap()
192 }
193 delete i;
194 return true;
195 }());
196 #endif
197
198 struct StructWithoutTypeBasedTraits {};
199 struct BaseWithTypeBasedTraits {};
200 struct DerivedWithTypeBasedTraits : BaseWithTypeBasedTraits {};
201
202 } // namespace
203
204 namespace base::raw_ptr_traits {
205 // `BaseWithTypeBasedTraits` and any derived classes have
206 // `RawPtrTraits::kDummyForTest`.
207 template <typename T>
208 constexpr auto kTypeTraits<
209 T,
210 std::enable_if_t<std::is_base_of_v<BaseWithTypeBasedTraits, T>>> =
211 RawPtrTraits::kDummyForTest;
212 } // namespace base::raw_ptr_traits
213
214 // `raw_ptr<T>` should have traits based on specialization of `kTypeTraits<T>`.
215 static_assert(!ContainsFlags(raw_ref<StructWithoutTypeBasedTraits>::Traits,
216 base::RawPtrTraits::kDummyForTest));
217 static_assert(ContainsFlags(raw_ref<BaseWithTypeBasedTraits>::Traits,
218 base::RawPtrTraits::kDummyForTest));
219 static_assert(ContainsFlags(raw_ref<DerivedWithTypeBasedTraits>::Traits,
220 base::RawPtrTraits::kDummyForTest));
221
222 namespace {
223
TEST(RawRef,Construct)224 TEST(RawRef, Construct) {
225 int i = 1;
226 auto r = raw_ref<int>(i);
227 EXPECT_EQ(&*r, &i);
228 auto cr = raw_ref<const int>(i);
229 EXPECT_EQ(&*cr, &i);
230 const int ci = 1;
231 auto cci = raw_ref<const int>(ci);
232 EXPECT_EQ(&*cci, &ci);
233 }
234
TEST(RawRef,CopyConstruct)235 TEST(RawRef, CopyConstruct) {
236 {
237 int i = 1;
238 auto r = raw_ref<int>(i);
239 EXPECT_EQ(&*r, &i);
240 auto r2 = raw_ref<int>(r);
241 EXPECT_EQ(&*r2, &i);
242 }
243 {
244 int i = 1;
245 auto r = raw_ref<const int>(i);
246 EXPECT_EQ(&*r, &i);
247 auto r2 = raw_ref<const int>(r);
248 EXPECT_EQ(&*r2, &i);
249 }
250 }
251
TEST(RawRef,MoveConstruct)252 TEST(RawRef, MoveConstruct) {
253 {
254 int i = 1;
255 auto r = raw_ref<int>(i);
256 EXPECT_EQ(&*r, &i);
257 auto r2 = raw_ref<int>(std::move(r));
258 EXPECT_EQ(&*r2, &i);
259 }
260 {
261 int i = 1;
262 auto r = raw_ref<const int>(i);
263 EXPECT_EQ(&*r, &i);
264 auto r2 = raw_ref<const int>(std::move(r));
265 EXPECT_EQ(&*r2, &i);
266 }
267 }
268
TEST(RawRef,CopyAssign)269 TEST(RawRef, CopyAssign) {
270 {
271 int i = 1;
272 int j = 2;
273 auto r = raw_ref<int>(i);
274 EXPECT_EQ(&*r, &i);
275 auto rj = raw_ref<int>(j);
276 r = rj;
277 EXPECT_EQ(&*r, &j);
278 }
279 {
280 int i = 1;
281 int j = 2;
282 auto r = raw_ref<const int>(i);
283 EXPECT_EQ(&*r, &i);
284 auto rj = raw_ref<const int>(j);
285 r = rj;
286 EXPECT_EQ(&*r, &j);
287 }
288 {
289 int i = 1;
290 int j = 2;
291 auto r = raw_ref<const int>(i);
292 EXPECT_EQ(&*r, &i);
293 auto rj = raw_ref<int>(j);
294 r = rj;
295 EXPECT_EQ(&*r, &j);
296 }
297 }
298
TEST(RawRef,CopyReassignAfterMove)299 TEST(RawRef, CopyReassignAfterMove) {
300 int i = 1;
301 int j = 1;
302 auto r = raw_ref<int>(i);
303 auto r2 = std::move(r);
304 r2 = raw_ref<int>(j);
305 // Reassign to the moved-from `r` so it can be used again.
306 r = r2;
307 EXPECT_EQ(&*r, &j);
308 }
309
TEST(RawRef,MoveAssign)310 TEST(RawRef, MoveAssign) {
311 {
312 int i = 1;
313 int j = 2;
314 auto r = raw_ref<int>(i);
315 EXPECT_EQ(&*r, &i);
316 r = raw_ref<int>(j);
317 EXPECT_EQ(&*r, &j);
318 }
319 {
320 int i = 1;
321 int j = 2;
322 auto r = raw_ref<const int>(i);
323 EXPECT_EQ(&*r, &i);
324 r = raw_ref<const int>(j);
325 EXPECT_EQ(&*r, &j);
326 }
327 {
328 int i = 1;
329 int j = 2;
330 auto r = raw_ref<const int>(i);
331 EXPECT_EQ(&*r, &i);
332 r = raw_ref<int>(j);
333 EXPECT_EQ(&*r, &j);
334 }
335 }
336
TEST(RawRef,MoveReassignAfterMove)337 TEST(RawRef, MoveReassignAfterMove) {
338 int i = 1;
339 int j = 1;
340 auto r = raw_ref<int>(i);
341 auto r2 = std::move(r);
342 // Reassign to the moved-from `r` so it can be used again.
343 r = raw_ref<int>(j);
344 EXPECT_EQ(&*r, &j);
345 }
346
TEST(RawRef,CopyConstructUpCast)347 TEST(RawRef, CopyConstructUpCast) {
348 {
349 auto s = SubClass();
350 auto r = raw_ref<SubClass>(s);
351 EXPECT_EQ(&*r, &s);
352 auto r2 = raw_ref<BaseClass>(r);
353 EXPECT_EQ(&*r2, &s);
354 }
355 {
356 auto s = SubClass();
357 auto r = raw_ref<const SubClass>(s);
358 EXPECT_EQ(&*r, &s);
359 auto r2 = raw_ref<const BaseClass>(r);
360 EXPECT_EQ(&*r2, &s);
361 }
362 }
363
TEST(RawRef,MoveConstructUpCast)364 TEST(RawRef, MoveConstructUpCast) {
365 {
366 auto s = SubClass();
367 auto r = raw_ref<SubClass>(s);
368 EXPECT_EQ(&*r, &s);
369 auto r2 = raw_ref<BaseClass>(std::move(r));
370 EXPECT_EQ(&*r2, &s);
371 }
372 {
373 auto s = SubClass();
374 auto r = raw_ref<const SubClass>(s);
375 EXPECT_EQ(&*r, &s);
376 auto r2 = raw_ref<const BaseClass>(std::move(r));
377 EXPECT_EQ(&*r2, &s);
378 }
379 }
380
TEST(RawRef,FromPtr)381 TEST(RawRef, FromPtr) {
382 int i = 42;
383 auto ref = raw_ref<int>::from_ptr(&i);
384 EXPECT_EQ(&i, &*ref);
385 }
386
TEST(RawRef,CopyAssignUpCast)387 TEST(RawRef, CopyAssignUpCast) {
388 {
389 auto s = SubClass();
390 auto r = raw_ref<SubClass>(s);
391 auto t = BaseClass();
392 auto rt = raw_ref<BaseClass>(t);
393 rt = r;
394 EXPECT_EQ(&*rt, &s);
395 }
396 {
397 auto s = SubClass();
398 auto r = raw_ref<const SubClass>(s);
399 auto t = BaseClass();
400 auto rt = raw_ref<const BaseClass>(t);
401 rt = r;
402 EXPECT_EQ(&*rt, &s);
403 }
404 {
405 auto s = SubClass();
406 auto r = raw_ref<SubClass>(s);
407 auto t = BaseClass();
408 auto rt = raw_ref<const BaseClass>(t);
409 rt = r;
410 EXPECT_EQ(&*rt, &s);
411 }
412 }
413
TEST(RawRef,MoveAssignUpCast)414 TEST(RawRef, MoveAssignUpCast) {
415 {
416 auto s = SubClass();
417 auto r = raw_ref<SubClass>(s);
418 auto t = BaseClass();
419 auto rt = raw_ref<BaseClass>(t);
420 rt = std::move(r);
421 EXPECT_EQ(&*rt, &s);
422 }
423 {
424 auto s = SubClass();
425 auto r = raw_ref<const SubClass>(s);
426 auto t = BaseClass();
427 auto rt = raw_ref<const BaseClass>(t);
428 rt = std::move(r);
429 EXPECT_EQ(&*rt, &s);
430 }
431 {
432 auto s = SubClass();
433 auto r = raw_ref<SubClass>(s);
434 auto t = BaseClass();
435 auto rt = raw_ref<const BaseClass>(t);
436 rt = std::move(r);
437 EXPECT_EQ(&*rt, &s);
438 }
439 }
440
TEST(RawRef,Deref)441 TEST(RawRef, Deref) {
442 int i;
443 auto r = raw_ref<int>(i);
444 EXPECT_EQ(&*r, &i);
445 }
446
TEST(RawRef,Arrow)447 TEST(RawRef, Arrow) {
448 int i;
449 auto r = raw_ref<int>(i);
450 EXPECT_EQ(r.operator->(), &i);
451 }
452
TEST(RawRef,Swap)453 TEST(RawRef, Swap) {
454 int i;
455 int j;
456 auto ri = raw_ref<int>(i);
457 auto rj = raw_ref<int>(j);
458 swap(ri, rj);
459 EXPECT_EQ(&*ri, &j);
460 EXPECT_EQ(&*rj, &i);
461 }
462
TEST(RawRef,Equals)463 TEST(RawRef, Equals) {
464 int i = 1;
465 auto r1 = raw_ref<int>(i);
466 auto r2 = raw_ref<int>(i);
467 EXPECT_TRUE(r1 == r1);
468 EXPECT_TRUE(r1 == r2);
469 EXPECT_TRUE(r1 == i);
470 EXPECT_TRUE(i == r1);
471 int j = 1;
472 auto r3 = raw_ref<int>(j);
473 EXPECT_FALSE(r1 == r3);
474 EXPECT_FALSE(r1 == j);
475 EXPECT_FALSE(j == r1);
476 }
477
TEST(RawRef,NotEquals)478 TEST(RawRef, NotEquals) {
479 int i = 1;
480 auto r1 = raw_ref<int>(i);
481 int j = 1;
482 auto r2 = raw_ref<int>(j);
483 EXPECT_TRUE(r1 != r2);
484 EXPECT_TRUE(r1 != j);
485 EXPECT_TRUE(j != r1);
486 EXPECT_FALSE(r1 != r1);
487 EXPECT_FALSE(r2 != j);
488 EXPECT_FALSE(j != r2);
489 }
490
TEST(RawRef,LessThan)491 TEST(RawRef, LessThan) {
492 int i[] = {1, 1};
493 auto r1 = raw_ref<int>(i[0]);
494 auto r2 = raw_ref<int>(i[1]);
495 EXPECT_TRUE(r1 < r2);
496 EXPECT_TRUE(r1 < i[1]);
497 EXPECT_FALSE(i[1] < r1);
498 EXPECT_FALSE(r2 < r1);
499 EXPECT_FALSE(r2 < i[0]);
500 EXPECT_TRUE(i[0] < r2);
501 EXPECT_FALSE(r1 < r1);
502 EXPECT_FALSE(r1 < i[0]);
503 EXPECT_FALSE(i[0] < r1);
504 }
505
TEST(RawRef,GreaterThan)506 TEST(RawRef, GreaterThan) {
507 int i[] = {1, 1};
508 auto r1 = raw_ref<int>(i[0]);
509 auto r2 = raw_ref<int>(i[1]);
510 EXPECT_TRUE(r2 > r1);
511 EXPECT_FALSE(r1 > r2);
512 EXPECT_FALSE(r1 > i[1]);
513 EXPECT_TRUE(i[1] > r1);
514 EXPECT_FALSE(r2 > r2);
515 EXPECT_FALSE(r2 > i[1]);
516 EXPECT_FALSE(i[1] > r2);
517 }
518
TEST(RawRef,LessThanOrEqual)519 TEST(RawRef, LessThanOrEqual) {
520 int i[] = {1, 1};
521 auto r1 = raw_ref<int>(i[0]);
522 auto r2 = raw_ref<int>(i[1]);
523 EXPECT_TRUE(r1 <= r2);
524 EXPECT_TRUE(r1 <= r1);
525 EXPECT_TRUE(r2 <= r2);
526 EXPECT_FALSE(r2 <= r1);
527 EXPECT_TRUE(r1 <= i[1]);
528 EXPECT_TRUE(r1 <= i[0]);
529 EXPECT_TRUE(r2 <= i[1]);
530 EXPECT_FALSE(r2 <= i[0]);
531 EXPECT_FALSE(i[1] <= r1);
532 EXPECT_TRUE(i[0] <= r1);
533 EXPECT_TRUE(i[1] <= r2);
534 EXPECT_TRUE(i[0] <= r2);
535 }
536
TEST(RawRef,GreaterThanOrEqual)537 TEST(RawRef, GreaterThanOrEqual) {
538 int i[] = {1, 1};
539 auto r1 = raw_ref<int>(i[0]);
540 auto r2 = raw_ref<int>(i[1]);
541 EXPECT_TRUE(r2 >= r1);
542 EXPECT_TRUE(r1 >= r1);
543 EXPECT_TRUE(r2 >= r2);
544 EXPECT_FALSE(r1 >= r2);
545 EXPECT_TRUE(r2 >= i[0]);
546 EXPECT_TRUE(r1 >= i[0]);
547 EXPECT_TRUE(r2 >= i[1]);
548 EXPECT_FALSE(r1 >= i[1]);
549 EXPECT_FALSE(i[0] >= r2);
550 EXPECT_TRUE(i[0] >= r1);
551 EXPECT_TRUE(i[1] >= r2);
552 EXPECT_TRUE(i[1] >= r1);
553 }
554
555 // Death Tests: If we're only using the no-op version of `raw_ptr` and
556 // have `!BUILDFLAG(PA_DCHECK_IS_ON)`, the `PA_RAW_PTR_CHECK()`s used in
557 // `raw_ref` evaluate to nothing. Therefore, death tests relying on
558 // these CHECKs firing are disabled in their absence.
559
560 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
561 BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) || BUILDFLAG(PA_DCHECK_IS_ON)
562
TEST(RawRefDeathTest,CopyConstructAfterMove)563 TEST(RawRefDeathTest, CopyConstructAfterMove) {
564 int i = 1;
565 auto r = raw_ref<int>(i);
566 auto r2 = std::move(r);
567 EXPECT_CHECK_DEATH({ [[maybe_unused]] auto r3 = r; });
568 }
569
TEST(RawRefDeathTest,MoveConstructAfterMove)570 TEST(RawRefDeathTest, MoveConstructAfterMove) {
571 int i = 1;
572 auto r = raw_ref<int>(i);
573 auto r2 = std::move(r);
574 EXPECT_CHECK_DEATH({ [[maybe_unused]] auto r3 = std::move(r); });
575 }
576
TEST(RawRefDeathTest,CopyAssignAfterMove)577 TEST(RawRefDeathTest, CopyAssignAfterMove) {
578 int i = 1;
579 auto r = raw_ref<int>(i);
580 auto r2 = std::move(r);
581 EXPECT_CHECK_DEATH({ r2 = r; });
582 }
583
TEST(RawRefDeathTest,MoveAssignAfterMove)584 TEST(RawRefDeathTest, MoveAssignAfterMove) {
585 int i = 1;
586 auto r = raw_ref<int>(i);
587 auto r2 = std::move(r);
588 EXPECT_CHECK_DEATH({ r2 = std::move(r); });
589 }
590
TEST(RawRefDeathTest,CopyConstructAfterMoveUpCast)591 TEST(RawRefDeathTest, CopyConstructAfterMoveUpCast) {
592 auto s = SubClass();
593 auto r = raw_ref<SubClass>(s);
594 auto moved = std::move(r);
595 EXPECT_CHECK_DEATH({ [[maybe_unused]] auto r2 = raw_ref<BaseClass>(r); });
596 }
597
TEST(RawRefDeathTest,MoveConstructAfterMoveUpCast)598 TEST(RawRefDeathTest, MoveConstructAfterMoveUpCast) {
599 auto s = SubClass();
600 auto r = raw_ref<SubClass>(s);
601 auto moved = std::move(r);
602 EXPECT_CHECK_DEATH(
603 { [[maybe_unused]] auto r2 = raw_ref<BaseClass>(std::move(r)); });
604 }
605
TEST(RawRefDeathTest,FromPtrWithNullptr)606 TEST(RawRefDeathTest, FromPtrWithNullptr) {
607 EXPECT_CHECK_DEATH({ raw_ref<int>::from_ptr(nullptr); });
608 }
609
TEST(RawRefDeathTest,CopyAssignAfterMoveUpCast)610 TEST(RawRefDeathTest, CopyAssignAfterMoveUpCast) {
611 auto s = SubClass();
612 auto r = raw_ref<const SubClass>(s);
613 auto t = BaseClass();
614 auto rt = raw_ref<const BaseClass>(t);
615 auto moved = std::move(r);
616 EXPECT_CHECK_DEATH({ rt = r; });
617 }
618
TEST(RawRefDeathTest,MoveAssignAfterMoveUpCast)619 TEST(RawRefDeathTest, MoveAssignAfterMoveUpCast) {
620 auto s = SubClass();
621 auto r = raw_ref<const SubClass>(s);
622 auto t = BaseClass();
623 auto rt = raw_ref<const BaseClass>(t);
624 auto moved = std::move(r);
625 EXPECT_CHECK_DEATH({ rt = std::move(r); });
626 }
627
TEST(RawRefDeathTest,DerefAfterMove)628 TEST(RawRefDeathTest, DerefAfterMove) {
629 int i;
630 auto r = raw_ref<int>(i);
631 auto moved = std::move(r);
632 EXPECT_CHECK_DEATH({ r.operator*(); });
633 }
634
TEST(RawRefDeathTest,ArrowAfterMove)635 TEST(RawRefDeathTest, ArrowAfterMove) {
636 int i;
637 auto r = raw_ref<int>(i);
638 auto moved = std::move(r);
639 EXPECT_CHECK_DEATH({ r.operator->(); });
640 }
641
TEST(RawRefDeathTest,SwapAfterMove)642 TEST(RawRefDeathTest, SwapAfterMove) {
643 {
644 int i;
645 auto ri = raw_ref<int>(i);
646 int j;
647 auto rj = raw_ref<int>(j);
648
649 auto moved = std::move(ri);
650 EXPECT_CHECK_DEATH({ swap(ri, rj); });
651 }
652 {
653 int i;
654 auto ri = raw_ref<int>(i);
655 int j;
656 auto rj = raw_ref<int>(j);
657
658 auto moved = std::move(rj);
659 EXPECT_CHECK_DEATH({ swap(ri, rj); });
660 }
661 }
662
TEST(RawRefDeathTest,EqualsAfterMove)663 TEST(RawRefDeathTest, EqualsAfterMove) {
664 {
665 int i = 1;
666 auto r1 = raw_ref<int>(i);
667 auto r2 = raw_ref<int>(i);
668 auto moved = std::move(r1);
669 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 == r2; });
670 }
671 {
672 int i = 1;
673 auto r1 = raw_ref<int>(i);
674 auto r2 = raw_ref<int>(i);
675 auto moved = std::move(r2);
676 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 == r2; });
677 }
678 {
679 int i = 1;
680 auto r1 = raw_ref<int>(i);
681 auto moved = std::move(r1);
682 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 == r1; });
683 }
684 }
685
TEST(RawRefDeathTest,NotEqualsAfterMove)686 TEST(RawRefDeathTest, NotEqualsAfterMove) {
687 {
688 int i = 1;
689 auto r1 = raw_ref<int>(i);
690 auto r2 = raw_ref<int>(i);
691 auto moved = std::move(r1);
692 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 != r2; });
693 }
694 {
695 int i = 1;
696 auto r1 = raw_ref<int>(i);
697 auto r2 = raw_ref<int>(i);
698 auto moved = std::move(r2);
699 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 != r2; });
700 }
701 {
702 int i = 1;
703 auto r1 = raw_ref<int>(i);
704 auto moved = std::move(r1);
705 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 != r1; });
706 }
707 }
708
TEST(RawRefDeathTest,LessThanAfterMove)709 TEST(RawRefDeathTest, LessThanAfterMove) {
710 {
711 int i = 1;
712 auto r1 = raw_ref<int>(i);
713 auto r2 = raw_ref<int>(i);
714 auto moved = std::move(r1);
715 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 < r2; });
716 }
717 {
718 int i = 1;
719 auto r1 = raw_ref<int>(i);
720 auto r2 = raw_ref<int>(i);
721 auto moved = std::move(r2);
722 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 < r2; });
723 }
724 {
725 int i = 1;
726 auto r1 = raw_ref<int>(i);
727 auto moved = std::move(r1);
728 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 < r1; });
729 }
730 }
731
TEST(RawRefDeathTest,GreaterThanAfterMove)732 TEST(RawRefDeathTest, GreaterThanAfterMove) {
733 {
734 int i = 1;
735 auto r1 = raw_ref<int>(i);
736 auto r2 = raw_ref<int>(i);
737 auto moved = std::move(r1);
738 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 > r2; });
739 }
740 {
741 int i = 1;
742 auto r1 = raw_ref<int>(i);
743 auto r2 = raw_ref<int>(i);
744 auto moved = std::move(r2);
745 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 > r2; });
746 }
747 {
748 int i = 1;
749 auto r1 = raw_ref<int>(i);
750 auto moved = std::move(r1);
751 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 > r1; });
752 }
753 }
754
TEST(RawRefDeathTest,LessThanOrEqualAfterMove)755 TEST(RawRefDeathTest, LessThanOrEqualAfterMove) {
756 {
757 int i = 1;
758 auto r1 = raw_ref<int>(i);
759 auto r2 = raw_ref<int>(i);
760 auto moved = std::move(r1);
761 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 <= r2; });
762 }
763 {
764 int i = 1;
765 auto r1 = raw_ref<int>(i);
766 auto r2 = raw_ref<int>(i);
767 auto moved = std::move(r2);
768 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 <= r2; });
769 }
770 {
771 int i = 1;
772 auto r1 = raw_ref<int>(i);
773 auto moved = std::move(r1);
774 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 <= r1; });
775 }
776 }
777
TEST(RawRefDeathTest,GreaterThanOrEqualAfterMove)778 TEST(RawRefDeathTest, GreaterThanOrEqualAfterMove) {
779 {
780 int i = 1;
781 auto r1 = raw_ref<int>(i);
782 auto r2 = raw_ref<int>(i);
783 auto moved = std::move(r1);
784 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 >= r2; });
785 }
786 {
787 int i = 1;
788 auto r1 = raw_ref<int>(i);
789 auto r2 = raw_ref<int>(i);
790 auto moved = std::move(r2);
791 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 >= r2; });
792 }
793 {
794 int i = 1;
795 auto r1 = raw_ref<int>(i);
796 auto moved = std::move(r1);
797 EXPECT_CHECK_DEATH({ [[maybe_unused]] bool b = r1 >= r1; });
798 }
799 }
800
801 #endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
802 // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) ||
803 // BUILDFLAG(PA_DCHECK_IS_ON)
804
TEST(RawRef,CTAD)805 TEST(RawRef, CTAD) {
806 int i = 1;
807 auto r = raw_ref(i);
808 EXPECT_EQ(&*r, &i);
809 }
810
TEST(RawRefPtr,CTADWithConst)811 TEST(RawRefPtr, CTADWithConst) {
812 std::string str;
813 struct S {
814 const raw_ref<const std::string> r;
815 };
816 // Deduces as `raw_ref<std::string>`, for which the constructor call is valid
817 // making a mutable reference, and then converts to
818 // `raw_ref<const std::string>`.
819 S s1 = {.r = raw_ref(str)};
820 // Deduces as raw_ref<const std::string>, for which the constructor call is
821 // valid from a const ref.
822 S s2 = {.r = raw_ref(static_cast<const std::string&>(str))};
823 EXPECT_EQ(&*s1.r, &str);
824 EXPECT_EQ(&*s2.r, &str);
825 }
826
827 // Shorter name for expected test impl.
828 using RawPtrCountingImpl = base::test::RawPtrCountingImplForTest;
829
830 template <typename T>
831 using CountingRawRef = raw_ref<T, base::RawPtrTraits::kUseCountingImplForTest>;
832
833 // Ensure that the `kUseCountingImplForTest` flag selects the test impl.
834 static_assert(std::is_same_v<CountingRawRef<int>::Impl, RawPtrCountingImpl>);
835
836 template <typename T>
837 using CountingRawRefMayDangle =
838 raw_ref<T,
839 base::RawPtrTraits::kMayDangle |
840 base::RawPtrTraits::kUseCountingImplForTest>;
841
842 // Ensure that the `kUseCountingImplForTest` flag selects the test impl.
843 static_assert(
844 std::is_same_v<CountingRawRefMayDangle<int>::Impl, RawPtrCountingImpl>);
845
TEST(RawRef,StdLess)846 TEST(RawRef, StdLess) {
847 int i[] = {1, 1};
848 {
849 RawPtrCountingImpl::ClearCounters();
850 auto r1 = CountingRawRef<int>(i[0]);
851 auto r2 = CountingRawRef<int>(i[1]);
852 EXPECT_TRUE(std::less<CountingRawRef<int>>()(r1, r2));
853 EXPECT_FALSE(std::less<CountingRawRef<int>>()(r2, r1));
854 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
855 }
856 {
857 RawPtrCountingImpl::ClearCounters();
858 const auto r1 = CountingRawRef<int>(i[0]);
859 const auto r2 = CountingRawRef<int>(i[1]);
860 EXPECT_TRUE(std::less<CountingRawRef<int>>()(r1, r2));
861 EXPECT_FALSE(std::less<CountingRawRef<int>>()(r2, r1));
862 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
863 }
864 {
865 RawPtrCountingImpl::ClearCounters();
866 auto r1 = CountingRawRef<const int>(i[0]);
867 auto r2 = CountingRawRef<const int>(i[1]);
868 EXPECT_TRUE(std::less<CountingRawRef<const int>>()(r1, r2));
869 EXPECT_FALSE(std::less<CountingRawRef<const int>>()(r2, r1));
870 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
871 }
872 {
873 RawPtrCountingImpl::ClearCounters();
874 auto r1 = CountingRawRef<int>(i[0]);
875 auto r2 = CountingRawRef<int>(i[1]);
876 EXPECT_TRUE(std::less<CountingRawRef<int>>()(r1, i[1]));
877 EXPECT_FALSE(std::less<CountingRawRef<int>>()(r2, i[0]));
878 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
879 }
880 {
881 RawPtrCountingImpl::ClearCounters();
882 const auto r1 = CountingRawRef<int>(i[0]);
883 const auto r2 = CountingRawRef<int>(i[1]);
884 EXPECT_TRUE(std::less<CountingRawRef<int>>()(r1, i[1]));
885 EXPECT_FALSE(std::less<CountingRawRef<int>>()(r2, i[0]));
886 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
887 }
888 {
889 RawPtrCountingImpl::ClearCounters();
890 auto r1 = CountingRawRef<const int>(i[0]);
891 auto r2 = CountingRawRef<const int>(i[1]);
892 EXPECT_TRUE(std::less<CountingRawRef<const int>>()(r1, i[1]));
893 EXPECT_FALSE(std::less<CountingRawRef<const int>>()(r2, i[0]));
894 EXPECT_EQ(2, RawPtrCountingImpl::wrapped_ptr_less_cnt);
895 }
896 }
897
898 // Verifies that comparing `raw_ref`s with different underlying Traits
899 // is a valid utterance and primarily uses the `GetForComparison()` methods.
TEST(RawRef,OperatorsUseGetForComparison)900 TEST(RawRef, OperatorsUseGetForComparison) {
901 int x = 123;
902 CountingRawRef<int> ref1(x);
903 CountingRawRefMayDangle<int> ref2(x);
904
905 RawPtrCountingImpl::ClearCounters();
906
907 EXPECT_TRUE(ref1 == ref2);
908 EXPECT_FALSE(ref1 != ref2);
909 // The use of `PA_RAW_PTR_CHECK()`s to catch dangling references means
910 // that we can't actually readily specify whether there are 0
911 // extractions (`CHECK()`s compiled out) or 2 extractions.
912 EXPECT_THAT((CountingRawPtrExpectations{.get_for_comparison_cnt = 4}),
913 CountersMatch());
914
915 EXPECT_FALSE(ref1 < ref2);
916 EXPECT_FALSE(ref1 > ref2);
917 EXPECT_TRUE(ref1 <= ref2);
918 EXPECT_TRUE(ref1 >= ref2);
919 EXPECT_THAT((CountingRawPtrExpectations{
920 .get_for_comparison_cnt = 12,
921 }),
922 CountersMatch());
923 }
924
TEST(RawRef,CrossKindConversion)925 TEST(RawRef, CrossKindConversion) {
926 int x = 123;
927 CountingRawRef<int> ref1(x);
928
929 RawPtrCountingImpl::ClearCounters();
930
931 CountingRawRefMayDangle<int> ref2(ref1);
932 CountingRawRefMayDangle<int> ref3(std::move(ref1)); // Falls back to copy.
933
934 EXPECT_THAT((CountingRawPtrExpectations{.wrap_raw_ptr_cnt = 0,
935 .get_for_dereference_cnt = 0,
936 .get_for_extraction_cnt = 0,
937 .wrap_raw_ptr_for_dup_cnt = 2,
938 .get_for_duplication_cnt = 2}),
939 CountersMatch());
940 }
941
TEST(RawRef,CrossKindAssignment)942 TEST(RawRef, CrossKindAssignment) {
943 int x = 123;
944 CountingRawRef<int> ref1(x);
945
946 CountingRawRefMayDangle<int> ref2(x);
947 CountingRawRefMayDangle<int> ref3(x);
948
949 RawPtrCountingImpl::ClearCounters();
950 ref2 = ref1;
951 ref3 = std::move(ref1); // Falls back to copy.
952
953 EXPECT_THAT((CountingRawPtrExpectations{.wrap_raw_ptr_cnt = 0,
954 .get_for_dereference_cnt = 0,
955 .get_for_extraction_cnt = 0,
956 .wrap_raw_ptr_for_dup_cnt = 2,
957 .get_for_duplication_cnt = 2}),
958 CountersMatch());
959 }
960
961 #if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
962
TEST(AsanBackupRefPtrImpl,RawRefGet)963 TEST(AsanBackupRefPtrImpl, RawRefGet) {
964 base::debug::AsanService::GetInstance()->Initialize();
965
966 if (!base::RawPtrAsanService::GetInstance().IsEnabled()) {
967 base::RawPtrAsanService::GetInstance().Configure(
968 base::EnableDereferenceCheck(true), base::EnableExtractionCheck(true),
969 base::EnableInstantiationCheck(true));
970 } else {
971 ASSERT_TRUE(
972 base::RawPtrAsanService::GetInstance().is_dereference_check_enabled());
973 ASSERT_TRUE(
974 base::RawPtrAsanService::GetInstance().is_extraction_check_enabled());
975 ASSERT_TRUE(base::RawPtrAsanService::GetInstance()
976 .is_instantiation_check_enabled());
977 }
978
979 auto ptr = ::std::make_unique<int>();
980 raw_ref<int> safe_ref(*ptr);
981 ptr.reset();
982
983 // This test is specifically to ensure that raw_ref.get() does not cause a
984 // dereference of the memory referred to by the reference. If there is a
985 // dereference, then this test will crash.
986 [[maybe_unused]] volatile int& ref = safe_ref.get();
987 }
988
TEST(AsanBackupRefPtrImpl,RawRefOperatorStar)989 TEST(AsanBackupRefPtrImpl, RawRefOperatorStar) {
990 base::debug::AsanService::GetInstance()->Initialize();
991
992 if (!base::RawPtrAsanService::GetInstance().IsEnabled()) {
993 base::RawPtrAsanService::GetInstance().Configure(
994 base::EnableDereferenceCheck(true), base::EnableExtractionCheck(true),
995 base::EnableInstantiationCheck(true));
996 } else {
997 ASSERT_TRUE(
998 base::RawPtrAsanService::GetInstance().is_dereference_check_enabled());
999 ASSERT_TRUE(
1000 base::RawPtrAsanService::GetInstance().is_extraction_check_enabled());
1001 ASSERT_TRUE(base::RawPtrAsanService::GetInstance()
1002 .is_instantiation_check_enabled());
1003 }
1004
1005 auto ptr = ::std::make_unique<int>();
1006 raw_ref<int> safe_ref(*ptr);
1007 ptr.reset();
1008
1009 // This test is specifically to ensure that &*raw_ref does not cause a
1010 // dereference of the memory referred to by the reference. If there is a
1011 // dereference, then this test will crash.
1012 [[maybe_unused]] volatile int& ref = *safe_ref;
1013 }
1014
1015 #endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
1016
1017 } // namespace
1018