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