| Submitter | Roberto Agostino Vitillo |
|---|---|
| Date | Sept. 20, 2011, 4:43 p.m. |
| Message ID | <CEFC5DBC-8421-4578-A04B-97FABD7A2214@lbl.gov> |
| Download | mbox | patch |
| Permalink | /patch/115601/ |
| State | New |
| Headers | show |
Comments
On 09/20/2011 12:43 PM, Roberto Agostino Vitillo wrote: > - 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; I think we don't need the extra parentheses on the flags test here; if LOOKUP_NONVIRTUAL is already set, we can stop right there rather than look for reasons to set it. I'll go ahead and change that and check in the patch. This patch is small enough not to need a copyright assignment, but it would be good to get one on file now so that we don't need to wait on that for future patches. You can get more information about copyright assignment from copyright-clerk@fsf.org Thanks, Jason
Patch
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;
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 <ravitillo@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