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 #ifndef ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ 16 #define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ 17 18 #include <memory> 19 #include <type_traits> 20 21 #include "absl/base/attributes.h" 22 #include "absl/meta/type_traits.h" 23 24 namespace absl { 25 26 namespace nullability_internal { 27 28 // `IsNullabilityCompatible` checks whether its first argument is a class 29 // explicitly tagged as supporting nullability annotations. The tag is the type 30 // declaration `absl_nullability_compatible`. 31 template <typename, typename = void> 32 struct IsNullabilityCompatible : std::false_type {}; 33 34 template <typename T> 35 struct IsNullabilityCompatible< 36 T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type { 37 }; 38 39 template <typename T> 40 constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value; 41 42 template <typename T> 43 constexpr bool IsSupportedType<T*> = true; 44 45 template <typename T, typename U> 46 constexpr bool IsSupportedType<T U::*> = true; 47 48 template <typename T, typename... Deleter> 49 constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true; 50 51 template <typename T> 52 constexpr bool IsSupportedType<std::shared_ptr<T>> = true; 53 54 template <typename T> 55 struct EnableNullable { 56 static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, 57 "Template argument must be a raw or supported smart pointer " 58 "type. See absl/base/nullability.h."); 59 using type = T; 60 }; 61 62 template <typename T> 63 struct EnableNonnull { 64 static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, 65 "Template argument must be a raw or supported smart pointer " 66 "type. See absl/base/nullability.h."); 67 using type = T; 68 }; 69 70 template <typename T> 71 struct EnableNullabilityUnknown { 72 static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, 73 "Template argument must be a raw or supported smart pointer " 74 "type. See absl/base/nullability.h."); 75 using type = T; 76 }; 77 78 // Note: we do not apply Clang nullability attributes (e.g. _Nullable). These 79 // only support raw pointers, and conditionally enabling them only for raw 80 // pointers inhibits template arg deduction. Ideally, they would support all 81 // pointer-like types. 82 template <typename T, typename = typename EnableNullable<T>::type> 83 using NullableImpl 84 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) 85 [[clang::annotate("Nullable")]] 86 #endif 87 = T; 88 89 template <typename T, typename = typename EnableNonnull<T>::type> 90 using NonnullImpl 91 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) 92 [[clang::annotate("Nonnull")]] 93 #endif 94 = T; 95 96 template <typename T, typename = typename EnableNullabilityUnknown<T>::type> 97 using NullabilityUnknownImpl 98 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) 99 [[clang::annotate("Nullability_Unspecified")]] 100 #endif 101 = T; 102 103 } // namespace nullability_internal 104 } // namespace absl 105 106 #endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ 107