class.c (find_final_overrider_data_s): Remove overriding_fn and overriding_base.
authorMark Mitchell <mark@codesourcery.com>
Fri, 18 Oct 2002 09:21:06 +0000 (09:21 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 18 Oct 2002 09:21:06 +0000 (09:21 +0000)
* class.c (find_final_overrider_data_s): Remove overriding_fn and
overriding_base.
(dfs_base_derived_from): New function.
(base_derived_from): Likewise.
(dfs_find_final_overrider): Use base_derived_from.
(find_final_overrider): Adjust.

* g++.dg/inherit/override1.C: New test.

From-SVN: r58283

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/override1.C [new file with mode: 0644]

index bdceab029c7c965144ab7578b9b2ef1b226eb8a6..ced9a04cfed252b7394db524e10f50d2e96c9ebf 100644 (file)
@@ -1,3 +1,12 @@
+2002-10-18  Mark Mitchell  <mark@codesourcery.com>
+
+       * class.c (find_final_overrider_data_s): Remove overriding_fn and
+       overriding_base.
+       (dfs_base_derived_from): New function.
+       (base_derived_from): Likewise.
+       (dfs_find_final_overrider): Use base_derived_from.
+       (find_final_overrider): Adjust.
+
 2002-10-18  Jason Merrill  <jason@redhat.com>
 
        PR c++/8080
index 7c660980c5774fbd3f1b21bed5e039093bdbdf0b..0434337ea6b526a619b7a5600bcdb6c0c8f2a1aa 100644 (file)
@@ -208,6 +208,8 @@ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
 static void warn_about_ambiguous_bases PARAMS ((tree));
 static bool type_requires_array_cookie PARAMS ((tree));
 static bool contains_empty_class_p (tree);
+static tree dfs_base_derived_from (tree, void *);
+static bool base_derived_from (tree, tree);
 
 /* Macros for dfs walking during vtt construction. See
    dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -2204,6 +2206,29 @@ same_signature_p (fndecl, base_fndecl)
   return 0;
 }
 
+/* Called from base_derived_from via dfs_walk.  */
+
+static tree
+dfs_base_derived_from (tree binfo, void *data)
+{
+  tree base = (tree) data;
+
+  if (same_type_p (TREE_TYPE (base), TREE_TYPE (binfo))
+      && tree_int_cst_equal (BINFO_OFFSET (base), BINFO_OFFSET (binfo)))
+    return error_mark_node;
+
+  return NULL_TREE;
+}
+
+/* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
+   subobject.  */
+static bool
+base_derived_from (tree derived, tree base)
+{
+  return dfs_walk (derived, dfs_base_derived_from, NULL, base);
+}
+
 typedef struct find_final_overrider_data_s {
   /* The function for which we are trying to find a final overrider.  */
   tree fn;
@@ -2211,14 +2236,8 @@ typedef struct find_final_overrider_data_s {
   tree declaring_base;
   /* The most derived class in the hierarchy.  */
   tree most_derived_type;
-  /* The final overriding function.  */
-  tree overriding_fn;
-  /* The functions that we thought might be final overriders, but
-     aren't.  */
+  /* The candidate overriders.  */
   tree candidates;
-  /* The BINFO for the class in which the final overriding function
-     appears.  */
-  tree overriding_base;
 } find_final_overrider_data;
 
 /* Called from find_final_overrider via dfs_walk.  */
@@ -2243,118 +2262,41 @@ dfs_find_final_overrider (binfo, data)
       /* We've found a path to the declaring base.  Walk down the path
         looking for an overrider for FN.  */
       for (path = reverse_path (binfo);
-          path; 
+          path;
           path = TREE_CHAIN (path))
        {
          method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
                                            ffod->fn);
          if (method)
-           break;
+           {
+             path = TREE_VALUE (path);
+             break;
+           }
        }
 
       /* If we found an overrider, record the overriding function, and
         the base from which it came.  */
       if (path)
        {
-         tree base;
-
-         /* Assume the path is non-virtual.  See if there are any
-            virtual bases from (but not including) the overrider up
-            to and including the base where the function is
-            defined.  */
-         for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
-           if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
-             {
-               base = ffod->declaring_base;
-               break;
-             }
+         tree *candidate;
 
-         /* If we didn't already have an overrider, or any
-            candidates, then this function is the best candidate so
-            far.  */
-         if (!ffod->overriding_fn && !ffod->candidates)
+         /* Remove any candidates overridden by this new function.  */
+         candidate = &ffod->candidates;
+         while (*candidate)
            {
-             ffod->overriding_fn = method;
-             ffod->overriding_base = TREE_VALUE (path);
-           }
-         else if (ffod->overriding_fn)
-           {
-             /* We had a best overrider; let's see how this compares.  */
-
-             if (ffod->overriding_fn == method
-                 && (tree_int_cst_equal 
-                     (BINFO_OFFSET (TREE_VALUE (path)),
-                      BINFO_OFFSET (ffod->overriding_base))))
-               /* We found the same overrider we already have, and in the
-                  same place; it's still the best.  */;
-             else if (strictly_overrides (ffod->overriding_fn, method))
-               /* The old function overrides this function; it's still the
-                  best.  */;
-             else if (strictly_overrides (method, ffod->overriding_fn))
-               {
-                 /* The new function overrides the old; it's now the
-                    best.  */
-                 ffod->overriding_fn = method;
-                 ffod->overriding_base = TREE_VALUE (path);
-               }
+             /* If *CANDIDATE overrides METHOD, then METHOD
+                cannot override anything else on the list.  */
+             if (base_derived_from (TREE_VALUE (*candidate), path))
+                 return NULL_TREE;
+             /* If METHOD overrides *CANDIDATE, remove *CANDIDATE.  */
+             if (base_derived_from (path, TREE_VALUE (*candidate)))
+               *candidate = TREE_CHAIN (*candidate);
              else
-               {
-                 /* Ambiguous.  */
-                 ffod->candidates 
-                   = build_tree_list (NULL_TREE,
-                                      ffod->overriding_fn);
-                 if (method != ffod->overriding_fn)
-                   ffod->candidates 
-                     = tree_cons (NULL_TREE, method, ffod->candidates);
-                 ffod->overriding_fn = NULL_TREE;
-                 ffod->overriding_base = NULL_TREE;
-               }
+               candidate = &TREE_CHAIN (*candidate);
            }
-         else
-           {
-             /* We had a list of ambiguous overrides; let's see how this
-                new one compares.  */
-
-             tree candidates;
-             bool incomparable = false;
-
-             /* If there were previous candidates, and this function
-                overrides all of them, then it is the new best
-                candidate.  */
-             for (candidates = ffod->candidates;
-                  candidates;
-                  candidates = TREE_CHAIN (candidates))
-               {
-                 /* If the candidate overrides the METHOD, then we
-                    needn't worry about it any further.  */
-                 if (strictly_overrides (TREE_VALUE (candidates),
-                                         method))
-                   {
-                     method = NULL_TREE;
-                     break;
-                   }
-
-                 /* If the METHOD doesn't override the candidate,
-                    then it is incomporable.  */
-                 if (!strictly_overrides (method,
-                                          TREE_VALUE (candidates)))
-                   incomparable = true;
-               }
 
-             /* If METHOD overrode all the candidates, then it is the
-                new best candidate.  */
-             if (!candidates && !incomparable)
-               {
-                 ffod->overriding_fn = method;
-                 ffod->overriding_base = TREE_VALUE (path);
-                 ffod->candidates = NULL_TREE;
-               }
-             /* If METHOD didn't override all the candidates, then it
-                is another candidate.  */
-             else if (method && incomparable)
-               ffod->candidates 
-                 = tree_cons (NULL_TREE, method, ffod->candidates);
-           }
+         /* Add the new function.  */
+         ffod->candidates = tree_cons (method, path, ffod->candidates);
        }
     }
 
@@ -2395,8 +2337,6 @@ find_final_overrider (t, binfo, fn)
   ffod.fn = fn;
   ffod.declaring_base = binfo;
   ffod.most_derived_type = t;
-  ffod.overriding_fn = NULL_TREE;
-  ffod.overriding_base = NULL_TREE;
   ffod.candidates = NULL_TREE;
 
   dfs_walk (TYPE_BINFO (t),
@@ -2405,13 +2345,13 @@ find_final_overrider (t, binfo, fn)
            &ffod);
 
   /* If there was no winner, issue an error message.  */
-  if (!ffod.overriding_fn)
+  if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
     {
       error ("no unique final overrider for `%D' in `%T'", fn, t);
       return error_mark_node;
     }
 
-  return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
+  return ffod.candidates;
 }
 
 /* Returns the function from the BINFO_VIRTUALS entry in T which matches
index 20fda9f5999cd014740d3dbc30dd6cb8ffe59c39..9c16af2cd475026295b437b4271b261b397a5219 100644 (file)
@@ -1,3 +1,11 @@
+2002-10-18  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/inherit/override1.C: New test.
+
+       * g++.dg/abi/mangle11.C: New test.
+       * g++.dg/abi/mangle14.C: New test.
+       * g++.dg/abi/mangle17.C: New test.
+
 2002-10-17  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/overload/member2.C: New test.
diff --git a/gcc/testsuite/g++.dg/inherit/override1.C b/gcc/testsuite/g++.dg/inherit/override1.C
new file mode 100644 (file)
index 0000000..04460ed
--- /dev/null
@@ -0,0 +1,18 @@
+struct c0 { virtual void f (); };
+struct c1 : public c0 {};
+struct c2 : public c0 {};
+struct c3 : virtual public c0, public c1, public c2 {};
+struct c5 {};
+struct c7 : virtual public c3 {};
+struct c8 : virtual public c1 { virtual void f (); };
+struct c9 {};
+struct c10 : virtual public c8, virtual public c7 {};
+struct c11 : virtual public c5 {};
+struct c12 : virtual public c8, public c7 {};
+struct c13 : public c9, public c3, virtual public c2 {};
+struct c14 : virtual public c1, virtual public c5, virtual public c0,
+            public c2 {};
+struct c15 : public c14, public c12, virtual public c3 {};
+struct c16 : public c12, public c10, public c2 { virtual void f (); };
+struct c17 : virtual public c13, public c15, virtual public c0,
+            virtual public c16 {};