xref: /aosp_15_r20/external/abseil-cpp/absl/base/internal/nullability_impl.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
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