10b57cec5SDimitry Andric //===-- sanitizer_type_traits.h ---------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Implements a subset of C++ type traits. This is so we can avoid depending
100b57cec5SDimitry Andric // on system C++ headers.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric #ifndef SANITIZER_TYPE_TRAITS_H
140b57cec5SDimitry Andric #define SANITIZER_TYPE_TRAITS_H
150b57cec5SDimitry Andric 
16349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h"
17349cc55cSDimitry Andric 
180b57cec5SDimitry Andric namespace __sanitizer {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric struct true_type {
210b57cec5SDimitry Andric   static const bool value = true;
220b57cec5SDimitry Andric };
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric struct false_type {
250b57cec5SDimitry Andric   static const bool value = false;
260b57cec5SDimitry Andric };
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric // is_same<T, U>
290b57cec5SDimitry Andric //
300b57cec5SDimitry Andric // Type trait to compare if types are the same.
310b57cec5SDimitry Andric // E.g.
320b57cec5SDimitry Andric //
330b57cec5SDimitry Andric // ```
340b57cec5SDimitry Andric // is_same<int,int>::value - True
350b57cec5SDimitry Andric // is_same<int,char>::value - False
360b57cec5SDimitry Andric // ```
370b57cec5SDimitry Andric template <typename T, typename U>
380b57cec5SDimitry Andric struct is_same : public false_type {};
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric template <typename T>
410b57cec5SDimitry Andric struct is_same<T, T> : public true_type {};
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric // conditional<B, T, F>
440b57cec5SDimitry Andric //
450b57cec5SDimitry Andric // Defines type as T if B is true or as F otherwise.
460b57cec5SDimitry Andric // E.g. the following is true
470b57cec5SDimitry Andric //
480b57cec5SDimitry Andric // ```
490b57cec5SDimitry Andric // is_same<int, conditional<true, int, double>::type>::value
500b57cec5SDimitry Andric // is_same<double, conditional<false, int, double>::type>::value
510b57cec5SDimitry Andric // ```
520b57cec5SDimitry Andric template <bool B, class T, class F>
530b57cec5SDimitry Andric struct conditional {
540b57cec5SDimitry Andric   using type = T;
550b57cec5SDimitry Andric };
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric template <class T, class F>
580b57cec5SDimitry Andric struct conditional<false, T, F> {
590b57cec5SDimitry Andric   using type = F;
600b57cec5SDimitry Andric };
610b57cec5SDimitry Andric 
62349cc55cSDimitry Andric template <class T>
63349cc55cSDimitry Andric struct remove_reference {
64349cc55cSDimitry Andric   using type = T;
65349cc55cSDimitry Andric };
66349cc55cSDimitry Andric template <class T>
67349cc55cSDimitry Andric struct remove_reference<T&> {
68349cc55cSDimitry Andric   using type = T;
69349cc55cSDimitry Andric };
70349cc55cSDimitry Andric template <class T>
71349cc55cSDimitry Andric struct remove_reference<T&&> {
72349cc55cSDimitry Andric   using type = T;
73349cc55cSDimitry Andric };
74349cc55cSDimitry Andric 
75349cc55cSDimitry Andric template <class T>
76349cc55cSDimitry Andric WARN_UNUSED_RESULT inline typename remove_reference<T>::type&& move(T&& t) {
77349cc55cSDimitry Andric   return static_cast<typename remove_reference<T>::type&&>(t);
78349cc55cSDimitry Andric }
79349cc55cSDimitry Andric 
80349cc55cSDimitry Andric template <class T>
81349cc55cSDimitry Andric WARN_UNUSED_RESULT inline constexpr T&& forward(
82349cc55cSDimitry Andric     typename remove_reference<T>::type& t) {
83349cc55cSDimitry Andric   return static_cast<T&&>(t);
84349cc55cSDimitry Andric }
85349cc55cSDimitry Andric 
86349cc55cSDimitry Andric template <class T>
87349cc55cSDimitry Andric WARN_UNUSED_RESULT inline constexpr T&& forward(
88349cc55cSDimitry Andric     typename remove_reference<T>::type&& t) {
89349cc55cSDimitry Andric   return static_cast<T&&>(t);
90349cc55cSDimitry Andric }
91349cc55cSDimitry Andric 
92349cc55cSDimitry Andric template <class T, T v>
93349cc55cSDimitry Andric struct integral_constant {
94349cc55cSDimitry Andric   static constexpr const T value = v;
95349cc55cSDimitry Andric   typedef T value_type;
96349cc55cSDimitry Andric   typedef integral_constant type;
97349cc55cSDimitry Andric   constexpr operator value_type() const { return value; }
98349cc55cSDimitry Andric   constexpr value_type operator()() const { return value; }
99349cc55cSDimitry Andric };
100349cc55cSDimitry Andric 
101349cc55cSDimitry Andric #ifndef __has_builtin
102349cc55cSDimitry Andric #  define __has_builtin(x) 0
103349cc55cSDimitry Andric #endif
104349cc55cSDimitry Andric 
105349cc55cSDimitry Andric #if __has_builtin(__is_trivially_destructible)
106349cc55cSDimitry Andric 
107349cc55cSDimitry Andric template <class T>
108349cc55cSDimitry Andric struct is_trivially_destructible
109349cc55cSDimitry Andric     : public integral_constant<bool, __is_trivially_destructible(T)> {};
110349cc55cSDimitry Andric 
111349cc55cSDimitry Andric #elif __has_builtin(__has_trivial_destructor)
112349cc55cSDimitry Andric 
113349cc55cSDimitry Andric template <class T>
114349cc55cSDimitry Andric struct is_trivially_destructible
115349cc55cSDimitry Andric     : public integral_constant<bool, __has_trivial_destructor(T)> {};
116349cc55cSDimitry Andric 
117349cc55cSDimitry Andric #else
118349cc55cSDimitry Andric 
119349cc55cSDimitry Andric template <class T>
120349cc55cSDimitry Andric struct is_trivially_destructible
121349cc55cSDimitry Andric     : public integral_constant<bool, /* less efficient fallback */ false> {};
122349cc55cSDimitry Andric 
123349cc55cSDimitry Andric #endif
124349cc55cSDimitry Andric 
125349cc55cSDimitry Andric #if __has_builtin(__is_trivially_copyable)
126349cc55cSDimitry Andric 
127349cc55cSDimitry Andric template <class T>
128349cc55cSDimitry Andric struct is_trivially_copyable
129349cc55cSDimitry Andric     : public integral_constant<bool, __is_trivially_copyable(T)> {};
130349cc55cSDimitry Andric 
131349cc55cSDimitry Andric #else
132349cc55cSDimitry Andric 
133349cc55cSDimitry Andric template <class T>
134349cc55cSDimitry Andric struct is_trivially_copyable
135349cc55cSDimitry Andric     : public integral_constant<bool, /* less efficient fallback */ false> {};
136349cc55cSDimitry Andric 
137349cc55cSDimitry Andric #endif
138349cc55cSDimitry Andric 
1390b57cec5SDimitry Andric }  // namespace __sanitizer
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric #endif
142