]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/search.c
class.c (add_method): Build up OVERLOADs properly for conversion ops.
[gcc.git] / gcc / cp / search.c
index 5af1c7d67c4e3900ed03457addda011b14446bc4..d0ae536ea7aee03be65ff0a91eb73dbd189f96bd 100644 (file)
@@ -1,6 +1,6 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
-   Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -116,17 +116,17 @@ static void dfs_get_vbase_types PROTO((tree));
 static void dfs_pushdecls PROTO((tree));
 static void dfs_compress_decls PROTO((tree));
 static void dfs_unuse_fields PROTO((tree));
-static void add_conversions PROTO((tree));
+static tree add_conversions PROTO((tree));
 static tree get_virtuals_named_this PROTO((tree));
-static tree get_virtual_destructor PROTO((tree, int));
-static int tree_has_any_destructor_p PROTO((tree, int));
+static tree get_virtual_destructor PROTO((tree));
+static int tree_has_any_destructor_p PROTO((tree));
 static int covariant_return_p PROTO((tree, tree));
 static struct search_level *push_search_level
        PROTO((struct stack_level *, struct obstack *));
 static struct search_level *pop_search_level
        PROTO((struct stack_level *));
-static HOST_WIDE_INT breadth_first_search
-       PROTO((tree, int (*) (tree, int), int (*) (tree, int)));
+static tree breadth_first_search
+       PROTO((tree, tree (*) (tree), int (*) (tree)));
 
 static tree vbase_types;
 static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;
@@ -1186,11 +1186,20 @@ lookup_field (xbasetype, name, protect, want_type)
        template <class T> void S<T>::I::f() {}
 
      will come through here to handle `S<T>::I'.  */
-  if (rval && TREE_CODE (rval) == TYPE_DECL
-      && processing_template_decl
+  if (rval && processing_template_decl
       && ! currently_open_class (BINFO_TYPE (rval_binfo))
       && uses_template_parms (type))
     {
+      /* We need to return a member template class so we can define partial
+        specializations.  Is there a better way?  */
+      if (DECL_CLASS_TEMPLATE_P (rval))
+       return rval;
+
+      /* Don't return a non-type.  Actually, we ought to return something
+        so lookup_name_real can give a warning.  */
+      if (TREE_CODE (rval) != TYPE_DECL)
+       return NULL_TREE;
+
       binfo = rval_binfo;
       for (; ; binfo = BINFO_INHERITANCE_CHAIN (binfo))
        if (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE
@@ -1277,7 +1286,8 @@ static int
 lookup_fnfields_1 (type, name)
      tree type, name;
 {
-  register tree method_vec = CLASSTYPE_METHOD_VEC (type);
+  register tree method_vec 
+    = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
 
   if (method_vec != 0)
     {
@@ -1605,17 +1615,21 @@ lookup_member (xbasetype, name, protect, want_type)
    QFN, if non-NULL, is a predicate dictating whether the type should
    even be queued.  */
 
-static HOST_WIDE_INT
+static tree
 breadth_first_search (binfo, testfn, qfn)
      tree binfo;
-     int (*testfn) PROTO((tree, int));
-     int (*qfn) PROTO((tree, int));
+     tree (*testfn) PROTO((tree));
+     int (*qfn) PROTO((tree));
 {
   int head = 0, tail = 0;
-  int rval = 0;
+  tree rval = NULL_TREE;
 
   search_stack = push_search_level (search_stack, &search_obstack);
 
+  SET_BINFO_MARKED (binfo);
+  obstack_ptr_grow (&search_obstack, binfo);
+  ++tail;
+
   while (1)
     {
       tree binfos = BINFO_BASETYPES (binfo);
@@ -1628,12 +1642,11 @@ breadth_first_search (binfo, testfn, qfn)
          tree base_binfo = TREE_VEC_ELT (binfos, i);
 
          if (BINFO_MARKED (base_binfo) == 0
-             && (qfn == 0 || (*qfn) (binfo, i)))
+             && (qfn == 0 || (*qfn) (base_binfo)))
            {
              SET_BINFO_MARKED (base_binfo);
-             obstack_ptr_grow (&search_obstack, binfo);
-             obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i);
-             tail += 2;
+             obstack_ptr_grow (&search_obstack, base_binfo);
+             ++tail;
              if (tail >= search_stack->limit)
                my_friendly_abort (100);
            }
@@ -1646,10 +1659,8 @@ breadth_first_search (binfo, testfn, qfn)
        }
 
       binfo = search_stack->first[head++];
-      i = (HOST_WIDE_INT) search_stack->first[head++];
-      if ((rval = (*testfn) (binfo, i)))
+      if ((rval = (*testfn) (binfo)))
        break;
-      binfo = BINFO_BASETYPE (binfo, i);
     }
   {
     tree *tp = search_stack->first;
@@ -1657,8 +1668,7 @@ breadth_first_search (binfo, testfn, qfn)
     while (tp < search_tail)
       {
        tree binfo = *tp++;
-       int i = (HOST_WIDE_INT)(*tp++);
-       CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
+       CLEAR_BINFO_MARKED (binfo);
       }
   }
 
@@ -1667,7 +1677,7 @@ breadth_first_search (binfo, testfn, qfn)
 }
 
 /* Functions to use in breadth first searches.  */
-typedef int (*pfi) PROTO((tree, int));
+typedef tree (*pfi) PROTO((tree));
 
 static tree declarator;
 
@@ -1698,13 +1708,10 @@ get_virtuals_named_this (binfo)
 }
 
 static tree
-get_virtual_destructor (binfo, i)
+get_virtual_destructor (binfo)
      tree binfo;
-     int i;
 {
   tree type = BINFO_TYPE (binfo);
-  if (i >= 0)
-    type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
   if (TYPE_HAS_DESTRUCTOR (type)
       && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1)))
     return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
@@ -1712,13 +1719,10 @@ get_virtual_destructor (binfo, i)
 }
 
 static int
-tree_has_any_destructor_p (binfo, i)
+tree_has_any_destructor_p (binfo)
      tree binfo;
-     int i;
 {
   tree type = BINFO_TYPE (binfo);
-  if (i >= 0)
-    type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
   return TYPE_NEEDS_DESTRUCTOR (type);
 }
 
@@ -1746,7 +1750,7 @@ covariant_return_p (brettype, drettype)
       drettype = TREE_TYPE (drettype);
     }
 
-  if (comptypes (brettype, drettype, 1))
+  if (same_type_p (brettype, drettype))
     return 0;
 
   if (! (TREE_CODE (brettype) == TREE_CODE (drettype)
@@ -1803,16 +1807,9 @@ get_matching_virtual (binfo, fndecl, dtorp)
      of TYPE, so we must perform first ply of search here.  */
   if (dtorp)
     {
-      if (tree_has_any_destructor_p (binfo, -1))
-       tmp = get_virtual_destructor (binfo, -1);
-
-      if (tmp)
-       return tmp;
-
-      tmp = (tree) breadth_first_search (binfo,
-                                        (pfi) get_virtual_destructor,
-                                        tree_has_any_destructor_p);
-      return tmp;
+      return breadth_first_search (binfo,
+                                  get_virtual_destructor,
+                                  tree_has_any_destructor_p);
     }
   else
     {
@@ -1863,7 +1860,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
                  && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
                {
                  tree brettype = TREE_TYPE (TREE_TYPE (tmp));
-                 if (comptypes (brettype, drettype, 1))
+                 if (same_type_p (brettype, drettype))
                    /* OK */;
                  else if ((i = covariant_return_p (brettype, drettype)))
                    {
@@ -1877,7 +1874,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
                        }
                    }
                  else if (IS_AGGR_TYPE_2 (brettype, drettype)
-                          && comptypes (brettype, drettype, 0))
+                          && same_or_base_type_p (brettype, drettype))
                    {
                      error ("invalid covariant return type (must use pointer or reference)");
                      cp_error_at ("  overriding `%#D'", tmp);
@@ -1971,7 +1968,9 @@ get_abstract_virtuals (type)
        {
          tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
-         if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
+         if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
+           cp_error ("`%#D' needs a final overrider", base_fndecl);
+         else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
          virtuals = TREE_CHAIN (virtuals);
        }
@@ -2542,7 +2541,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
              /* Dup it if it isn't in local scope yet.  */
              nvtbl = build_decl
                (VAR_DECL, DECL_NAME (vtbl),
-                TYPE_MAIN_VARIANT (TREE_TYPE (BINFO_VTABLE (binfo))));
+                TYPE_MAIN_VARIANT (TREE_TYPE (vtbl)));
              DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
                                        DECL_ALIGN (nvtbl));
              TREE_READONLY (nvtbl) = 0;
@@ -3015,6 +3014,7 @@ dfs_pushdecls (binfo)
 
          /* If the class value is not an envelope of the kind described in
             the comment above, we create a new envelope.  */
+         maybe_push_cache_obstack ();
          if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
              || TREE_PURPOSE (class_value) == NULL_TREE
              || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
@@ -3027,10 +3027,11 @@ dfs_pushdecls (binfo)
            }
 
          envelope_add_decl (type, fields, &TREE_PURPOSE (class_value));
+         pop_obstacks ();
        }
     }
 
-  method_vec = CLASSTYPE_METHOD_VEC (type);
+  method_vec = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
   if (method_vec && ! dummy)
     {
       tree *methods;
@@ -3052,6 +3053,8 @@ dfs_pushdecls (binfo)
          name = DECL_NAME (OVL_CURRENT (*methods));
          class_value = IDENTIFIER_CLASS_VALUE (name);
 
+         maybe_push_cache_obstack ();
+
          /* If the class value is not an envelope of the kind described in
             the comment above, we create a new envelope.  */
          if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
@@ -3068,7 +3071,6 @@ dfs_pushdecls (binfo)
          /* Here we try to rule out possible ambiguities.
             If we can't do that, keep a TREE_LIST with possibly ambiguous
             decls in there.  */
-         maybe_push_cache_obstack ();
          /* Arbitrarily choose the first function in the list.  This is OK
             because this is only used for initial lookup; anything that
             actually uses the function will look it up again.  */
@@ -3090,7 +3092,8 @@ dfs_compress_decls (binfo)
      tree binfo;
 {
   tree type = BINFO_TYPE (binfo);
-  tree method_vec = CLASSTYPE_METHOD_VEC (type);
+  tree method_vec 
+    = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
 
   if (processing_template_decl && type != current_class_type
       && dependent_base_p (binfo))
@@ -3140,6 +3143,11 @@ push_class_decls (type)
   struct obstack *ambient_obstack = current_obstack;
   search_stack = push_search_level (search_stack, &search_obstack);
 
+  /* Build up all the relevant bindings and such on the cache
+     obstack.  That way no memory is wasted when we throw away the
+     cache later.  */
+  maybe_push_cache_obstack ();
+
   /* Push class fields into CLASS_VALUE scope, and mark.  */
   dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarked_pushdecls_p);
 
@@ -3207,6 +3215,10 @@ push_class_decls (type)
        pushdecl_class_level (new);
       closed_envelopes = TREE_CHAIN (closed_envelopes);
     }
+  
+  /* Undo the call to maybe_push_cache_obstack above.  */
+  pop_obstacks ();
+
   current_obstack = ambient_obstack;
 }
 
@@ -3284,7 +3296,7 @@ reinit_search_statistics ()
 #define scratch_tree_cons expr_tree_cons
 
 static tree conversions;
-static void
+static tree
 add_conversions (binfo)
      tree binfo;
 {
@@ -3294,25 +3306,37 @@ add_conversions (binfo)
   for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
     {
       tree tmp = TREE_VEC_ELT (method_vec, i);
+      tree name;
 
-      if (!tmp
-         || !IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (tmp))))
+      if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
        break;
-      conversions = scratch_tree_cons (binfo, tmp, conversions);
+
+      name = DECL_NAME (OVL_CURRENT (tmp));
+
+      /* Make sure we don't already have this conversion.  */
+      if (! IDENTIFIER_MARKED (name))
+       {
+         conversions = scratch_tree_cons (binfo, tmp, conversions);
+         IDENTIFIER_MARKED (name) = 1;
+       }
     }
-  SET_BINFO_MARKED (binfo);
+  return NULL_TREE;
 }
 
 tree
 lookup_conversions (type)
      tree type;
 {
+  tree t;
+
   conversions = NULL_TREE;
+
   if (TYPE_SIZE (type))
-    {
-      dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp);
-      dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
-    }
+    breadth_first_search (TYPE_BINFO (type), add_conversions, 0);
+
+  for (t = conversions; t; t = TREE_CHAIN (t))
+    IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
+
   return conversions;
 }
 
This page took 0.041725 seconds and 5 git commands to generate.