When calling a final virtual function or a virtual function that belongs to a final class there is no need for a virtual lookup. E.g.:
struct A final { virtual void foo () { } }; struct B { virtual void foo () final { } }; void fun(A* a, B* b) { a->foo(); b->foo(); } with this patch translates to: (__TEXT,__text) section __Z3funP1AP1B: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 subq $0x10,%rsp 0000000000000008 movq %rdi,0xf8(%rbp) 000000000000000c movq %rsi,0xf0(%rbp) 0000000000000010 movq 0xf8(%rbp),%rax 0000000000000014 movq %rax,%rdi 0000000000000017 callq __ZN1A3fooEv 000000000000001c movq 0xf0(%rbp),%rax 0000000000000020 movq %rax,%rdi 0000000000000023 callq __ZN1B3fooEv 0000000000000028 leave 0000000000000029 ret Tested on macosx x86_64. r 2011-09-20 Roberto Agostino Vitillo <raviti...@lbl.gov> * gcc/testsuite/g++.dg/other/final1.C: new test * gcc/cp/call.c (build_new_method_call_1): use non virtual lookup for final virtual functions Index: gcc/testsuite/g++.dg/other/final1.C =================================================================== --- gcc/testsuite/g++.dg/other/final1.C (revision 0) +++ gcc/testsuite/g++.dg/other/final1.C (revision 0) @@ -0,0 +1,26 @@ +/* Verify that final methods are devirtualized */ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original -std=c++0x" } */ + +struct A final +{ + virtual void foo () + { + } +}; + +struct B +{ + virtual void foo () final + { + } +}; + +void fun(A* a, B* b) +{ + a->foo(); + b->foo(); +} + +/* { dg-final { scan-tree-dump-times "A::foo" 2 "original" } } */ +/* { dg-final { scan-tree-dump-times "B::foo" 2 "original" } } */ Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 178911) +++ gcc/cp/call.c (working copy) @@ -7277,8 +7277,9 @@ } else { - if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL) - && resolves_to_fixed_type_p (instance, 0)) + if (DECL_VINDEX (fn) && ((! (flags & LOOKUP_NONVIRTUAL) + && resolves_to_fixed_type_p (instance, 0)) + || DECL_FINAL_P (fn) || CLASSTYPE_FINAL (basetype))) flags |= LOOKUP_NONVIRTUAL; if (explicit_targs) flags |= LOOKUP_EXPLICIT_TMPL_ARGS;