• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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