]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/53186 ([C++11] missing devirtualization for operators "final")
authorPaolo Carlini <paolo.carlini@oracle.com>
Thu, 3 May 2012 14:28:46 +0000 (14:28 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Thu, 3 May 2012 14:28:46 +0000 (14:28 +0000)
/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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/final2.C [new file with mode: 0644]

index 6b0e57cedb53add7b352f05e131afc43465197b6..46d8b89a0ed05c9e986f6043e42d0b6c2ad6a607 100644 (file)
@@ -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
index e072891f9271c2c69d3d9f211ccbaed2e5afa235..8ae4afe44453def78b1c34492d2528020233b338 100644 (file)
@@ -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;
index c35bd8523abdecf4fb083bb2568531c8440223d4..1378ff45d9c83777667ee813a561ab7c0941b9d1 100644 (file)
@@ -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 (file)
index 0000000..a075622
--- /dev/null
@@ -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" } }