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;

Reply via email to