Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][libc++] Implement __is_nothrow_convertible and use it in libc++ #80436

Merged
merged 1 commit into from
Feb 2, 2024

Conversation

philnik777
Copy link
Contributor

GCC 13 has implemented this builtin.

@philnik777 philnik777 requested a review from a team as a code owner February 2, 2024 14:17
@llvmbot llvmbot added clang Clang issues not falling into any other category libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 2, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 2, 2024

@llvm/pr-subscribers-libcxx

@llvm/pr-subscribers-clang

Author: Nikolas Klauser (philnik777)

Changes

GCC 13 has implemented this builtin.


Full diff: https://github.com/llvm/llvm-project/pull/80436.diff

5 Files Affected:

  • (modified) clang/docs/LanguageExtensions.rst (+1)
  • (modified) clang/include/clang/Basic/TokenKinds.def (+1)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+9-2)
  • (modified) clang/test/SemaCXX/type-traits.cpp (+14-2)
  • (modified) libcxx/include/__type_traits/is_nothrow_convertible.h (+12)
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..2f9b4f953c140 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

Copy link

github-actions bot commented Feb 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Front end changes looks good.
It would be nice to add a release note on the clang side

@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to move __is_nothrow_convertible / __is_convertible / __is_same above the Embarcadero comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a bunch more type traits that aren't listed correctly anymore, so IMO an NFC patch that updates them all would be better.

@philnik777 philnik777 merged commit 9cc2122 into llvm:main Feb 2, 2024
9 of 10 checks passed
@philnik777 philnik777 deleted the is_nothrow_convertible branch February 2, 2024 18:16
@sdkrystian
Copy link
Member

@philnik777
Copy link
Contributor Author

@sdkrystian #80476

agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants