On 25 April 2014 13:01, Richard Biener wrote: > On Fri, Apr 25, 2014 at 1:18 PM, Jonathan Wakely <jwakely....@gmail.com> > wrote: >> On 25 April 2014 11:22, Andrew Haley wrote: >>> Summary: Devirtualization uses type information to determine if a >>> virtual method is reachable from a call site. If type information >>> indicates that it is not, devirt marks the site as unreachable. I >>> think this is wrong, and it breaks some programs. At least, it should >>> not do this if the user specifies -fno-strict-aliasing. >>> >>> Consider this class: >>> >>> class Container { >>> void *buffer[5]; >>> public: >>> EmbeddedObject *obj() { return (EmbeddedObject*)buffer; } >>> Container() { new (buffer) EmbeddedObject(); } >>> }; >>> >>> Placement new is used to embed an object in a buffer inside another >>> object. Its address can be retrieved. This usage of placement new is >>> common, and it even appears as the canonical use of placement new in >>> the in the C++ FAQ at >>> http://www.parashift.com/c++-faq/placement-new.html. (I am aware that >>> this is not strictly legal. For one thing, the memory at buffer may >>> not be suitably aligned. Please bear with me.) >> >> I think the program is strictly legal if you define Container like this: >> >> class Container { >> alignas(EmbeddedObject) char buffer[sizeof(EmbeddedObject)]; >> public: >> EmbeddedObject *obj() { return (EmbeddedObject*)buffer; } >> Container() { new (buffer) EmbeddedObject(); } >> }; >> >> But GCC still does the same transformation and prints nothing, which I >> agree is wrong (even with -fstrict-aliasing). > > I agree, -fstrict-aliasing has nothing to do with this. Sounds simply like > a genuine bug (please open a bugzilla). > > Thanks, > Richard. > >> With ubsan that program gives: >> >> sa.cc:9:24: runtime error: load of null pointer of type '<unknown> *' >> Segmentation fault (core dumped)
I created http://gcc.gnu.org/60963 for the ubsan error. The testcase there is a single file which crashes with ubsan and returns the wrong value without. Changing the return statement to __builtin_printf("%d\n", o.obj()->val()) prints nothing, like Andrew's original example. If it's not really a ubsan problem feel free to re-categorise that as a devirt bug rather than open a new one, whatever's most appropriate.