diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2012-05-03 14:28:46 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2012-05-03 14:28:46 +0000 |
commit | 1fa2969ff66462973c073f4605d8881e40551aff (patch) | |
tree | 15f1bda4374b20c465ed4e02d97a90f4645632fe | |
parent | bea966c222bf8900ebfcc5cd6d83e507b6bec748 (diff) | |
download | gcc-1fa2969ff66462973c073f4605d8881e40551aff.zip gcc-1fa2969ff66462973c073f4605d8881e40551aff.tar.gz gcc-1fa2969ff66462973c073f4605d8881e40551aff.tar.bz2 |
re PR c++/53186 ([C++11] missing devirtualization for operators "final")
/cp
2012-05-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/53186
* call.c (build_over_call): Handle final member functions
and class types.
(build_new_method_call_1): Do not handle here.
/testsuite
2012-05-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/53186
* g++.dg/other/final2.C: New.
From-SVN: r187097
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/final2.C | 27 |
4 files changed, 46 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6b0e57c..46d8b89 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2012-05-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53186 + * call.c (build_over_call): Handle final member functions + and class types. + (build_new_method_call_1): Do not handle here. + 2012-05-02 Richard Guenther <rguenther@suse.de> * decl.c (grokdeclarator): Properly check for sizes that diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e072891..8ae4afe 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6550,6 +6550,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return error_mark_node; } + /* See if the function member or the whole class type is declared + final and the call can be devirtualized. */ + if (DECL_FINAL_P (fn) + || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)))) + flags |= LOOKUP_NONVIRTUAL; + /* [class.mfct.nonstatic]: If a nonstatic member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined. @@ -7418,8 +7424,7 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args, /* Optimize away vtable lookup if we know that this function can't be overridden. */ if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL) - && (resolves_to_fixed_type_p (instance, 0) - || DECL_FINAL_P (fn) || CLASSTYPE_FINAL (basetype))) + && resolves_to_fixed_type_p (instance, 0)) flags |= LOOKUP_NONVIRTUAL; if (explicit_targs) flags |= LOOKUP_EXPLICIT_TMPL_ARGS; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c35bd85..1378ff4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-05-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53186 + * g++.dg/other/final2.C: New. + 2012-05-03 Richard Guenther <rguenther@suse.de> * gcc.dg/tree-ssa/ssa-pre-27.c: Remove XFAIL. diff --git a/gcc/testsuite/g++.dg/other/final2.C b/gcc/testsuite/g++.dg/other/final2.C new file mode 100644 index 0000000..a075622 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/final2.C @@ -0,0 +1,27 @@ +// PR c++/53186 +// { dg-options "-fdump-tree-original -std=c++11" } + +struct F1 +{ + virtual void operator()() final; + virtual operator int() final; + virtual int operator++() final; +}; + +struct F2 final +{ + virtual void operator()(); + virtual operator int(); + virtual int operator++(); +}; + +void fooF1(F1& a) { a(); int m = a; ++a; } +void fooF2(F2& a) { a(); int m = a; ++a; } + +// { dg-final { scan-tree-dump-times "F1::operator\\(\\)" 1 "original" } } +// { dg-final { scan-tree-dump-times "F1::operator int" 1 "original" } } +// { dg-final { scan-tree-dump-times "F1::operator\\+\\+" 1 "original" } } +// { dg-final { scan-tree-dump-times "F2::operator\\(\\)" 1 "original" } } +// { dg-final { scan-tree-dump-times "F2::operator int" 1 "original" } } +// { dg-final { scan-tree-dump-times "F2::operator\\+\\+" 1 "original" } } +// { dg-final { cleanup-tree-dump "original" } } |