diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp index abe03a7d2d0ea..e76ccb240dcfc 100644 --- a/clang-tools-extra/test/clang-doc/templates.cpp +++ b/clang-tools-extra/test/clang-doc/templates.cpp @@ -7,6 +7,11 @@ // RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=md // RUN: cat %t/docs/GlobalNamespace/index.md | FileCheck %s --check-prefix=MD +// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=html +// RUN: cat %t/docs/json/GlobalNamespace/index.json | FileCheck %s --check-prefix=JSON +// RUN: cat %t/docs/html/GlobalNamespace/_ZTV5tuple.html | FileCheck %s --check-prefix=HTML-STRUCT +// RUN: cat %t/docs/html/GlobalNamespace/index.html | FileCheck %s --check-prefix=HTML + // YAML: --- // YAML-NEXT: USR: '{{([0-9A-F]{40})}}' // YAML-NEXT: ChildRecords: @@ -44,6 +49,39 @@ void ParamPackFunction(T... args); // MD: ### ParamPackFunction // MD: *void ParamPackFunction(T... args)* +// JSON: "Name": "ParamPackFunction", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "args", +// JSON-NEXT: "Type": "T..." +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "class... T" +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: }, + +// HTML:
+// HTML-NEXT:
+// HTML-NEXT:
template <class... T>
+// HTML-NEXT:
void ParamPackFunction (T... args)
+// COM: FIXME: Omit defined line if not defined, or emit declaration line. +// HTML-NEXT:

Defined at line of file

+// HTML-NEXT:
+// HTML-NEXT:
+ template void function(T x) {} @@ -70,6 +108,42 @@ void function(T x) {} // MD: *void function(T x)* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 23]]* +// JSON: "Name": "function", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "x", +// JSON-NEXT: "Type": "T" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: { +// JSON-NEXT: "Param": "typename T" +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "int U = 1" +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: } + +// HTML:
+// HTML-NEXT:
+// HTML-NEXT:
template <typename T, int U = 1>
+// HTML-NEXT:
void function (T x)
+// HTML-NEXT:

Defined at line [[# @LINE - 56]] of file {{.*}}templates.cpp

+// HTML-NEXT:
+// HTML-NEXT:
+ + template <> void function(bool x) {} @@ -98,12 +172,66 @@ void function(bool x) {} // MD: *void function(bool x)* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 26]]* +// JSON: "Name": "function", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "x", +// JSON-NEXT: "Type": "bool" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Specialization": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: { +// JSON-NEXT: "Param": "bool" +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "0" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "SpecializationOf": "{{([0-9A-F]{40})}}" +// JSON-NEXT: } +// JSON-NEXT: }, + +// HTML:
+// HTML-NEXT:
+// HTML-NEXT:
template <>
+// HTML-NEXT:
void function<bool, 0> (bool x)
+// HTML-NEXT:

Defined at line [[# @LINE - 62]] of file {{.*}}templates.cpp

+// HTML-NEXT:
+// HTML-NEXT:
+ /// A Tuple type /// /// Does Tuple things. template struct tuple {}; +// HTML-STRUCT:
+// HTML-STRUCT-NEXT:
template <typename... Tys>
+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:

struct tuple

+// HTML-STRUCT-NEXT:

Defined at line [[# @LINE - 6]] of file {{.*}}templates.cpp

+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:

A Tuple type

+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:

Does Tuple things.

+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:
+// HTML-STRUCT-NEXT:
+ /// A function with a tuple parameter /// /// \param t The input to func_with_tuple_param @@ -154,3 +282,36 @@ tuple func_with_tuple_param(tuple t) { return t; // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 44]]* // MD: A function with a tuple parameter // MD: **t** The input to func_with_tuple_param + +// JSON: "Name": "func_with_tuple_param", +// COM: FIXME: Add type info to parameters +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "t", +// JSON-NEXT: "Type": "tuple" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": false, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "tuple", +// JSON-NEXT: "QualName": "tuple", +// JSON-NEXT: "USR": "{{([0-9A-F]{40})}}" +// JSON-NEXT: }, + +// HTML:
+// HTML-NEXT:
+// HTML-NEXT:
tuple func_with_tuple_param (tuple t)
+// HTML-NEXT:
+// HTML-NEXT:
+// HTML-NEXT:

A function with a tuple parameter

+// HTML-NEXT:
+// HTML-NEXT:

Parameters

+// HTML-NEXT:
+// HTML-NEXT: t The input to func_with_tuple_param +// HTML-NEXT:
+// HTML-NEXT:
+// HTML-NEXT:

Defined at line [[# @LINE - 77]] of file {{.*}}templates.cpp

+// HTML-NEXT:
+// HTML-NEXT:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/meta/type_traits.h b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/meta/type_traits.h new file mode 100644 index 0000000000000..06ce61dbcc1e7 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/meta/type_traits.h @@ -0,0 +1,46 @@ +#include + +namespace absl { + +template +struct conjunction : std::true_type {}; + +template +struct conjunction + : std::conditional, T>::type {}; + +template +struct conjunction : T {}; + +template +struct disjunction : std::false_type {}; + +template +struct disjunction + : std::conditional>::type {}; + +template +struct disjunction : T {}; + +template +struct negation : std::integral_constant {}; + +template +using enable_if_t = typename std::enable_if::type; + + +template +using conditional_t = typename std::conditional::type; + +template +using remove_cv_t = typename std::remove_cv::type; + +template +using remove_reference_t = typename std::remove_reference::type; + +template +using decay_t = typename std::decay::type; + +using std::in_place; +using std::in_place_t; +} // namespace absl diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/status.h b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/status.h new file mode 100644 index 0000000000000..fd0910e81436a --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/status.h @@ -0,0 +1,69 @@ +namespace absl { +struct SourceLocation { + static constexpr SourceLocation current(); + static constexpr SourceLocation + DoNotInvokeDirectlyNoSeriouslyDont(int line, const char *file_name); +}; +} // namespace absl +namespace absl { +enum class StatusCode : int { + kOk, + kCancelled, + kUnknown, + kInvalidArgument, + kDeadlineExceeded, + kNotFound, + kAlreadyExists, + kPermissionDenied, + kResourceExhausted, + kFailedPrecondition, + kAborted, + kOutOfRange, + kUnimplemented, + kInternal, + kUnavailable, + kDataLoss, + kUnauthenticated, +}; +} // namespace absl + +namespace absl { +enum class StatusToStringMode : int { + kWithNoExtraData = 0, + kWithPayload = 1 << 0, + kWithSourceLocation = 1 << 1, + kWithEverything = ~kWithNoExtraData, + kDefault = kWithPayload, +}; +class Status { +public: + Status(); + Status(const Status &base_status, absl::SourceLocation loc); + Status(Status &&base_status, absl::SourceLocation loc); + ~Status() {} + + Status(const Status &); + Status &operator=(const Status &x); + + Status(Status &&) noexcept; + Status &operator=(Status &&); + + friend bool operator==(const Status &, const Status &); + friend bool operator!=(const Status &, const Status &); + + bool ok() const { return true; } + void CheckSuccess() const; + void IgnoreError() const; + int error_code() const; + absl::Status ToCanonical() const; + void Update(const Status &new_status); + void Update(Status &&new_status); +}; + +bool operator==(const Status &lhs, const Status &rhs); +bool operator!=(const Status &lhs, const Status &rhs); + +Status OkStatus(); +Status InvalidArgumentError(const char *); + +} // namespace absl diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/statusor.h b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/statusor.h new file mode 100644 index 0000000000000..0151dda0cb97d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/absl/status/statusor.h @@ -0,0 +1,346 @@ +#include "status.h" +#include +#include + +namespace absl { + +template struct StatusOr; + +namespace internal_statusor { + +template +struct HasConversionOperatorToStatusOr : std::false_type {}; + +template +void test(char (*)[sizeof(std::declval().operator absl::StatusOr())]); + +template +struct HasConversionOperatorToStatusOr(0))> + : std::true_type {}; + +template +using IsConstructibleOrConvertibleFromStatusOr = + absl::disjunction &>, + std::is_constructible &>, + std::is_constructible &&>, + std::is_constructible &&>, + std::is_convertible &, T>, + std::is_convertible &, T>, + std::is_convertible &&, T>, + std::is_convertible &&, T>>; + +template +using IsConstructibleOrConvertibleOrAssignableFromStatusOr = + absl::disjunction, + std::is_assignable &>, + std::is_assignable &>, + std::is_assignable &&>, + std::is_assignable &&>>; + +template +struct IsDirectInitializationAmbiguous + : public absl::conditional_t< + std::is_same>, + U>::value, + std::false_type, + IsDirectInitializationAmbiguous< + T, absl::remove_cv_t>>> {}; + +template +struct IsDirectInitializationAmbiguous> + : public IsConstructibleOrConvertibleFromStatusOr {}; + +template +using IsDirectInitializationValid = absl::disjunction< + // Short circuits if T is basically U. + std::is_same>>, + absl::negation, + absl::remove_cv_t>>, + std::is_same>>, + std::is_same>>, + IsDirectInitializationAmbiguous>>>; + +template +struct IsForwardingAssignmentAmbiguous + : public absl::conditional_t< + std::is_same>, + U>::value, + std::false_type, + IsForwardingAssignmentAmbiguous< + T, absl::remove_cv_t>>> {}; + +template +struct IsForwardingAssignmentAmbiguous> + : public IsConstructibleOrConvertibleOrAssignableFromStatusOr {}; + +template +using IsForwardingAssignmentValid = absl::disjunction< + // Short circuits if T is basically U. + std::is_same>>, + absl::negation, + absl::remove_cv_t>>, + std::is_same>>, + std::is_same>>, + IsForwardingAssignmentAmbiguous>>>; + +template +using IsForwardingAssignmentValid = absl::disjunction< + // Short circuits if T is basically U. + std::is_same>>, + absl::negation, + absl::remove_cv_t>>, + std::is_same>>, + std::is_same>>, + IsForwardingAssignmentAmbiguous>>>; + +template struct OperatorBase { + const T &value() const &; + T &value() &; + const T &&value() const &&; + T &&value() &&; + + const T &operator*() const &; + T &operator*() &; + const T &&operator*() const &&; + T &&operator*() &&; + + // To test that analyses are okay if there is a use of operator* + // within this base class. + const T *operator->() const { return __builtin_addressof(**this); } + T *operator->() { return __builtin_addressof(**this); } +}; + +} // namespace internal_statusor + +template +struct StatusOr : private internal_statusor::OperatorBase { + explicit StatusOr(); + + StatusOr(const StatusOr &) = default; + StatusOr &operator=(const StatusOr &) = default; + + StatusOr(StatusOr &&) = default; + StatusOr &operator=(StatusOr &&) = default; + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, + std::is_convertible, + absl::negation< + internal_statusor::IsConstructibleOrConvertibleFromStatusOr< + T, U>>>::value, + int> = 0> + StatusOr(const StatusOr &); + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, + absl::negation>, + absl::negation< + internal_statusor::IsConstructibleOrConvertibleFromStatusOr< + T, U>>>::value, + int> = 0> + explicit StatusOr(const StatusOr &); + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, std::is_convertible, + absl::negation< + internal_statusor::IsConstructibleOrConvertibleFromStatusOr< + T, U>>>::value, + int> = 0> + StatusOr(StatusOr &&); + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, + absl::negation>, + absl::negation< + internal_statusor::IsConstructibleOrConvertibleFromStatusOr< + T, U>>>::value, + int> = 0> + explicit StatusOr(StatusOr &&); + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, + std::is_assignable, + absl::negation< + internal_statusor:: + IsConstructibleOrConvertibleOrAssignableFromStatusOr< + T, U>>>::value, + int> = 0> + StatusOr &operator=(const StatusOr &); + + template < + typename U, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, std::is_assignable, + absl::negation< + internal_statusor:: + IsConstructibleOrConvertibleOrAssignableFromStatusOr< + T, U>>>::value, + int> = 0> + StatusOr &operator=(StatusOr &&); + + template < + typename U = absl::Status, + absl::enable_if_t< + absl::conjunction< + std::is_convertible, + std::is_constructible, + absl::negation, absl::StatusOr>>, + absl::negation, T>>, + absl::negation, absl::in_place_t>>, + absl::negation>>::value, + int> = 0> + StatusOr(U &&); + + template < + typename U = absl::Status, + absl::enable_if_t< + absl::conjunction< + absl::negation>, + std::is_constructible, + absl::negation, absl::StatusOr>>, + absl::negation, T>>, + absl::negation, absl::in_place_t>>, + absl::negation>>::value, + int> = 0> + explicit StatusOr(U &&); + + template < + typename U = absl::Status, + absl::enable_if_t< + absl::conjunction< + std::is_convertible, + std::is_constructible, + absl::negation, absl::StatusOr>>, + absl::negation, T>>, + absl::negation, absl::in_place_t>>, + absl::negation>>::value, + int> = 0> + StatusOr &operator=(U &&); + + template < + typename U = T, + typename = typename std::enable_if, std::is_assignable, + absl::disjunction< + std::is_same>, T>, + absl::conjunction< + absl::negation>, + absl::negation< + internal_statusor::HasConversionOperatorToStatusOr< + T, U &&>>>>, + internal_statusor::IsForwardingAssignmentValid>::value>:: + type> + StatusOr &operator=(U &&); + + template explicit StatusOr(absl::in_place_t, Args &&...); + + template + explicit StatusOr(absl::in_place_t, std::initializer_list, Args &&...); + + template < + typename U = T, + absl::enable_if_t< + absl::conjunction< + internal_statusor::IsDirectInitializationValid, + std::is_constructible, std::is_convertible, + absl::disjunction< + std::is_same>, + T>, + absl::conjunction< + absl::negation>, + absl::negation< + internal_statusor::HasConversionOperatorToStatusOr< + T, U &&>>>>>::value, + int> = 0> + StatusOr(U &&); + + template < + typename U = T, + absl::enable_if_t< + absl::conjunction< + internal_statusor::IsDirectInitializationValid, + absl::disjunction< + std::is_same>, + T>, + absl::conjunction< + absl::negation>, + absl::negation< + internal_statusor::HasConversionOperatorToStatusOr< + T, U &&>>>>, + std::is_constructible, + absl::negation>>::value, + int> = 0> + explicit StatusOr(U &&); + + bool ok() const; + + const Status &status() const & { return status_; } + Status status() &&; + + using StatusOr::OperatorBase::value; + + const T &ValueOrDie() const &; + T &ValueOrDie() &; + const T &&ValueOrDie() const &&; + T &&ValueOrDie() &&; + + using StatusOr::OperatorBase::operator*; + using StatusOr::OperatorBase::operator->; + + template T value_or(U &&default_value) const &; + template T value_or(U &&default_value) &&; + + template T &emplace(Args &&...args); + + template < + typename U, typename... Args, + absl::enable_if_t &, + Args &&...>::value, + int> = 0> + T &emplace(std::initializer_list ilist, Args &&...args); + +private: + absl::Status status_; +}; + +template +bool operator==(const StatusOr &lhs, const StatusOr &rhs); + +template +bool operator!=(const StatusOr &lhs, const StatusOr &rhs); + +} // namespace absl diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/cstddef.h b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/cstddef.h new file mode 100644 index 0000000000000..633260f24f99b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/cstddef.h @@ -0,0 +1,10 @@ +namespace std { + +typedef decltype(sizeof(char)) size_t; + +using nullptr_t = decltype(nullptr); + +} // namespace std + +typedef decltype(sizeof(char)) size_t; +typedef decltype(sizeof(char*)) ptrdiff_t; diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/initializer_list b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/initializer_list new file mode 100644 index 0000000000000..886a54fe217f4 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/initializer_list @@ -0,0 +1,11 @@ + +namespace std { + +template +class initializer_list { + public: + const T *a, *b; + initializer_list() noexcept; +}; + +} // namespace std \ No newline at end of file diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/type_traits b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/type_traits new file mode 100644 index 0000000000000..c97ae9c2d14bd --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/Inputs/type_traits @@ -0,0 +1,427 @@ +#include "cstddef.h" + +namespace std { + +template +struct integral_constant { + static constexpr T value = V; +}; + +using true_type = integral_constant; +using false_type = integral_constant; + +template< class T > struct remove_reference {typedef T type;}; +template< class T > struct remove_reference {typedef T type;}; +template< class T > struct remove_reference {typedef T type;}; + +template + using remove_reference_t = typename remove_reference::type; + +template +struct remove_extent { + typedef T type; +}; + +template +struct remove_extent { + typedef T type; +}; + +template +struct remove_extent { + typedef T type; +}; + +template +struct is_array : false_type {}; + +template +struct is_array : true_type {}; + +template +struct is_array : true_type {}; + +template +struct is_function : false_type {}; + +template +struct is_function : true_type {}; + +namespace detail { + +template +struct type_identity { + using type = T; +}; // or use type_identity (since C++20) + +template +auto try_add_pointer(int) -> type_identity::type*>; +template +auto try_add_pointer(...) -> type_identity; + +} // namespace detail + +template +struct add_pointer : decltype(detail::try_add_pointer(0)) {}; + +template +struct conditional { + typedef T type; +}; + +template +struct conditional { + typedef F type; +}; + +template +struct remove_cv { + typedef T type; +}; +template +struct remove_cv { + typedef T type; +}; +template +struct remove_cv { + typedef T type; +}; +template +struct remove_cv { + typedef T type; +}; + +template +using remove_cv_t = typename remove_cv::type; + +template +struct decay { + private: + typedef typename remove_reference::type U; + + public: + typedef typename conditional< + is_array::value, typename remove_extent::type*, + typename conditional::value, typename add_pointer::type, + typename remove_cv::type>::type>::type type; +}; + +template +struct enable_if {}; + +template +struct enable_if { + typedef T type; +}; + +template +using enable_if_t = typename enable_if::type; + +template +struct is_same : false_type {}; + +template +struct is_same : true_type {}; + +template +struct is_void : is_same::type> {}; + +namespace detail { + +template +auto try_add_lvalue_reference(int) -> type_identity; +template +auto try_add_lvalue_reference(...) -> type_identity; + +template +auto try_add_rvalue_reference(int) -> type_identity; +template +auto try_add_rvalue_reference(...) -> type_identity; + +} // namespace detail + +template +struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference(0)) { +}; + +template +struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) { +}; + +template +typename add_rvalue_reference::type declval() noexcept; + +namespace detail { + +template +auto test_returnable(int) + -> decltype(void(static_cast(nullptr)), true_type{}); +template +auto test_returnable(...) -> false_type; + +template +auto test_implicitly_convertible(int) + -> decltype(void(declval()(declval())), true_type{}); +template +auto test_implicitly_convertible(...) -> false_type; + +} // namespace detail + +template +struct is_convertible + : integral_constant(0))::value && + decltype(detail::test_implicitly_convertible( + 0))::value) || + (is_void::value && is_void::value)> {}; + +template +inline constexpr bool is_convertible_v = is_convertible::value; + +template +using void_t = void; + +template +struct is_constructible_ : false_type {}; + +template +struct is_constructible_()...))>, T, Args...> + : true_type {}; + +template +using is_constructible = is_constructible_, T, Args...>; + +template +inline constexpr bool is_constructible_v = is_constructible::value; + +template +struct __uncvref { + typedef typename remove_cv::type>::type type; +}; + +template +using __uncvref_t = typename __uncvref<_Tp>::type; + +template +using _BoolConstant = integral_constant; + +template +using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>; + +template +using _IsNotSame = _BoolConstant; + +template +struct _MetaBase; +template <> +struct _MetaBase { + template + using _SelectImpl = _Tp; + template