diff mbox

Handle final types & methods in ipa-devirt

Message ID 20130825151924.GA29339@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Aug. 25, 2013, 3:19 p.m. UTC
Hi,
this patch adds ipa-devirt code for final types and methods.  There is
probably no way to construct a testcase that will be devirtualized,
since all the simple minded devirtualization is already done by FE.
I however checked that dumps seems sane at least.  Once we are able
to track types of THIS pointers, this will become interesting.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

	* ipa-devirt.c (struct odr_type_d): Add final_type field.
	(dump_odr_type): Add dumping.
	(possible_polymorphic_call_targets): Support final types
	and final methods.
diff mbox

Patch

Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 201974)
+++ ipa-devirt.c	(working copy)
@@ -137,6 +137,8 @@  struct GTY(()) odr_type_d
   int id;
   /* Is it in anonymous namespace? */
   bool anonymous_namespace;
+  /* Is it final type?  */
+  bool final_type;
 };
 
 
@@ -270,6 +272,7 @@  get_odr_type (tree type, bool insert)
       val->bases = vNULL;
       val->derived_types = vNULL;
       val->anonymous_namespace = type_in_anonymous_namespace_p (type);
+      val->final_type = TYPE_FINAL_P (type);
       *slot = val;
       for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++)
 	/* For now record only polymorphic types. other are
@@ -300,7 +303,8 @@  dump_odr_type (FILE *f, odr_type t, int
   unsigned int i;
   fprintf (f, "%*s type %i: ", indent * 2, "", t->id);
   print_generic_expr (f, t->type, TDF_SLIM);
-  fprintf (f, "%s\n", t->anonymous_namespace ? " (anonymous namespace)":"");
+  fprintf (f, "%s%s\n", t->anonymous_namespace ? " (anonymous namespace)":"",
+	   t->final_type ? " (final)":"");
   if (TYPE_NAME (t->type))
     {
       fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "",
@@ -598,7 +602,7 @@  possible_polymorphic_call_targets (tree
 
   /* For anonymous namespace types we can attempt to build full type.
      All derivations must be in this unit.  */
-  if (type->anonymous_namespace && finalp && !flag_ltrans)
+  if ((type->anonymous_namespace || type->final_type) && finalp && !flag_ltrans)
     *finalp = true;
 
   /* Initialize query cache.  */
@@ -637,19 +641,24 @@  possible_polymorphic_call_targets (tree
   target = gimple_get_virt_method_for_binfo (otr_token, binfo);
   if (target)
     maybe_record_node (nodes, target, inserted);
-  pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
 
-  /* TODO: If method is final, we can stop here and signaize that
-     list is final.  We need C++ FE to pass our info about final
-     methods and classes.  */
+  /* If we failed to find the method, we no longer have final list
+     This can happen i.e. when we can not refer to decl from other unit.  */
+  if (!nodes.length())
+    *finalp = false;
+  pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
 
-  /* Walk recursively all derived types.  Here we need to lookup proper basetype
-     via their BINFO walk that is done by record_binfo  */
-  for (i = 0; i < type->derived_types.length(); i++)
-    possible_polymorphic_call_targets_1 (nodes, inserted,
-					 matched_vtables,
-					 otr_type, type->derived_types[i],
-					 otr_token);
+  /* If method is not final, walk recursively all derived types.
+     Here we need to lookup proper basetype via their BINFO walk that is done
+     by record_binfo  */
+  if (!nodes.length () || !DECL_FINAL_P (nodes[0]->symbol.decl))
+    for (i = 0; i < type->derived_types.length(); i++)
+      possible_polymorphic_call_targets_1 (nodes, inserted,
+					   matched_vtables,
+					   otr_type, type->derived_types[i],
+					   otr_token);
+  else if (finalp)
+    *finalp = true;
   (*slot)->targets = nodes;
 
   pointer_set_destroy (inserted);