-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
We should be able to throw and catch null pointers to objects.
(this is easier to see on macOS, with currently-installed versions of libc++abi, but we also fail on compiler explorer)
e.g.
https://godbolt.org/z/fjdhvev93 (non-virtual bases only)
https://godbolt.org/z/qj8nah55j (virtual bases)
edit: -DBROKEN enables the cases
NOTE1: libstdc++ / libsupc++ handle this fine on both macOS and Linux.
NOTE2: This is repeatable with GCC / libstdc++ / libc++abi (but that is only possible with WIP patches to allow the use of c++abi there).
Analysis
The failing cases are when we throw a null pointer-to-object.
The underlying reason for the fail is that the code in private_typeinfo.cpp:
(__base_class_type_info::has_unambiguous_public_base() and the other class impls. + process_found_base_class()) inspects the thrown object layout to determine whether we have seen distinct copies of base classes (and it uses the thrown object to do that).
In the case of a thrown pointer, we pass the pointer-to-object to the methods mentioned above.
However, if those methods see that the pointer is null they (mostly reasonably) refuse to use it to figure out the layout; this means that process_found_base_class() then makes the wrong call on whether base classes are distinct.
Possible ways forward
I spent some time looking at this (a) to analyse and (b) to see if I could come up with a patch.
-
In the case where we have non-virtual base classes, we can actually make this work by pretending we have a dummy object based at 0. Since the __base_class_type_info only contains actual offset of bases, we can compute the layout without having a real object (since we never actually access the object vtables).
-
In the case of virtual bases the situation is much more difficult, since the current code actually inspects the vtables of the thrown object - e.g. __base_class_type_info contains negative offsets to vtable entries, and those are dereferenced to find the actual offset to the virtual base. Clearly, we cannot do that without an object.
So .. I have a WIP patch that does (1) [which I will put on phab as a draft after some more testing]
... but currently no real plan/idea on how to deal with (2)