http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53186
Bug #: 53186 Summary: [C++11] missing devirtualization for operators "final" Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: vincenzo.innoce...@cern.ch the example below shows how the keyword "final" has NO effect in devirtualizing operators while it works for methods (as solved in PR49488) cat opFinal.cpp struct A { virtual void operator()(); virtual void m(); }; struct F1 { virtual void operator()() final; virtual void m() final; }; struct F2 final { virtual void operator()(); virtual void m(); }; void fooAop(A & a) {a();} void fooA(A & a) {a.m();} void fooF1op(F1 & a) {a();} void fooF1(F1 & a) {a.m();} void fooF2op(F2 & a) {a();} void fooF2(F2 & a) {a.m();} c++ -std=gnu++11 -c opFinal.cpp; nm opFinal.o; otool -t -v -V -X opFinal.o | c++filt 00000000000000c0 s EH_frame1 0000000000000021 T __Z4fooAR1A 0000000000000067 T __Z5fooF1R2F1 00000000000000a2 T __Z5fooF2R2F2 0000000000000000 T __Z6fooAopR1A 0000000000000046 T __Z7fooF1opR2F1 0000000000000081 T __Z7fooF2opR2F2 U __ZN2F11mEv U __ZN2F21mEv fooAop(A&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooA(A&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax addq $0x08,%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF1op(F1&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF1(F1&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq %rax,%rdi callq F1::m() leave ret fooF2op(F2&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF2(F2&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq %rax,%rdi callq F2::m() leave ret host-001:bugs48 innocent$ cat opFinal.cpp struct A { virtual void operator()(); virtual void m(); }; struct F1 { virtual void operator()() final; virtual void m() final; }; struct F2 final { virtual void operator()(); virtual void m(); }; void fooAop(A & a) {a();} void fooA(A & a) {a.m();} void fooF1op(F1 & a) {a();} void fooF1(F1 & a) {a.m();} void fooF2op(F2 & a) {a();} void fooF2(F2 & a) {a.m();} host-001:bugs48 innocent$ c++ -std=gnu++11 -c opFinal.cpp; nm opFinal.o; otool -t -v -V -X opFinal.o | c++filt 00000000000000c0 s EH_frame1 0000000000000021 T __Z4fooAR1A 0000000000000067 T __Z5fooF1R2F1 00000000000000a2 T __Z5fooF2R2F2 0000000000000000 T __Z6fooAopR1A 0000000000000046 T __Z7fooF1opR2F1 0000000000000081 T __Z7fooF2opR2F2 U __ZN2F11mEv U __ZN2F21mEv fooAop(A&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooA(A&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax addq $0x08,%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF1op(F1&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF1(F1&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq %rax,%rdi callq F1::m() leave ret fooF2op(F2&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq (%rax),%rax movq (%rax),%rax movq 0xf8(%rbp),%rdx movq %rdx,%rdi call *%rax leave ret fooF2(F2&): pushq %rbp movq %rsp,%rbp subq $0x10,%rsp movq %rdi,0xf8(%rbp) movq 0xf8(%rbp),%rax movq %rax,%rdi callq F2::m() leave ret host-001:bugs48 innocent$ c++ -v Using built-in specs. COLLECT_GCC=c++ COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-apple-darwin11.3.0/4.8.0/lto-wrapper Target: x86_64-apple-darwin11.3.0 Configured with: ./configure --enable-languages=c,c++,fortran --disable-multilib --disable-bootstrap --enable-lto -disable-libitm : (reconfigured) ./configure --enable-languages=c,c++,fortran --disable-multilib --disable-bootstrap --enable-lto -disable-libitm Thread model: posix gcc version 4.8.0 20120416 (experimental) [trunk revision 186494] (GCC)