Skip to content

Commit 9cc2122

Browse files
authored
[Clang][libc++] Implement __is_nothrow_convertible and use it in libc++ (#80436)
GCC 13 has implemented this builtin.
1 parent 1156bbc commit 9cc2122

File tree

5 files changed

+37
-4
lines changed

5 files changed

+37
-4
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,7 @@ The following type trait primitives are supported by Clang. Those traits marked
15691569
* ``__is_const`` (C++, Embarcadero)
15701570
* ``__is_constructible`` (C++, MSVC 2013)
15711571
* ``__is_convertible`` (C++, Embarcadero)
1572+
* ``__is_nothrow_convertible`` (C++, GNU)
15721573
* ``__is_convertible_to`` (Microsoft):
15731574
Synonym for ``__is_convertible``.
15741575
* ``__is_destructible`` (C++, MSVC 2013)

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
567567
// Embarcadero Binary Type Traits
568568
TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
569569
TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
570+
TYPE_TRAIT_2(__is_nothrow_convertible, IsNothrowConvertible, KEYCXX)
570571
ARRAY_TYPE_TRAIT(__array_rank, ArrayRank, KEYCXX)
571572
ARRAY_TYPE_TRAIT(__array_extent, ArrayExtent, KEYCXX)
572573
// Name for GCC 6 compatibility.

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5779,7 +5779,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
57795779
return Self.Context.typesAreCompatible(Lhs, Rhs);
57805780
}
57815781
case BTT_IsConvertible:
5782-
case BTT_IsConvertibleTo: {
5782+
case BTT_IsConvertibleTo:
5783+
case BTT_IsNothrowConvertible: {
57835784
// C++0x [meta.rel]p4:
57845785
// Given the following function prototype:
57855786
//
@@ -5840,7 +5841,13 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
58405841
return false;
58415842

58425843
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
5843-
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
5844+
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
5845+
return false;
5846+
5847+
if (BTT != BTT_IsNothrowConvertible)
5848+
return true;
5849+
5850+
return Self.canThrow(Result.get()) == CT_Cannot;
58445851
}
58455852

58465853
case BTT_IsAssignable:

clang/test/SemaCXX/type-traits.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,15 +2118,15 @@ struct IntWrapper
21182118
{
21192119
int value;
21202120
IntWrapper(int _value) : value(_value) {}
2121-
operator int() const {
2121+
operator int() const noexcept {
21222122
return value;
21232123
}
21242124
};
21252125

21262126
struct FloatWrapper
21272127
{
21282128
float value;
2129-
FloatWrapper(float _value) : value(_value) {}
2129+
FloatWrapper(float _value) noexcept : value(_value) {}
21302130
FloatWrapper(const IntWrapper& obj)
21312131
: value(static_cast<float>(obj.value)) {}
21322132
operator float() const {
@@ -2149,6 +2149,18 @@ void is_convertible()
21492149
int t08[T(__is_convertible(float, FloatWrapper))];
21502150
}
21512151

2152+
void is_nothrow_convertible()
2153+
{
2154+
int t01[T(__is_nothrow_convertible(IntWrapper, IntWrapper))];
2155+
int t02[T(__is_nothrow_convertible(IntWrapper, const IntWrapper))];
2156+
int t03[T(__is_nothrow_convertible(IntWrapper, int))];
2157+
int t04[F(__is_nothrow_convertible(int, IntWrapper))];
2158+
int t05[F(__is_nothrow_convertible(IntWrapper, FloatWrapper))];
2159+
int t06[F(__is_nothrow_convertible(FloatWrapper, IntWrapper))];
2160+
int t07[F(__is_nothrow_convertible(FloatWrapper, float))];
2161+
int t08[T(__is_nothrow_convertible(float, FloatWrapper))];
2162+
}
2163+
21522164
struct FromInt { FromInt(int); };
21532165
struct ToInt { operator int(); };
21542166
typedef void Function();

libcxx/include/__type_traits/is_nothrow_convertible.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2626

2727
#if _LIBCPP_STD_VER >= 20
2828

29+
# if __has_builtin(__is_nothrow_convertible)
30+
31+
template <class _Tp, class _Up>
32+
struct is_nothrow_convertible : bool_constant<__is_nothrow_convertible(_Tp, _Up)> {};
33+
34+
template <class _Tp, class _Up>
35+
inline constexpr bool is_nothrow_convertible_v = __is_nothrow_convertible(_Tp, _Up);
36+
37+
# else // __has_builtin(__is_nothrow_convertible)
38+
2939
template <typename _Tp>
3040
void __test_noexcept(_Tp) noexcept;
3141

@@ -43,6 +53,8 @@ struct is_nothrow_convertible
4353
template <typename _Fm, typename _To>
4454
inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value;
4555

56+
# endif // __has_builtin(__is_nothrow_convertible)
57+
4658
#endif // _LIBCPP_STD_VER >= 20
4759

4860
_LIBCPP_END_NAMESPACE_STD

0 commit comments

Comments
 (0)