OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Dec 2000 15:50:06 +0000 (15:50 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Dec 2000 15:50:06 +0000 (15:50 +0000)
* cp-tree.h (IDENTIFIER_VIRTUAL_P): Document.
(get_matching_virtual): Remove.
(look_for_overrides): Declare new function.
* decl.c (grokfndecl): Don't set IDENTIFIER_VIRTUAL_P or
DECL_VINDEX here.
* class.c (check_for_override): Move base class iteration code
to look_for_overrides.
* search.c (next_baselink): Remove.
(get_virtuals_named_this): Remove.
(get_virtual_destructor): Remove.
(tree_has_any_destructors_p): Remove.
(struct gvnt_info): Remove.
(check_final_overrider): Remove `virtual' from error messages.
(get_matching_virtuals): Remove. Move functionality to ...
(look_for_overrides): ... here, and ...
(look_for_overrides_r): ... here. Set DECL_VIRTUAL_P, if found
to be overriding.
testsuite:
* g++.old-deja/g++.h/spec6.C: Remove some of the XFAILS.
* g++.old-deja/g++.other/virtual10.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.eh/spec6.C
gcc/testsuite/g++.old-deja/g++.other/virtual10.C [new file with mode: 0644]

index e2d7226..10fff7f 100644 (file)
@@ -1,5 +1,25 @@
 2000-12-05  Nathan Sidwell  <nathan@codesourcery.com>
 
+       * cp-tree.h (IDENTIFIER_VIRTUAL_P): Document.
+       (get_matching_virtual): Remove.
+       (look_for_overrides): Declare new function.
+       * decl.c (grokfndecl): Don't set IDENTIFIER_VIRTUAL_P or
+       DECL_VINDEX here.
+       * class.c (check_for_override): Move base class iteration code
+       to look_for_overrides.
+       * search.c (next_baselink): Remove.
+       (get_virtuals_named_this): Remove.
+       (get_virtual_destructor): Remove.
+       (tree_has_any_destructors_p): Remove.
+       (struct gvnt_info): Remove.
+       (check_final_overrider): Remove `virtual' from error messages.
+       (get_matching_virtuals): Remove. Move functionality to ...
+       (look_for_overrides): ... here, and ...
+       (look_for_overrides_r): ... here. Set DECL_VIRTUAL_P, if found
+       to be overriding.
+
+2000-12-05  Nathan Sidwell  <nathan@codesourcery.com>
+
        * typeck.c (get_delta_difference): If via a virtual base,
        return zero.
        * cvt.c (cp_convert_to_pointer): If via a virtual base, do no
index 9a71203..ff3d264 100644 (file)
@@ -2910,56 +2910,24 @@ static void
 check_for_override (decl, ctype)
      tree decl, ctype;
 {
-  tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  int virtualp = DECL_VIRTUAL_P (decl);
-  int found_overriden_fn = 0;
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+    /* In [temp.mem] we have:
 
-  for (i = 0; i < n_baselinks; i++)
-    {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
-       {
-         tree tmp = get_matching_virtual
-           (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
-
-         if (tmp && !found_overriden_fn)
-           {
-             /* If this function overrides some virtual in some base
-                class, then the function itself is also necessarily
-                virtual, even if the user didn't explicitly say so.  */
-             DECL_VIRTUAL_P (decl) = 1;
-
-             /* The TMP we really want is the one from the deepest
-                baseclass on this path, taking care not to
-                duplicate if we have already found it (via another
-                path to its virtual baseclass.  */
-             if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
-               {
-                 cp_error_at ("`static %#D' cannot be declared", decl);
-                 cp_error_at ("  since `virtual %#D' declared in base class",
-                              tmp);
-                 break;
-               }
-             virtualp = 1;
-
-             /* Set DECL_VINDEX to a value that is neither an
-                INTEGER_CST nor the error_mark_node so that
-                add_virtual_function will realize this is an
-                overridden function.  */
-             DECL_VINDEX (decl) 
-               = tree_cons (tmp, NULL_TREE, DECL_VINDEX (decl));
-             
-             /* We now know that DECL overrides something,
-                which is all that is important.  But, we must
-                continue to iterate through all the base-classes
-                in order to allow get_matching_virtual to check for
-                various illegal overrides.  */
-             found_overriden_fn = 1;
-           }
-       }
-    }
-  if (virtualp)
+         A specialization of a member function template does not
+         override a virtual function from a base class.  */
+    return;
+  if ((DECL_DESTRUCTOR_P (decl)
+       || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+      && look_for_overrides (ctype, decl)
+      && !DECL_STATIC_FUNCTION_P (decl))
+    {
+      /* Set DECL_VINDEX to a value that is neither an
+        INTEGER_CST nor the error_mark_node so that
+        add_virtual_function will realize this is an
+        overriding function.  */
+      DECL_VINDEX (decl) = decl;
+    }
+  if (DECL_VIRTUAL_P (decl))
     {
       if (DECL_VINDEX (decl) == NULL_TREE)
        DECL_VINDEX (decl) = error_mark_node;
index c8cfa25..5b7eca9 100644 (file)
@@ -514,7 +514,8 @@ struct tree_srcloc
 #define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \
        SET_LANG_ID(NODE, VALUE, error_locus)
 
-
+/* Nonzero if this identifier is used as a virtual function name somewhere
+   (optimizes searches).  */
 #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE)
 
 /* Nonzero if this identifier is the prefix for a mangled C++ operator
@@ -4250,7 +4251,7 @@ extern tree lookup_field                  PARAMS ((tree, tree, int, int));
 extern int lookup_fnfields_1                    PARAMS ((tree, tree));
 extern tree lookup_fnfields                    PARAMS ((tree, tree, int));
 extern tree lookup_member                      PARAMS ((tree, tree, int, int));
-extern tree get_matching_virtual               PARAMS ((tree, tree, int));
+extern int look_for_overrides                  PARAMS ((tree, tree));
 extern void get_pure_virtuals                  PARAMS ((tree));
 extern tree init_vbase_pointers                        PARAMS ((tree, tree));
 extern void get_vbase_types                    PARAMS ((tree));
index b84e847..24b24df 100644 (file)
@@ -9038,12 +9038,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
     return decl;
 
   if (virtualp)
-    {
-      DECL_VIRTUAL_P (decl) = 1;
-      if (DECL_VINDEX (decl) == NULL_TREE)
-       DECL_VINDEX (decl) = error_mark_node;
-      IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
-    }
+    DECL_VIRTUAL_P (decl) = 1;
 
   return decl;
 }
index aa48b7d..601f08b 100644 (file)
@@ -83,7 +83,6 @@ struct vbase_info
   tree inits;
 };
 
-static tree next_baselink PARAMS ((tree));
 static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
 static tree lookup_field_1 PARAMS ((tree, tree));
 static int lookup_fnfields_here PARAMS ((tree, tree));
@@ -110,11 +109,9 @@ static tree dfs_push_type_decls PARAMS ((tree, void *));
 static tree dfs_push_decls PARAMS ((tree, void *));
 static tree dfs_unuse_fields PARAMS ((tree, void *));
 static tree add_conversions PARAMS ((tree, void *));
-static tree get_virtuals_named_this PARAMS ((tree, tree));
-static tree get_virtual_destructor PARAMS ((tree, void *));
-static tree tree_has_any_destructor_p PARAMS ((tree, void *));
 static int covariant_return_p PARAMS ((tree, tree));
 static int check_final_overrider PARAMS ((tree, tree));
+static int look_for_overrides_r PARAMS ((tree, tree));
 static struct search_level *push_search_level
        PARAMS ((struct stack_level *, struct obstack *));
 static struct search_level *pop_search_level
@@ -124,7 +121,6 @@ static tree bfs_walk
               void *));
 static tree lookup_field_queue_p PARAMS ((tree, void *));
 static tree lookup_field_r PARAMS ((tree, void *));
-static tree get_virtuals_named_this_r PARAMS ((tree, void *));
 static tree context_for_name_lookup PARAMS ((tree));
 static tree canonical_binfo PARAMS ((tree));
 static tree shared_marked_p PARAMS ((tree, void *));
@@ -1867,87 +1863,6 @@ dfs_walk (binfo, fn, qfn, data)
   return dfs_walk_real (binfo, 0, fn, qfn, data);
 }
 
-struct gvnt_info 
-{
-  /* The name of the function we are looking for.  */
-  tree name;
-  /* The overloaded functions we have found.  */
-  tree fields;
-};
-
-/* Called from get_virtuals_named_this via bfs_walk.  */
-
-static tree
-get_virtuals_named_this_r (binfo, data)
-     tree binfo;
-     void *data;
-{
-  struct gvnt_info *gvnti = (struct gvnt_info *) data;
-  tree type = BINFO_TYPE (binfo);
-  int idx;
-
-  idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name);
-  if (idx >= 0)
-    gvnti->fields
-      = tree_cons (binfo, 
-                  TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx),
-                  gvnti->fields);
-
-  return NULL_TREE;
-}
-
-/* Return the virtual functions with the indicated NAME in the type
-   indicated by BINFO.  The result is a TREE_LIST whose TREE_PURPOSE
-   indicates the base class from which the TREE_VALUE (an OVERLOAD or
-   just a FUNCTION_DECL) originated.  */
-
-static tree
-get_virtuals_named_this (binfo, name)
-     tree binfo;
-     tree name;
-{
-  struct gvnt_info gvnti;
-  tree fields;
-
-  gvnti.name = name;
-  gvnti.fields = NULL_TREE;
-
-  bfs_walk (binfo, get_virtuals_named_this_r, 0, &gvnti);
-
-  /* Get to the function decls, and return the first virtual function
-     with this name, if there is one.  */
-  for (fields = gvnti.fields; fields; fields = next_baselink (fields))
-    {
-      tree fndecl;
-
-      for (fndecl = TREE_VALUE (fields); fndecl; fndecl = OVL_NEXT (fndecl))
-       if (DECL_VINDEX (OVL_CURRENT (fndecl)))
-         return fields;
-    }
-  return NULL_TREE;
-}
-
-static tree
-get_virtual_destructor (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  tree type = BINFO_TYPE (binfo);
-  if (TYPE_HAS_DESTRUCTOR (type)
-      && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1)))
-    return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
-  return 0;
-}
-
-static tree
-tree_has_any_destructor_p (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  tree type = BINFO_TYPE (binfo);
-  return TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) ? binfo : NULL_TREE;
-}
-
 /* Returns > 0 if a function with type DRETTYPE overriding a function
    with type BRETTYPE is covariant, as defined in [class.virtual].
 
@@ -2026,124 +1941,128 @@ check_final_overrider (overrider, basefn)
 
       if (pedantic && i == -1)
        {
-         cp_pedwarn_at ("invalid covariant return type for `virtual %#D'", overrider);
-         cp_pedwarn_at ("  overriding `virtual %#D' (must be pointer or reference to class)", basefn);
+         cp_pedwarn_at ("invalid covariant return type for `%#D'", overrider);
+         cp_pedwarn_at ("  overriding `%#D' (must be pointer or reference to class)", basefn);
        }
     }
   else if (IS_AGGR_TYPE_2 (base_return, over_return)
           && same_or_base_type_p (base_return, over_return))
     {
-      cp_error_at ("invalid covariant return type for `virtual %#D'", overrider);
-      cp_error_at ("  overriding `virtual %#D' (must use pointer or reference)", basefn);
+      cp_error_at ("invalid covariant return type for `%#D'", overrider);
+      cp_error_at ("  overriding `%#D' (must use pointer or reference)", basefn);
       return 0;
     }
   else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)) == NULL_TREE)
     {
-      cp_error_at ("conflicting return type specified for `virtual %#D'", overrider);
-      cp_error_at ("  overriding `virtual %#D'", basefn);
+      cp_error_at ("conflicting return type specified for `%#D'", overrider);
+      cp_error_at ("  overriding `%#D'", basefn);
       SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
                                   DECL_CONTEXT (overrider));
       return 0;
     }
   
   /* Check throw specifier is subset.  */
-  /* XXX At the moment, punt on an overriding artificial function. We
-     don't generate its exception specifier, so can't check it properly.  */
+  /* XXX At the moment, punt with artificial functions. We
+     don't generate their exception specifiers, so can't check properly.  */
   if (! DECL_ARTIFICIAL (overrider)
       && !comp_except_specs (base_throw, over_throw, 0))
     {
-      cp_error_at ("looser throw specifier for `virtual %#F'", overrider);
-      cp_error_at ("  overriding `virtual %#F'", basefn);
+      cp_error_at ("looser throw specifier for `%#F'", overrider);
+      cp_error_at ("  overriding `%#F'", basefn);
       return 0;
     }
   return 1;
 }
 
-/* Given a class type TYPE, and a function decl FNDECL, look for a
-   virtual function in TYPE's hierarchy which FNDECL could match as a
-   virtual function.  It doesn't matter which one we find.
-
-   DTORP is nonzero if we are looking for a destructor.  Destructors
-   need special treatment because they do not match by name.  */
+/* Given a class TYPE, and a function decl FNDECL, look for
+   virtual functions in TYPE's hierarchy which FNDECL overrides.
+   We do not look in TYPE itself, only its bases.
+   
+   Returns non-zero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
+   find that it overrides anything.
+   
+   We check that every function which is overridden, is correctly
+   overridden.  */
 
-tree
-get_matching_virtual (binfo, fndecl, dtorp)
-     tree binfo, fndecl;
-     int dtorp;
+int
+look_for_overrides (type, fndecl)
+     tree type, fndecl;
 {
-  tree tmp = NULL_TREE;
+  tree binfo = TYPE_BINFO (type);
+  tree basebinfos = BINFO_BASETYPES (binfo);
+  int nbasebinfos = basebinfos ? TREE_VEC_LENGTH (basebinfos) : 0;
+  int ix;
+  int found = 0;
 
-  if (TREE_CODE (fndecl) == TEMPLATE_DECL)
-    /* In [temp.mem] we have:
+  for (ix = 0; ix != nbasebinfos; ix++)
+    {
+      tree basetype = BINFO_TYPE (TREE_VEC_ELT (basebinfos, ix));
+      
+      if (TYPE_POLYMORPHIC_P (basetype))
+        found += look_for_overrides_r (basetype, fndecl);
+    }
+  return found;
+}
 
-         A specialization of a member function template does not
-         override a virtual function from a base class.  */
-    return NULL_TREE;
+/* Look in TYPE for virtual functions overridden by FNDECL. Check both
+   TYPE itself and its bases. */
 
-  /* Breadth first search routines start searching basetypes
-     of TYPE, so we must perform first ply of search here.  */
-  if (dtorp)
-    return bfs_walk (binfo, get_virtual_destructor,
-                    tree_has_any_destructor_p, 0);
+static int
+look_for_overrides_r (type, fndecl)
+     tree type, fndecl;
+{
+  int ix;
+  
+  if (DECL_DESTRUCTOR_P (fndecl))
+    ix = CLASSTYPE_DESTRUCTOR_SLOT;
   else
+    ix = lookup_fnfields_here (type, DECL_NAME (fndecl));
+  if (ix >= 0)
     {
-      tree drettype, dtypes, btypes, instptr_type;
-      tree baselink, best = NULL_TREE;
-      tree declarator = DECL_NAME (fndecl);
-      if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
-       return NULL_TREE;
-
-      baselink = get_virtuals_named_this (binfo, declarator);
-      if (baselink == NULL_TREE)
-       return NULL_TREE;
-
-      drettype = TREE_TYPE (TREE_TYPE (fndecl));
-      dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-      if (DECL_STATIC_FUNCTION_P (fndecl))
-       instptr_type = NULL_TREE;
-      else
-       instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
-
-      for (; baselink; baselink = next_baselink (baselink))
-       {
-         tree tmps;
-         for (tmps = TREE_VALUE (baselink); tmps; tmps = OVL_NEXT (tmps))
+      tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
+      tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+      tree thistype = DECL_STATIC_FUNCTION_P (fndecl)
+                      ? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes));
+  
+      for (; fns; fns = OVL_NEXT (fns))
+        {
+          tree fn = OVL_CURRENT (fns);
+          tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+          
+          if (!DECL_VIRTUAL_P (fn))
+            ;
+         else if (thistype == NULL_TREE)
            {
-             tmp = OVL_CURRENT (tmps);
-             if (! DECL_VINDEX (tmp))
-               continue;
-
-             btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
-             if (instptr_type == NULL_TREE)
-               {
-                 if (compparms (TREE_CHAIN (btypes), dtypes))
-                   /* Caller knows to give error in this case.  */
-                   return tmp;
-                 return NULL_TREE;
-               }
-
-             if (/* The first parameter is the `this' parameter,
-                    which has POINTER_TYPE, and we can therefore
-                    safely use TYPE_QUALS, rather than
+             if (compparms (TREE_CHAIN (btypes), dtypes))
+                {
+                  /* A static member function cannot match an inherited
+                     virtual member function.  */
+                  cp_error_at ("`%#D' cannot be declared", fndecl);
+                  cp_error_at ("  since `%#D' declared in base class", fn);
+                  return 1;
+                }
+            }
+          else
+            {
+              if (/* The first parameter is the `this' parameter,
+                    which has POINTER_TYPE, and we can therefore
+                    safely use TYPE_QUALS, rather than
                     CP_TYPE_QUALS.  */
-                 (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes)))
-                  == TYPE_QUALS (instptr_type))
-                 && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
-               {
-                 check_final_overrider (fndecl, tmp);
-
-                 /* FNDECL overrides this function.  We continue to
-                    check all the other functions in order to catch
-                    errors; it might be that in some other baseclass
-                    a virtual function was declared with the same
-                    parameter types, but a different return type.  */
-                 best = tmp;
-               }
+                 (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes)))
+                  == TYPE_QUALS (thistype))
+                 && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
+                {
+                  /* It's definitely virtual, even if not explicitly set.  */
+                  DECL_VIRTUAL_P (fndecl) = 1;
+                 check_final_overrider (fndecl, fn);
+             
+                 return 1;
+               }
            }
        }
-
-      return best;
     }
+  /* We failed to find one declared in this class. Look in its bases.  */
+  return look_for_overrides (type, fndecl);
 }
 
 /* A queue function for dfs_walk that skips any nonprimary virtual
@@ -2320,23 +2239,6 @@ get_pure_virtuals (type)
        }
     }
 }
-
-static tree
-next_baselink (baselink)
-     tree baselink;
-{
-  tree tmp = TREE_TYPE (baselink);
-  baselink = TREE_CHAIN (baselink);
-  while (tmp)
-    {
-      /* @@ does not yet add previous base types.  */
-      baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp),
-                           baselink);
-      TREE_TYPE (baselink) = TREE_TYPE (tmp);
-      tmp = TREE_CHAIN (tmp);
-    }
-  return baselink;
-}
 \f
 /* DEPTH-FIRST SEARCH ROUTINES.  */
 
index 54d8296..be99b99 100644 (file)
@@ -1,5 +1,10 @@
 2000-12-05  Nathan Sidwell  <nathan@codesourcery.com>
 
+       * g++.old-deja/g++.h/spec6.C: Remove some of the XFAILS.
+       * g++.old-deja/g++.other/virtual10.C: New test.
+
+2000-12-05  Nathan Sidwell  <nathan@codesourcery.com>
+
        * g++.old-deja/g++.mike/pmf5.C: Remove test.
 
 2000-12-05  Richard Henderson  <rth@redhat.com>
index 2dfc5d6..b6cd06a 100644 (file)
@@ -92,7 +92,7 @@ struct A
   virtual void wobble(int) throw(E *);    // ERROR - overriding 
   virtual void wabble(int) throw(E *);
   virtual void wubble(int) throw(E *, H *);
-  virtual ~A() throw();                   // ERROR - overriding XFAIL
+  virtual ~A() throw();                   // ERROR - overriding
 };
 
 struct B : A
@@ -133,9 +133,7 @@ struct C : A, A1
 
 struct D : A, A1
 {
-  // The xfail here is because we don't have the check in the right place to
-  // catch dtor failings.
-  virtual ~D() throw(int); // ERROR - looser throw - A::~A() - XFAIL
+  virtual ~D() throw(int); // ERROR - looser throw - A::~A()
 };
 
 // [except.spec] 5, types shall not be defined in exception specifiers
diff --git a/gcc/testsuite/g++.old-deja/g++.other/virtual10.C b/gcc/testsuite/g++.old-deja/g++.other/virtual10.C
new file mode 100644 (file)
index 0000000..020a082
--- /dev/null
@@ -0,0 +1,20 @@
+// Build don't link:
+
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 14 Nov 2000 <nathan@codesourcery.com>
+
+// We failed to spot a static member which overrode a virtual
+
+struct A
+{
+  virtual int foo (char);
+  static int foo ();
+  virtual int foo (int);    // ERROR - this function
+  static int foo (float);
+  virtual int foo (double);
+};
+
+struct B : A
+{
+  static int foo (int);   // ERROR - cannot override
+};