From: Paolo Carlini Date: Thu, 3 May 2012 14:28:46 +0000 (+0000) Subject: re PR c++/53186 ([C++11] missing devirtualization for operators "final") X-Git-Tag: misc/gccgo-go1_1_2~3128 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1fa2969ff66462973c073f4605d8881e40551aff;p=thirdparty%2Fgcc.git re PR c++/53186 ([C++11] missing devirtualization for operators "final") /cp 2012-05-03 Paolo Carlini 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 PR c++/53186 * g++.dg/other/final2.C: New. From-SVN: r187097 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6b0e57cedb53..46d8b89a0ed0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2012-05-03 Paolo Carlini + + 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 * decl.c (grokdeclarator): Properly check for sizes that diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e072891f9271..8ae4afe44453 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 c35bd8523abd..1378ff45d9c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-05-03 Paolo Carlini + + PR c++/53186 + * g++.dg/other/final2.C: New. + 2012-05-03 Richard Guenther * 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 000000000000..a07562299d6f --- /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" } }