Skip to content

Commit 56ce752

Browse files
[libc][NFC] Add new is_trivially_destructible check to libc's type_traits
This patch adds new code to check if a given object is trivially destructible. The ifdefs where necessary to implement it in gcc, as it doesn't have the __is_trivially_destructible builtin like clang. In gcc, it's not enough to only call __has_trivial_destructor, see: https://stackoverflow.com/questions/20181702/which-type-traits-cannot-be-implemented-without-compiler-hooks This patch only adds the new check, it will be used in D150211. Reviewed By: michaelrj, sivachandra Differential Revision: https://reviews.llvm.org/D158033
1 parent ada2a45 commit 56ce752

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

libc/src/__support/CPP/type_traits.h

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include "src/__support/macros/attributes.h"
1313

14+
#include <stddef.h> // For size_t.
15+
1416
namespace __llvm_libc {
1517
namespace cpp {
1618

@@ -30,6 +32,8 @@ template <typename T, T v> struct integral_constant {
3032
using true_type = cpp::integral_constant<bool, true>;
3133
using false_type = cpp::integral_constant<bool, false>;
3234

35+
template <bool V> using bool_constant = integral_constant<bool, V>;
36+
3337
template <class T>
3438
struct is_trivially_copyable
3539
: public integral_constant<bool, __is_trivially_copyable(T)> {};
@@ -214,6 +218,131 @@ constexpr bool
214218
details::void_t<decltype(details::convertible_to_helper<T>(
215219
declval<F>()))>> = true;
216220

221+
namespace details {
222+
#if __has_builtin(__is_lvalue_reference) && \
223+
__has_builtin(__is_rvalue_reference) && __has_builtin(__is_reference)
224+
225+
template <typename T>
226+
struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {};
227+
template <typename T>
228+
struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {};
229+
template <typename T> struct is_reference : bool_constant<__is_reference(T)> {};
230+
231+
#else // __has_builtin(__is_lvalue_reference) && etc...
232+
233+
template <typename T> struct is_lvalue_reference : public false_type {};
234+
template <typename T> struct is_lvalue_reference<T &> : public true_type {};
235+
236+
template <typename T> struct is_rvalue_reference : public false_type {};
237+
template <typename T> struct is_rvalue_reference<T &&> : public true_type {};
238+
239+
template <typename T> struct is_reference : public false_type {};
240+
template <typename T> struct is_reference<T &> : public true_type {};
241+
template <typename T> struct is_reference<T &&> : public true_type {};
242+
243+
#endif // __has_builtin(__is_lvalue_reference) && etc...
244+
245+
#if __has_builtin(__remove_all_extents)
246+
template <typename T> using __remove_all_extents_t = __remove_all_extents(T);
247+
#else
248+
template <typename T> struct remove_all_extents {
249+
typedef T type;
250+
};
251+
template <typename T> struct remove_all_extents<T[]> {
252+
typedef typename remove_all_extents<T>::type type;
253+
};
254+
template <typename T, size_t _Np> struct remove_all_extents<T[_Np]> {
255+
typedef typename remove_all_extents<T>::type type;
256+
};
257+
258+
template <typename T>
259+
using __remove_all_extents_t = typename remove_all_extents<T>::type;
260+
#endif // __has_builtin(__remove_all_extents)
261+
262+
#if __has_builtin(__is_function)
263+
264+
template <typename T>
265+
struct is_function : integral_constant<bool, __is_function(T)> {};
266+
267+
#else
268+
269+
template <typename T>
270+
struct is_function
271+
: public integral_constant<bool, !(is_reference<T>::value ||
272+
is_const<const T>::value)> {};
273+
274+
#endif // __has_builtin(__is_function)
275+
276+
#if __has_builtin(__is_destructible)
277+
278+
template <typename T>
279+
struct is_destructible : bool_constant<__is_destructible(T)> {};
280+
281+
#else // __has_builtin(__is_destructible)
282+
283+
// if it's a reference, return true
284+
// if it's a function, return false
285+
// if it's void, return false
286+
// if it's an array of unknown bound, return false
287+
// Otherwise, return "declval<T&>().~T()" is well-formed
288+
// where T is remove_all_extents<T>::type
289+
290+
template <typename> struct __is_destructible_apply {
291+
typedef int type;
292+
};
293+
294+
template <typename T> struct __is_destructor_wellformed {
295+
template <typename T1>
296+
static true_type __test(
297+
typename __is_destructible_apply<decltype(declval<T1 &>().~T1())>::type);
298+
299+
template <typename T1> static false_type __test(...);
300+
301+
static const bool value = decltype(__test<T>(12))::value;
302+
};
303+
304+
template <typename T, bool> struct __destructible_imp;
305+
306+
template <typename T>
307+
struct __destructible_imp<T, false>
308+
: public integral_constant<
309+
bool, __is_destructor_wellformed<__remove_all_extents_t<T>>::value> {
310+
};
311+
312+
template <typename T> struct __destructible_imp<T, true> : public true_type {};
313+
314+
template <typename T, bool> struct __destructible_false;
315+
template <typename T>
316+
struct __destructible_false<T, false>
317+
: public __destructible_imp<T, is_reference<T>::value> {};
318+
template <typename T>
319+
struct __destructible_false<T, true> : public false_type {};
320+
321+
template <typename T>
322+
struct is_destructible : public __destructible_false<T, is_function<T>::value> {
323+
};
324+
template <typename T> struct is_destructible<T[]> : public false_type {};
325+
template <> struct is_destructible<void> : public false_type {};
326+
327+
#endif // __has_builtin(__is_destructible)
328+
} // namespace details
329+
330+
#if __has_builtin(__is_trivially_destructible)
331+
332+
template <typename T>
333+
struct is_trivially_destructible
334+
: public integral_constant<bool, __is_trivially_destructible(T)> {};
335+
336+
#elif __has_builtin(__has_trivial_destructor)
337+
338+
template <typename T>
339+
struct is_trivially_destructible
340+
: public integral_constant<
341+
bool, __llvm_libc::cpp::details::is_destructible<T>::value
342+
&&__has_trivial_destructor(T)> {};
343+
344+
#endif // __has_builtin(__is_trivially_destructible)
345+
217346
} // namespace cpp
218347
} // namespace __llvm_libc
219348

0 commit comments

Comments
 (0)