mirror of git://gcc.gnu.org/git/gcc.git
dyncast.cc (__dynamic_cast): Handle mid-destruction dynamic_cast more gracefully.
* libsupc++/dyncast.cc (__dynamic_cast): Handle mid-destruction dynamic_cast more gracefully. From-SVN: r215350
This commit is contained in:
parent
e770bfd997
commit
4666e1fb92
|
|
@ -0,0 +1,28 @@
|
||||||
|
// I think this dynamic_cast has undefined behavior when destroying E::o
|
||||||
|
// because we're the F period of destruction has started and ap doesn't
|
||||||
|
// point to the object currently being destroyed--but the reasonable
|
||||||
|
// options are success or failure, not SEGV.
|
||||||
|
|
||||||
|
// { dg-do run }
|
||||||
|
|
||||||
|
extern "C" void abort();
|
||||||
|
|
||||||
|
struct A { virtual ~A(); };
|
||||||
|
struct B { virtual ~B() { } };
|
||||||
|
struct C : B, A { };
|
||||||
|
struct E : virtual B { A o; };
|
||||||
|
struct F : virtual C, virtual E { };
|
||||||
|
|
||||||
|
A* ap;
|
||||||
|
C* cp;
|
||||||
|
|
||||||
|
A::~A() {
|
||||||
|
C* cp2 = dynamic_cast<C*>(ap);
|
||||||
|
if (cp2 != cp && cp2 != 0)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
F f;
|
||||||
|
ap = cp = &f;
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2014-09-17 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* libsupc++/dyncast.cc (__dynamic_cast): Handle mid-destruction
|
||||||
|
dynamic_cast more gracefully.
|
||||||
|
|
||||||
2014-09-15 Jakub Jelinek <jakub@redhat.com>
|
2014-09-15 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* testsuite/Makefile.am (check_p_numbers0, check_p_numbers1,
|
* testsuite/Makefile.am (check_p_numbers0, check_p_numbers1,
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,18 @@ __dynamic_cast (const void *src_ptr, // object started from
|
||||||
const __class_type_info *whole_type = prefix->whole_type;
|
const __class_type_info *whole_type = prefix->whole_type;
|
||||||
__class_type_info::__dyncast_result result;
|
__class_type_info::__dyncast_result result;
|
||||||
|
|
||||||
|
// If the whole object vptr doesn't refer to the whole object type, we're
|
||||||
|
// in the middle of constructing a primary base, and src is a separate
|
||||||
|
// base. This has undefined behavior and we can't find anything outside
|
||||||
|
// of the base we're actually constructing, so fail now rather than
|
||||||
|
// segfault later trying to use a vbase offset that doesn't exist.
|
||||||
|
const void *whole_vtable = *static_cast <const void *const *> (whole_ptr);
|
||||||
|
const vtable_prefix *whole_prefix =
|
||||||
|
adjust_pointer <vtable_prefix> (whole_vtable,
|
||||||
|
-offsetof (vtable_prefix, origin));
|
||||||
|
if (whole_prefix->whole_type != whole_type)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
|
whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
|
||||||
dst_type, whole_ptr, src_type, src_ptr, result);
|
dst_type, whole_ptr, src_type, src_ptr, result);
|
||||||
if (!result.dst_ptr)
|
if (!result.dst_ptr)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue