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