nullability_test.cc (6905B)
1 // Copyright 2023 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/base/nullability.h" 16 17 #include <cassert> 18 #include <memory> 19 #include <type_traits> 20 #include <utility> 21 22 #include "gtest/gtest.h" 23 24 namespace { 25 namespace macro_annotations { 26 void funcWithNonnullArg(int* absl_nonnull /*arg*/) {} 27 template <typename T> 28 void funcWithDeducedNonnullArg(T* absl_nonnull /*arg*/) {} 29 30 TEST(NonnullTest, NonnullArgument) { 31 int var = 0; 32 funcWithNonnullArg(&var); 33 funcWithDeducedNonnullArg(&var); 34 } 35 36 int* absl_nonnull funcWithNonnullReturn() { 37 static int var = 0; 38 return &var; 39 } 40 41 TEST(NonnullTest, NonnullReturn) { 42 auto var = funcWithNonnullReturn(); 43 (void)var; 44 } 45 46 TEST(PassThroughTest, PassesThroughRawPointerToInt) { 47 EXPECT_TRUE((std::is_same<int* absl_nonnull, int*>::value)); 48 EXPECT_TRUE((std::is_same<int* absl_nullable, int*>::value)); 49 EXPECT_TRUE((std::is_same<int* absl_nullability_unknown, int*>::value)); 50 } 51 52 TEST(PassThroughTest, PassesThroughRawPointerToVoid) { 53 EXPECT_TRUE((std::is_same<void* absl_nonnull, void*>::value)); 54 EXPECT_TRUE((std::is_same<void* absl_nullable, void*>::value)); 55 EXPECT_TRUE((std::is_same<void* absl_nullability_unknown, void*>::value)); 56 } 57 58 TEST(PassThroughTest, PassesThroughUniquePointerToInt) { 59 using T = std::unique_ptr<int>; 60 EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value)); 61 EXPECT_TRUE((std::is_same<absl_nullable T, T>::value)); 62 EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value)); 63 } 64 65 TEST(PassThroughTest, PassesThroughSharedPointerToInt) { 66 using T = std::shared_ptr<int>; 67 EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value)); 68 EXPECT_TRUE((std::is_same<absl_nullable T, T>::value)); 69 EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value)); 70 } 71 72 TEST(PassThroughTest, PassesThroughSharedPointerToVoid) { 73 using T = std::shared_ptr<void>; 74 EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value)); 75 EXPECT_TRUE((std::is_same<absl_nullable T, T>::value)); 76 EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value)); 77 } 78 79 TEST(PassThroughTest, PassesThroughPointerToMemberObject) { 80 using T = decltype(&std::pair<int, int>::first); 81 EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value)); 82 EXPECT_TRUE((std::is_same<absl_nullable T, T>::value)); 83 EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value)); 84 } 85 86 TEST(PassThroughTest, PassesThroughPointerToMemberFunction) { 87 using T = decltype(&std::unique_ptr<int>::reset); 88 EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value)); 89 EXPECT_TRUE((std::is_same<absl_nullable T, T>::value)); 90 EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value)); 91 } 92 } // namespace macro_annotations 93 94 using ::absl::Nonnull; 95 using ::absl::NullabilityUnknown; 96 using ::absl::Nullable; 97 namespace type_alias_annotations { 98 99 void funcWithNonnullArg(Nonnull<int*> /*arg*/) {} 100 template <typename T> 101 void funcWithDeducedNonnullArg(Nonnull<T*> /*arg*/) {} 102 103 TEST(NonnullTest, NonnullArgument) { 104 int var = 0; 105 funcWithNonnullArg(&var); 106 funcWithDeducedNonnullArg(&var); 107 } 108 109 Nonnull<int*> funcWithNonnullReturn() { 110 static int var = 0; 111 return &var; 112 } 113 114 TEST(NonnullTest, NonnullReturn) { 115 auto var = funcWithNonnullReturn(); 116 (void)var; 117 } 118 119 TEST(PassThroughTest, PassesThroughRawPointerToInt) { 120 EXPECT_TRUE((std::is_same<Nonnull<int*>, int*>::value)); 121 EXPECT_TRUE((std::is_same<Nullable<int*>, int*>::value)); 122 EXPECT_TRUE((std::is_same<NullabilityUnknown<int*>, int*>::value)); 123 } 124 125 TEST(PassThroughTest, PassesThroughRawPointerToVoid) { 126 EXPECT_TRUE((std::is_same<Nonnull<void*>, void*>::value)); 127 EXPECT_TRUE((std::is_same<Nullable<void*>, void*>::value)); 128 EXPECT_TRUE((std::is_same<NullabilityUnknown<void*>, void*>::value)); 129 } 130 131 TEST(PassThroughTest, PassesThroughUniquePointerToInt) { 132 using T = std::unique_ptr<int>; 133 EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value)); 134 EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); 135 EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); 136 } 137 138 TEST(PassThroughTest, PassesThroughSharedPointerToInt) { 139 using T = std::shared_ptr<int>; 140 EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value)); 141 EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); 142 EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); 143 } 144 145 TEST(PassThroughTest, PassesThroughSharedPointerToVoid) { 146 using T = std::shared_ptr<void>; 147 EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value)); 148 EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); 149 EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); 150 } 151 152 TEST(PassThroughTest, PassesThroughPointerToMemberObject) { 153 using T = decltype(&std::pair<int, int>::first); 154 EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value)); 155 EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); 156 EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); 157 } 158 159 TEST(PassThroughTest, PassesThroughPointerToMemberFunction) { 160 using T = decltype(&std::unique_ptr<int>::reset); 161 EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value)); 162 EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); 163 EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); 164 } 165 166 } // namespace type_alias_annotations 167 } // namespace 168 169 // Nullable ADL lookup test 170 namespace util { 171 // Helper for NullableAdlTest. Returns true, denoting that argument-dependent 172 // lookup found this implementation of DidAdlWin. Must be in namespace 173 // util itself, not a nested anonymous namespace. 174 template <typename T> 175 bool DidAdlWin(T*) { 176 return true; 177 } 178 179 // Because this type is defined in namespace util, an unqualified call to 180 // DidAdlWin with a pointer to MakeAdlWin will find the above implementation. 181 struct MakeAdlWin {}; 182 } // namespace util 183 184 namespace { 185 // Returns false, denoting that ADL did not inspect namespace util. If it 186 // had, the better match (T*) above would have won out over the (...) here. 187 bool DidAdlWin(...) { return false; } 188 189 TEST(NullableAdlTest, NullableAddsNothingToArgumentDependentLookup) { 190 // Treatment: util::Nullable<int*> contributes nothing to ADL because 191 // int* itself doesn't. 192 EXPECT_FALSE(DidAdlWin((int*)nullptr)); 193 EXPECT_FALSE(DidAdlWin((Nullable<int*>)nullptr)); 194 195 // Control: Argument-dependent lookup does find the implementation in 196 // namespace util when the underlying pointee type resides there. 197 EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr)); 198 EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr)); 199 } 200 } // namespace