1 // Copyright 2022 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_ 6 #define BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_ 7 8 #include "build/build_config.h" 9 10 #include <type_traits> 11 12 // Various opaque system types that should still be usable with the base 13 // callback system. Please keep sorted. 14 struct ANativeWindow; 15 struct DBusMessage; 16 struct HWND__; 17 struct VkBuffer_T; 18 struct VkDeviceMemory_T; 19 struct VkImage_T; 20 struct VkSemaphore_T; 21 struct VmaAllocation_T; 22 struct WGPUAdapterImpl; 23 struct fpdf_action_t__; 24 struct fpdf_annotation_t__; 25 struct fpdf_attachment_t__; 26 struct fpdf_bookmark_t__; 27 struct fpdf_document_t__; 28 struct fpdf_form_handle_t__; 29 struct fpdf_page_t__; 30 struct fpdf_structelement_t__; 31 struct hb_set_t; 32 struct wl_gpu; 33 struct wl_shm; 34 struct wl_surface; 35 36 namespace base::internal { 37 38 // True if `T` is completely defined or false otherwise. Note that this always 39 // returns false for function types. 40 template <typename T, typename = void> 41 inline constexpr bool IsCompleteTypeV = false; 42 43 template <typename T> 44 inline constexpr bool IsCompleteTypeV<T, std::void_t<decltype(sizeof(T))>> = 45 true; 46 47 // Determining whether a type can be used with `Unretained()` requires that `T` 48 // be completely defined. Some system types have an intentionally opaque and 49 // incomplete representation, but should still be usable with `Unretained()`. 50 // The specializations here provide intentional escape hatches for those 51 // instances. 52 template <typename T> 53 inline constexpr bool IsIncompleteTypeSafeForUnretained = false; 54 55 // void* is occasionally used with callbacks; in the future, this may be more 56 // restricted/limited, but allow it for now. 57 template <> 58 inline constexpr bool IsIncompleteTypeSafeForUnretained<void> = true; 59 60 // Functions have static lifetime and are always safe for use with 61 // `Unretained()`. 62 template <typename R, typename... Args> 63 inline constexpr bool IsIncompleteTypeSafeForUnretained<R(Args...)> = true; 64 65 // Various opaque system types that should still be usable with the base 66 // callback system. Please keep sorted. 67 template <> 68 inline constexpr bool IsIncompleteTypeSafeForUnretained<ANativeWindow> = true; 69 template <> 70 inline constexpr bool IsIncompleteTypeSafeForUnretained<DBusMessage> = true; 71 template <> 72 inline constexpr bool IsIncompleteTypeSafeForUnretained<HWND__> = true; 73 template <> 74 inline constexpr bool IsIncompleteTypeSafeForUnretained<VkBuffer_T> = true; 75 template <> 76 inline constexpr bool IsIncompleteTypeSafeForUnretained<VkDeviceMemory_T> = 77 true; 78 template <> 79 inline constexpr bool IsIncompleteTypeSafeForUnretained<VkImage_T> = true; 80 template <> 81 inline constexpr bool IsIncompleteTypeSafeForUnretained<VkSemaphore_T> = true; 82 template <> 83 inline constexpr bool IsIncompleteTypeSafeForUnretained<VmaAllocation_T> = true; 84 template <> 85 inline constexpr bool IsIncompleteTypeSafeForUnretained<WGPUAdapterImpl> = true; 86 template <> 87 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_action_t__> = true; 88 template <> 89 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_annotation_t__> = 90 true; 91 template <> 92 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_attachment_t__> = 93 true; 94 template <> 95 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_bookmark_t__> = 96 true; 97 template <> 98 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_document_t__> = 99 true; 100 template <> 101 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_form_handle_t__> = 102 true; 103 template <> 104 inline constexpr bool IsIncompleteTypeSafeForUnretained<fpdf_page_t__> = true; 105 template <> 106 inline constexpr bool 107 IsIncompleteTypeSafeForUnretained<fpdf_structelement_t__> = true; 108 template <> 109 inline constexpr bool IsIncompleteTypeSafeForUnretained<hb_set_t> = true; 110 template <> 111 inline constexpr bool IsIncompleteTypeSafeForUnretained<wl_gpu> = true; 112 template <> 113 inline constexpr bool IsIncompleteTypeSafeForUnretained<wl_shm> = true; 114 template <> 115 inline constexpr bool IsIncompleteTypeSafeForUnretained<wl_surface> = true; 116 117 template <typename T, typename SFINAE = void> 118 struct TypeSupportsUnretained { 119 // Incrementally enforce the requirement to be completely defined. For now, 120 // limit the failures to: 121 // 122 // - non-test code 123 // - non-official code (because these builds don't run as part of the default CQ 124 // and are slower due to PGO and LTO) 125 // - Android, Linux or Windows 126 // 127 // to make this easier to land without potentially breaking the tree. 128 // 129 // TODO(https://crbug.com/1392872): Enable this on all platforms, then in 130 // official builds, and then in non-test code as well. 131 #if !defined(UNIT_TEST) && !defined(OFFICIAL_BUILD) 132 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || \ 133 defined(FORCE_UNRETAINED_COMPLETENESS_CHECKS_FOR_TESTS) 134 static_assert(IsCompleteTypeV<T> || 135 IsIncompleteTypeSafeForUnretained<std::remove_cv_t<T>>, 136 "T must be fully defined."); 137 #endif 138 #endif // !defined(UNIT_TEST) && !defined(OFFICIAL_BUILD) 139 140 static constexpr inline bool kValue = true; 141 }; 142 143 // Matches against the marker tag created by the `DISALLOW_UNRETAINED()` macro 144 // in //base/functional/disallow_unretained.h. 145 template <typename T> 146 struct TypeSupportsUnretained<T, typename T::DisallowBaseUnretainedMarker> { 147 static constexpr inline bool kValue = false; 148 }; 149 150 // True if `T` is annotated with `DISALLOW_UNRETAINED()` and false otherwise. 151 template <typename T> 152 static inline constexpr bool TypeSupportsUnretainedV = 153 TypeSupportsUnretained<T>::kValue; 154 155 } // namespace base::internal 156 157 #endif // BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_ 158