diff mbox

[C++] PR 53186

Message ID 4FA28F06.3080509@oracle.com
State New
Headers show

Commit Message

Paolo Carlini May 3, 2012, 1:58 p.m. UTC
On 05/03/2012 03:08 PM, Jason Merrill wrote:
> What if we moved all the devirtualization logic from 
> build_new_method_call_1 to build_over_call?
Doh, you are absolutely right, the below, very simple, appears to work 
well. Probably I was afraid that we could have issues with the other 
build_over_call callers, but in fact now I don't see why.

C++ testing done, testing the library. Ok if it passes?

Thanks,
Paolo.

PS: submitter would like to see this in 4.7.1 too...

/////////////////////////
/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.

Comments

Jason Merrill May 3, 2012, 2 p.m. UTC | #1
OK.  Seems safe enough for 4.7.1.

Jason
Paolo Carlini May 3, 2012, 2:41 p.m. UTC | #2
On 05/03/2012 04:00 PM, Jason Merrill wrote:
> OK.  Seems safe enough for 4.7.1.
Applied, thanks!

Paolo.
diff mbox

Patch

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 187058)
+++ cp/call.c	(working copy)
@@ -6550,6 +6550,12 @@  build_over_call (struct z_candidate *cand, int fla
 	    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,
 	      /* 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: testsuite/g++.dg/other/final2.C
===================================================================
--- testsuite/g++.dg/other/final2.C	(revision 0)
+++ testsuite/g++.dg/other/final2.C	(revision 0)
@@ -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" } }