* cp-tree.h (struct lang_type_class): add field for key method
authoraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jan 2003 19:48:55 +0000 (19:48 +0000)
committeraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jan 2003 19:48:55 +0000 (19:48 +0000)
        (cp_global_trees): rename dynamic_classes to keyed_classes
        (key_method): add definition
        * class.c (finish_struct_1): compute class's key method, and add
        the class to keyed_classes list if there is no key method.
        * decl.c (finish_function): add class to keyed_classes list if we
        see a definition of the class's key method.
        * pt.c (instantiate_class_template): add template specialization
        of a dynamic class to keyed_classes list.
        * decl2.c (key_method): remove
        (finish_file): iterate only through keyed_classes list when
        deciding whether to emit vtables, remove class from its list after
        we do the emission.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60850 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c

index dad9680..344630d 100644 (file)
@@ -1,3 +1,19 @@
+2003-01-03  Matt Austern  <austern@apple.com>
+
+       * cp-tree.h (struct lang_type_class): add field for key method
+       (cp_global_trees): rename dynamic_classes to keyed_classes
+       (key_method): add definition
+       * class.c (finish_struct_1): compute class's key method, and add
+       the class to keyed_classes list if there is no key method.
+       * decl.c (finish_function): add class to keyed_classes list if we
+       see a definition of the class's key method.
+       * pt.c (instantiate_class_template): add template specialization
+       of a dynamic class to keyed_classes list.
+       * decl2.c (key_method): remove
+       (finish_file): iterate only through keyed_classes list when
+       deciding whether to emit vtables, remove class from its list after
+       we do the emission.
+       
 2003-01-02  Jason Merrill  <jason@redhat.com>
 
        * decl.c (cp_make_fname_decl): Push the decls inside the
index 54dde53..c278aa5 100644 (file)
@@ -5224,6 +5224,30 @@ layout_class_type (tree t, tree *virtuals_p)
   splay_tree_delete (empty_base_offsets);
 }
 
+/* Returns the virtual function with which the vtable for TYPE is
+   emitted, or NULL_TREE if that heuristic is not applicable to TYPE.  */
+
+static tree
+key_method (tree type)
+{
+  tree method;
+
+  if (TYPE_FOR_JAVA (type)
+      || processing_template_decl
+      || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+      || CLASSTYPE_INTERFACE_KNOWN (type))
+    return NULL_TREE;
+
+  for (method = TYPE_METHODS (type); method != NULL_TREE;
+       method = TREE_CHAIN (method))
+    if (DECL_VINDEX (method) != NULL_TREE
+       && ! DECL_DECLARED_INLINE_P (method)
+       && ! DECL_PURE_VIRTUAL_P (method))
+      return method;
+
+  return NULL_TREE;
+}
+
 /* Perform processing required when the definition of T (a class type)
    is complete.  */
 
@@ -5265,6 +5289,17 @@ finish_struct_1 (t)
      bases and members and add implicitly generated methods.  */
   check_bases_and_members (t);
 
+  /* Find the key method */
+    if (TYPE_CONTAINS_VPTR_P (t))
+    {
+      CLASSTYPE_KEY_METHOD (t) = key_method (t);
+
+      /* If a polymorphic class has no key method, we may emit the vtable
+        in every translation unit where the class definition appears. */
+      if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
+       keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+    }
+
   /* Layout the class itself.  */
   layout_class_type (t, &virtuals);
 
@@ -5342,9 +5377,6 @@ finish_struct_1 (t)
          else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
            DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);
        }
-
-      /* Add this class to the list of dynamic classes.  */
-      dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
     }
 
   finish_struct_bits (t);
index 111cc2f..8f77d10 100644 (file)
@@ -628,7 +628,7 @@ enum cp_tree_index
     CPTI_DSO_HANDLE,
     CPTI_DCAST,
 
-    CPTI_DYNAMIC_CLASSES,
+    CPTI_KEYED_CLASSES,
 
     CPTI_MAX
 };
@@ -761,9 +761,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
    destructors.  */
 #define vtt_parm_type                   cp_global_trees[CPTI_VTT_PARM_TYPE]
 
-/* A TREE_LIST of all of the dynamic classes in the program.  */
+/* A TREE_LIST of the dynamic classes whose vtables may have to be
+   emitted in this translation unit.  */
 
-#define dynamic_classes                 cp_global_trees[CPTI_DYNAMIC_CLASSES]
+#define keyed_classes                   cp_global_trees[CPTI_KEYED_CLASSES]
 
 /* Global state.  */
 
@@ -1182,6 +1183,7 @@ struct lang_type_class GTY(())
   tree pure_virtuals;
   tree friend_classes;
   tree methods;
+  tree key_method;
   tree decl_list;
   tree template_info;
   tree befriending_classes;
@@ -1302,6 +1304,11 @@ struct lang_type GTY(())
    hierarchy, then we can use more efficient search techniques.  */
 #define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3 (NODE))
 
+/* The member function with which the vtable will be emitted:
+   the first noninline non-pure-virtual member function.  NULL_TREE
+   if there is no key function or if this is a class template */
+#define CLASSTYPE_KEY_METHOD(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->key_method)
+
 /* Vector member functions defined in this class.  Each element is
    either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD.  All
    functions with the same name end up in the same slot.  The first
index ed20009..63ec317 100644 (file)
@@ -14360,6 +14360,15 @@ finish_function (flags)
   if (fndecl == NULL_TREE)
     return error_mark_node;
 
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+      && DECL_VIRTUAL_P (fndecl)
+      && !processing_template_decl)
+    {
+      tree fnclass = DECL_CONTEXT (fndecl);
+      if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+       keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+    }
+
   nested = function_depth > 1;
   fntype = TREE_TYPE (fndecl);
 
index 8e440e9..73e37ad 100644 (file)
@@ -88,7 +88,6 @@ static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
 static tree prune_vars_needing_no_initialization (tree);
 static void write_out_vars (tree);
 static void import_export_class (tree);
-static tree key_method (tree); 
 static tree get_guard_bits (tree);
 
 /* A list of static class variables.  This is needed, because a
@@ -1536,29 +1535,6 @@ maybe_make_one_only (tree decl)
     }
 }
 
-/* Returns the virtual function with which the vtable for TYPE is
-   emitted, or NULL_TREE if that heuristic is not applicable to TYPE.  */
-
-static tree
-key_method (tree type)
-{
-  tree method;
-
-  if (TYPE_FOR_JAVA (type)
-      || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
-      || CLASSTYPE_INTERFACE_KNOWN (type))
-    return NULL_TREE;
-
-  for (method = TYPE_METHODS (type); method != NULL_TREE;
-       method = TREE_CHAIN (method))
-    if (DECL_VINDEX (method) != NULL_TREE
-       && ! DECL_DECLARED_INLINE_P (method)
-       && ! DECL_PURE_VIRTUAL_P (method))
-      return method;
-
-  return NULL_TREE;
-}
-
 /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
    based on TYPE and other static flags.
 
@@ -1589,7 +1565,7 @@ import_export_vtable (tree decl, tree type, int final)
         functions in our class, or if we come from a template.  */
 
       int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
-                  || key_method (type));
+                  || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
 
       if (final || ! found)
        {
@@ -1648,7 +1624,7 @@ import_export_class (tree ctype)
   if (import_export == 0
       && TYPE_POLYMORPHIC_P (ctype))
     {
-      tree method = key_method (ctype);
+      tree method = CLASSTYPE_KEY_METHOD (ctype);
       if (method)
        import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
     }
@@ -2639,12 +2615,37 @@ finish_file ()
       instantiate_pending_templates ();
 
       /* Write out virtual tables as required.  Note that writing out
-        the virtual table for a template class may cause the
-        instantiation of members of that class.  */
-      for (t = dynamic_classes; t; t = TREE_CHAIN (t))
-       if (maybe_emit_vtables (TREE_VALUE (t)))
-         reconsider = true;
-      
+        the virtual table for a template class may cause the
+        instantiation of members of that class.  If we write out
+        vtables then we remove the class from our list so we don't
+        have to look at it again. */
+      while (keyed_classes != NULL_TREE
+            && maybe_emit_vtables (TREE_VALUE (keyed_classes)))
+       {
+         reconsider = 1;
+         keyed_classes = TREE_CHAIN (keyed_classes);
+       }
+      t = keyed_classes;
+      if (t != NULL_TREE)
+       {
+         tree next = TREE_CHAIN (t);
+         while (next)
+           {
+             if (maybe_emit_vtables (TREE_VALUE (next)))
+               {
+                 reconsider = 1;
+                 TREE_CHAIN (t) = TREE_CHAIN (next);
+               }
+             else
+               t = next;
+             next = TREE_CHAIN (t);
+           }
+       }
+       
       /* Write out needed type info variables. Writing out one variable
          might cause others to be needed.  */
       if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
index ae81051..aedc90d 100644 (file)
@@ -5487,6 +5487,9 @@ instantiate_class_template (type)
   pop_from_top_level ();
   pop_tinst_level ();
 
+  if (TYPE_CONTAINS_VPTR_P (type))
+    keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
   return type;
 }