-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[libc++] Fix std::make_exception_ptr interaction with ObjC #135386
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-libcxx Author: None (itrofimow) ChangesClang treats throwing/catching ObjC types differently from C++ types, and omitting the Full diff: https://github.com/llvm/llvm-project/pull/135386.diff 1 Files Affected:
diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h
index dac5b00b57fe3..167aa4d9b367a 100644
--- a/libcxx/include/__exception/exception_ptr.h
+++ b/libcxx/include/__exception/exception_ptr.h
@@ -92,7 +92,8 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
# if _LIBCPP_HAS_EXCEPTIONS
-# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
+ // Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior
+# if !defined(__OBJC__) && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
using _Ep2 = __decay_t<_Ep>;
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
|
It's not great to condition only on If you switch to the As a refinement to my suggestion on the issue, I think |
Are you still planning to update this patch? |
Hi! Yes, sorry, just got back to office I was thinking, wouldn't just |
You mean without the OBJC ifdef? I think that would be OK. But IMO it's not actually an improvement, because the condition is no longer clearly connected with the actual reason for the existence of the alternate codepath. |
I don't think CI failure has to do with these changes, @jyknight could you please have a look? |
using _Ep2 = __decay_t<_Ep>; | ||
|
||
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); | ||
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should really be _LIBCPP_STD_VER >= 17
. Also, why did this change from C++11 to C++17?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is about language-level features rather than libc++ features: c++11 or higher was required for the lambda to compile; c++17 or higher is now required for if constexpr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both are available as extensions in older versions. No need to put this behind a guard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks fine.
But is there any way to add a test-case for this? (It's not clear to me there is since it depends on the non-llvm-project objc runtime, but it'd be great if there was.)
There's some prior art in |
I'll see what I can do about the test for this. |
@itrofimow @jyknight Thanks for the PR. I updated the PR with a test and I refactored the code as a drive-by so it would be easier to understand -- after adding yet another |
We might be able to make it into LLVM 20.1.9 if we end up having such a release. |
// | ||
// [1]: | ||
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html | ||
if constexpr (is_pointer<_Ep>::value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, if there was a way to query Clang whether _Ep
is an Objective-C pointer type, that would match exactly the condition they use in
if (ThrowType->isObjCObjectPointerType()) { |
throw
or a normal C++ throw
. Do you think that is something we should be able to query directly from Clang?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had suggested std::is_pointer_v<_Ep> && std::is_convertible_v<_Ep, id>
earlier if we want to avoid C++ pointers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that id
is not a known identifier in C++, so we have to guard this with an #ifdef
checking whether we're compiling in Objective-C mode, and I think we had ODR issues with doing that?
Naively adding the check right now, I get:
exception_ptr.h:141:71: error: use of undeclared identifier 'id'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right; it needs an ifdef. That shouldn't cause issues -- I think -- because the template arg cannot be an ObjC type and thus convertible to id if it's not an objc file. The reason not to do it was just itrofimow's feeling it was too complicated. It may well be, I don't have strong feelings here. So probably best to just leave it the way you have it now.
Gentle ping @itrofimow @jyknight WDYT about the current PR? It's passing CI and I'd like to get it merged whenever possible! |
Hi @ldionne! Thank you for taking care of this PR, I've got completely consumed by work and absolutely failed to clean up my own mess in time. Personally, I don't think narrowing the "could it be ObjC type" condition any further via compiler intrinsics is worth it: for me (as someone who just reads libcxx source code from time to time, not a maintainer) the mere presence of ObjC-related code/comments in libcxx seems confusing enough, and I'd say that Nice refactoring by you, and I'm happy to see CI finally working. LGTM |
Clang treats throwing/catching ObjC types differently from C++ types, and omitting the
throw
instd::make_exception_ptr
breaks ObjC invariants about how types are thrown/caught.Fixes #135089