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// This is a "No Compile Test" suite. 6// http://dev.chromium.org/developers/testing/no-compile-tests 7 8#include <memory> 9#include <utility> 10 11#include "base/functional/bind.h" 12#include "base/functional/callback.h" 13#include "partition_alloc/pointers/raw_ptr.h" 14#include "partition_alloc/partition_alloc_buildflags.h" 15 16namespace { 17 18// Using distinct enum types causes distinct `raw_ptr` template instantiations, 19// so we get assertion failures below where we expect. 20enum TypeA {}; 21enum TypeB {}; 22 23void UnknownTraits() { 24 constexpr auto InvalidRawPtrTrait = static_cast<base::RawPtrTraits>(-1); 25 raw_ptr<TypeA, InvalidRawPtrTrait> ptr_a; // expected-error@*:* {{Unknown raw_ptr trait(s)}} 26 raw_ptr<TypeB, DisableDanglingPtrDetection | InvalidRawPtrTrait> ptr_b; // expected-error@*:* {{Unknown raw_ptr trait(s)}} 27} 28 29void DifferentTypeAssignment() { 30 struct Unrelated {}; 31 struct Producer {} p; 32 struct DerivedProducer : public Producer {} dp; 33 raw_ptr<Producer> ptr_p = &p; 34 raw_ptr<DerivedProducer> ptr_dp1 = &dp; 35 36 // Conversion 37 raw_ptr<DerivedProducer> ptr_dp2 = ptr_p; // expected-error {{no viable conversion from 'raw_ptr<Producer>' to 'raw_ptr<DerivedProducer>'}} 38 raw_ptr<DerivedProducer> ptr_dp3 = 39 static_cast<raw_ptr<DerivedProducer>>(ptr_p); // expected-error {{no matching conversion for static_cast from 'raw_ptr<Producer>' to 'raw_ptr<DerivedProducer>'}} 40 raw_ptr<DerivedProducer> ptr_dp4 = &p; // expected-error {{no viable conversion from 'struct Producer *' to 'raw_ptr<DerivedProducer>'}} 41 raw_ptr<Unrelated> ptr_u1 = &dp; // expected-error {{no viable conversion from 'struct DerivedProducer *' to 'raw_ptr<Unrelated>'}} 42 43 // Reference binding 44 raw_ptr<DerivedProducer>& ptr_dp5 = ptr_p; // expected-error {{non-const lvalue reference to type 'raw_ptr<DerivedProducer>' cannot bind to a value of unrelated type 'raw_ptr<Producer>'}} 45 raw_ptr<DerivedProducer>& ptr_dp6 = 46 static_cast<raw_ptr<DerivedProducer>&>(ptr_p); // expected-error {{non-const lvalue reference to type 'raw_ptr<DerivedProducer>' cannot bind to a value of unrelated type 'raw_ptr<Producer>'}} 47 48 // Casting 49 auto* ptr_u2 = static_cast<Unrelated*>(ptr_dp1); // expected-error@*:* {{static_cast from 'DerivedProducer *' to 'Unrelated *', which are not related by inheritance, is not allowed}} 50} 51 52void DereferenceVoidPtr() { 53 constexpr char kFoo[] = "42"; 54 raw_ptr<const void> ptr = kFoo; 55 *ptr; // expected-error {{indirection requires pointer operand ('raw_ptr<const void>' invalid)}} 56} 57 58void FunctionPointerType() { 59 raw_ptr<void(int)> ptr; // expected-error@*:* {{raw_ptr<T> doesn't work with this kind of pointee type T}} 60} 61 62void Dangling() { 63 [[maybe_unused]] raw_ptr<int> ptr = std::make_unique<int>(2).get(); // expected-error {{object backing the pointer will be destroyed at the end of the full-expression}} 64} 65 66void BindRawPtrParam() { 67 // `raw_ptr` is not intended to be used as a function param type, so trying to 68 // bind to a function with a `raw_ptr<T>` param should error out. 69 raw_ptr<int> ptr = new int(3); 70 base::BindOnce([](raw_ptr<int> ptr) {}, ptr); // expected-error@*:* {{base::Bind() target functor has a parameter of type raw_ptr<T>.}} 71} 72 73void PointerArithmetic() { 74 using PtrCanDoArithmetic = 75 raw_ptr<int, base::RawPtrTraits::kAllowPtrArithmetic>; 76 77 PtrCanDoArithmetic ptr1 = new int(3); 78 struct {} s; 79 ptr1 += s; // expected-error@*:* {{no viable overloaded '+='}} 80 ptr1 -= s; // expected-error@*:* {{no viable overloaded '-='}} 81 PtrCanDoArithmetic ptr2 = ptr1 + s; // expected-error@*:* {{no viable overloaded '+='}} 82 ptr2 = ptr1 - s; // expected-error@*:* {{no viable overloaded '-='}} 83 84#if !BUILDFLAG(HAS_64_BIT_POINTERS) 85 ptr1 += uint64_t{2}; // expected-error@*:* {{no viable overloaded '+='}} 86 ptr1 -= uint64_t{2}; // expected-error@*:* {{no viable overloaded '-='}} 87 ptr2 = ptr1 + uint64_t{2}; // expected-error@*:* {{no viable overloaded '+='}} 88 ptr2 = ptr1 - uint64_t{2}; // expected-error@*:* {{no viable overloaded '-='}} 89#endif // !BUILDFLAG(HAS_64_BIT_POINTERS) 90} 91 92#if BUILDFLAG(ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK) 93void PointerArithmeticDisabled() { 94 raw_ptr<TypeA> ptr_a1 = new TypeA(); 95 ptr_a1++; // expected-error@*:* {{cannot increment raw_ptr unless AllowPtrArithmetic trait is present.}} 96 ptr_a1--; // expected-error@*:* {{cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.}} 97 ++ptr_a1; // expected-error@*:* {{cannot increment raw_ptr unless AllowPtrArithmetic trait is present.}} 98 --ptr_a1; // expected-error@*:* {{cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.}} 99 raw_ptr<TypeA> ptr_a2 = ptr_a1 + 1; // expected-error@*:* {{cannot increment raw_ptr unless AllowPtrArithmetic trait is present.}} 100 ptr_a2 = ptr_a1 - 1; // expected-error@*:* {{cannot decrement raw_ptr unless AllowPtrArithmetic trait is present.}} 101 raw_ptr<TypeB> ptr_b1 = new TypeB(); 102 raw_ptr<TypeB> ptr_b2 = 1 + ptr_b1; // expected-error@*:* {{cannot increment raw_ptr unless AllowPtrArithmetic trait is present.}} 103} 104 105void Indexing() { 106 raw_ptr<int> ptr = new int(3); 107 [[maybe_unused]] int val = ptr[1]; // expected-error@*:* {{cannot index raw_ptr unless AllowPtrArithmetic trait is present.}} 108} 109#endif 110 111using DanglingPtrA = raw_ptr<TypeA, base::RawPtrTraits::kMayDangle>; 112using DanglingPtrB = raw_ptr<TypeB, base::RawPtrTraits::kMayDangle>; 113 114void CrossKindConversionFromMayDangle() { 115 // Conversions may add the `kMayDangle` trait, but not remove it. 116 DanglingPtrA ptr_a1 = new TypeA(); 117 DanglingPtrB ptr_b1 = new TypeB(); 118 raw_ptr<TypeA> ptr_a2 = ptr_a1; // expected-error {{no viable conversion from 'raw_ptr<[...], base::RawPtrTraits::kMayDangle aka 1>' to 'raw_ptr<[...], (default) RawPtrTraits::kEmpty aka 0>'}} 119 raw_ptr<TypeA> ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle>::Traits | RawPtrTraits::kMayDangle)'}} 120 raw_ptr<TypeA> ptr_a4 = std::move(ptr_a1); // expected-error {{no viable conversion from '__libcpp_remove_reference_t<raw_ptr<TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle> &>' (aka 'base::raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle>') to 'raw_ptr<TypeA>'}} 121 raw_ptr<TypeB> ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, partition_alloc::internal::RawPtrTraits::kMayDangle>::Traits | RawPtrTraits::kMayDangle)'}} 122} 123 124void CrossKindConversionFromDummy() { 125 // Only the `kMayDangle` trait can change in an implicit conversion. 126 raw_ptr<TypeA, base::RawPtrTraits::kDummyForTest> ptr_a1 = new TypeA(); 127 raw_ptr<TypeB, base::RawPtrTraits::kDummyForTest> ptr_b1 = new TypeB(); 128 DanglingPtrA ptr_a2 = ptr_a1; // expected-error {{no viable conversion from 'raw_ptr<[...], base::RawPtrTraits::kDummyForTest aka 2048>' to 'raw_ptr<[...], base::RawPtrTraits::kMayDangle aka 1>'}} 129 DanglingPtrA ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest>::Traits | RawPtrTraits::kMayDangle)'}} 130 DanglingPtrA ptr_a4 = std::move(ptr_a1); // expected-error {{no viable conversion from '__libcpp_remove_reference_t<raw_ptr<TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest> &>' (aka 'base::raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest>') to 'DanglingPtrA' (aka 'raw_ptr<TypeA, base::RawPtrTraits::kMayDangle>')}} 131 DanglingPtrB ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, partition_alloc::internal::RawPtrTraits::kDummyForTest>::Traits | RawPtrTraits::kMayDangle)'}} 132} 133 134} // namespace 135