https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69777

Eric Gallager <egallager at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |NEW
         Resolution|INVALID                     |---
      Known to fail|                            |4.9.1, 5.5.0, 6.4.0, 7.2.1,
                   |                            |8.0

--- Comment #5 from Eric Gallager <egallager at gcc dot gnu.org> ---
(In reply to Vadim Zeitlin from comment #4)
> Sorry, I've somehow forgot to provide the example, but here it is in its
> most minimal form:
> 
> namespace {
>     struct AnonB {
>         virtual bool foo() const = 0;
>         virtual ~AnonB() {}
>     };
> }
> 
> struct RealB {
>     virtual bool foo() const = 0;
>     virtual ~RealB() {}
> };
> 
> AnonB* create()
> {
>     struct D : RealB {
>         virtual bool foo() const { return true; }
>     };
> 
>     return reinterpret_cast<AnonB*>(new D);
> }
> 
> int main() {
>     return create()->foo(); // please ignore the memory leak here
> }
> 
> Compiling this without optimizations "works", while with -O2 or -O3 the
> program terminates due to a pure virtual function call and the code looks
> just like this:
> 
> (gdb) disassemble
> Dump of assembler code for function main():
> => 0x0000000000400670 <+0>:     mov    edi,0x8
>    0x0000000000400675 <+5>:     sub    rsp,0x8
>    0x0000000000400679 <+9>:     call   0x400660 <_Znwm@plt>
>    0x000000000040067e <+14>:    mov    QWORD PTR [rax],0x4008b0
>    0x0000000000400685 <+21>:    mov    rdi,rax
>    0x0000000000400688 <+24>:    call   0x400650 <__cxa_pure_virtual@plt>
> End of assembler dump.
> 
> Again, I understand that the program invokes undefined behaviour and the
> compiler is perfectly in its right to do what it does. But in practice casts
> such as above are always required when using COM with its QueryInterface()
> and it would be nice if the compiler could warn about this devirtualization
> because it can never be intentional, AFAICS.
> 
> Also notice that giving the namespace a name (and replacing AnonB with
> NS::AnonB) also prevents the devirtualization from happening.
> 
> Finally, I've tested this with (the originally reported) 4.9, 5.5, 6.4 and
> 7.2 and the behaviour is almost the same for all of them, but 7.2 does give
> this warning
> 
> puredevirt.cpp: In function β€˜int main()’:
> puredevirt.cpp:24:25: warning: β€˜<anonymous>’ is used uninitialized in this
> function [-Wuninitialized]
>      return create()->foo();
>             ~~~~~~~~~~~~~^~
> 
> I guess this already partially addresses my request because at least there
> is a warning, but its wording is not especially clear. Looking at the
> disassembly
> 
> (gdb) disassemble
> Dump of assembler code for function main:
> => 0x0000555555554600 <+0>:     sub    rsp,0x8
>    0x0000555555554604 <+4>:     mov    edi,0x8
>    0x0000555555554609 <+9>:     call   0x5555555545e0 <_Znwm@plt>
>    0x000055555555460e <+14>:    call   0x5555555545d0
> <__cxa_pure_virtual@plt>
> End of assembler dump.
> 
> it becomes clear that it's the object on which foo() is called which is not
> initialized (i.e. it doesn't even bother loading its address before calling
> __cxa_pure_virtual, which makes sense), but it's not really obvious from
> just the error message.

Reopening; confirmed that the example only prints the -Wuninitialized warning,
but I get different disassembly, although that's probably due to target
differences. (my gdb doesn't disassemble it properly when optimized, but if I
use -save-temps and examine the assembly, I can see that it still contains the
call to __cxa_pure_virtual at least)

Reply via email to