The new exceptional EH allocator failed to align exception objects properly (it ended up aligning to __alignof__((std::size_t))). The following fixes that by aligning to what __attribute__((aligned)) would align to (this is what _Unwind_Exception is aligned to, a member of __cxa_refcounted_exception).
Bootstrapped and tested on x86_64-unknown-linux-gnu - Rainer is testing this on sparc-solaris where it broke g++.old-deja/g++.eh/badalloc1.C. Ok for trunk? Thanks, Richard. 2015-01-27 Richard Biener <rguent...@suse.de> PR libstdc++/64798 * libsupc++/eh_alloc.cc (struct allocated_entry): Align data member. (pool::allocate): Adjust allocation size and alignment to that change. (pool::free): Adjust pointer offsetting. Index: libstdc++-v3/libsupc++/eh_alloc.cc =================================================================== --- libstdc++-v3/libsupc++/eh_alloc.cc (revision 220164) +++ libstdc++-v3/libsupc++/eh_alloc.cc (working copy) @@ -94,7 +94,7 @@ namespace }; struct allocated_entry { std::size_t size; - char data[]; + char data[] __attribute__((aligned)); }; // A single mutex controlling emergency allocations. @@ -133,17 +133,18 @@ namespace void *pool::allocate (std::size_t size) { __gnu_cxx::__scoped_lock sentry(emergency_mutex); - // We need an additional size_t member. - size += sizeof (std::size_t); + // We need an additional size_t member plus the padding to + // ensure proper alignment of data. + size += offsetof (allocated_entry, data); // And we need to at least hand out objects of the size of // a freelist entry. if (size < sizeof (free_entry)) size = sizeof (free_entry); - // And we need to align objects we hand out to the required - // alignment of a freelist entry (this really aligns the + // And we need to align objects we hand out to the maximum + // alignment required on the target (this really aligns the // tail which will become a new freelist entry). - size = ((size + __alignof__(free_entry) - 1) - & ~(__alignof__(free_entry) - 1)); + size = ((size + __alignof__ (allocated_entry::data) - 1) + & ~(__alignof__ (allocated_entry::data) - 1)); // Search for an entry of proper size on the freelist. free_entry **e; for (e = &first_free_entry; @@ -185,7 +186,7 @@ namespace { __gnu_cxx::__scoped_lock sentry(emergency_mutex); allocated_entry *e = reinterpret_cast <allocated_entry *> - (reinterpret_cast <char *> (data) - sizeof (std::size_t)); + (reinterpret_cast <char *> (data) - offsetof (allocated_entry, data)); std::size_t sz = e->size; if (!first_free_entry) {