[libcxx-commits] [libcxx] [clang] [Clang][libc++] Implement __is_nothrow_convertible and use it in libc++ (PR #80436)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Feb 2 10:13:25 PST 2024
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/80436
>From d210ffcbc1c60c222bd456851372f4835cc12127 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 2 Feb 2024 15:12:15 +0100
Subject: [PATCH] [Clang][libc++] Implement __is_nothrow_convertible and use it
in libc++
---
clang/docs/LanguageExtensions.rst | 1 +
clang/include/clang/Basic/TokenKinds.def | 1 +
clang/lib/Sema/SemaExprCXX.cpp | 11 +++++++++--
clang/test/SemaCXX/type-traits.cpp | 16 ++++++++++++++--
.../__type_traits/is_nothrow_convertible.h | 12 ++++++++++++
5 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index c1420079f7511..e91156837290f 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1569,6 +1569,7 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_const`` (C++, Embarcadero)
* ``__is_constructible`` (C++, MSVC 2013)
* ``__is_convertible`` (C++, Embarcadero)
+* ``__is_nothrow_convertible`` (C++, GNU)
* ``__is_convertible_to`` (Microsoft):
Synonym for ``__is_convertible``.
* ``__is_destructible`` (C++, MSVC 2013)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 9117e4376c371..23817cde7a935 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -567,6 +567,7 @@ TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
// Embarcadero Binary Type Traits
TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
+TYPE_TRAIT_2(__is_nothrow_convertible, IsNothrowConvertible, KEYCXX)
ARRAY_TYPE_TRAIT(__array_rank, ArrayRank, KEYCXX)
ARRAY_TYPE_TRAIT(__array_extent, ArrayExtent, KEYCXX)
// Name for GCC 6 compatibility.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 3a32754e5376e..246d2313e089f 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5779,7 +5779,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return Self.Context.typesAreCompatible(Lhs, Rhs);
}
case BTT_IsConvertible:
- case BTT_IsConvertibleTo: {
+ case BTT_IsConvertibleTo:
+ case BTT_IsNothrowConvertible: {
// C++0x [meta.rel]p4:
// Given the following function prototype:
//
@@ -5840,7 +5841,13 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return false;
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
- return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
+ if (Result.isInvalid() || SFINAE.hasErrorOccurred())
+ return false;
+
+ if (BTT != BTT_IsNothrowConvertible)
+ return true;
+
+ return Self.canThrow(Result.get()) == CT_Cannot;
}
case BTT_IsAssignable:
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index c5d196a2590f8..5659594577111 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -2118,7 +2118,7 @@ struct IntWrapper
{
int value;
IntWrapper(int _value) : value(_value) {}
- operator int() const {
+ operator int() const noexcept {
return value;
}
};
@@ -2126,7 +2126,7 @@ struct IntWrapper
struct FloatWrapper
{
float value;
- FloatWrapper(float _value) : value(_value) {}
+ FloatWrapper(float _value) noexcept : value(_value) {}
FloatWrapper(const IntWrapper& obj)
: value(static_cast<float>(obj.value)) {}
operator float() const {
@@ -2149,6 +2149,18 @@ void is_convertible()
int t08[T(__is_convertible(float, FloatWrapper))];
}
+void is_nothrow_convertible()
+{
+ int t01[T(__is_nothrow_convertible(IntWrapper, IntWrapper))];
+ int t02[T(__is_nothrow_convertible(IntWrapper, const IntWrapper))];
+ int t03[T(__is_nothrow_convertible(IntWrapper, int))];
+ int t04[F(__is_nothrow_convertible(int, IntWrapper))];
+ int t05[F(__is_nothrow_convertible(IntWrapper, FloatWrapper))];
+ int t06[F(__is_nothrow_convertible(FloatWrapper, IntWrapper))];
+ int t07[F(__is_nothrow_convertible(FloatWrapper, float))];
+ int t08[T(__is_nothrow_convertible(float, FloatWrapper))];
+}
+
struct FromInt { FromInt(int); };
struct ToInt { operator int(); };
typedef void Function();
diff --git a/libcxx/include/__type_traits/is_nothrow_convertible.h b/libcxx/include/__type_traits/is_nothrow_convertible.h
index eda7a49d7224c..bfc5a94cbadec 100644
--- a/libcxx/include/__type_traits/is_nothrow_convertible.h
+++ b/libcxx/include/__type_traits/is_nothrow_convertible.h
@@ -26,6 +26,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
+# if __has_builtin(__is_nothrow_convertible)
+
+template <class _Tp, class _Up>
+struct is_nothrow_convertible : bool_constant<__is_nothrow_convertible(_Tp, _Up)> {};
+
+template <class _Tp, class _Up>
+inline constexpr bool is_nothrow_convertible_v = __is_nothrow_convertible(_Tp, _Up);
+
+# else // __has_builtin(__is_nothrow_convertible)
+
template <typename _Tp>
void __test_noexcept(_Tp) noexcept;
@@ -43,6 +53,8 @@ struct is_nothrow_convertible
template <typename _Fm, typename _To>
inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value;
+# endif // __has_builtin(__is_nothrow_convertible)
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
More information about the libcxx-commits
mailing list