cp-tree.h (binfo_from_vbase): Return the virtual base's binfo.
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 27 Nov 2000 10:55:32 +0000 (10:55 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 27 Nov 2000 10:55:32 +0000 (10:55 +0000)
cp:
* cp-tree.h (binfo_from_vbase): Return the virtual base's binfo.
* cvt.c (cp_convert_to_pointer): Add force parameter.
Allow conversions via virtual base if forced.
(convert_to_pointer_force): Adjust call to cp_convert_to_pointer.
(ocp_convert): Likewise.
* search.c (binfo_from_vbase): Return the virtual base's binfo.
* typeck.c (get_delta_difference): Adjust handling of virtual
bases.
testsuite:
* g++.old-deja/g++.other/ptrmem8.C: New test.

From-SVN: r37791

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/search.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/ptrmem8.C [new file with mode: 0644]

index 7b36db17751cf532e6f259d77e982c6687786003..f2b1adc92ec094d05424663f2b9c506bec03ea7d 100644 (file)
@@ -1,3 +1,14 @@
+2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * cp-tree.h (binfo_from_vbase): Return the virtual base's binfo.
+       * cvt.c (cp_convert_to_pointer): Add force parameter.
+       Allow conversions via virtual base if forced.
+       (convert_to_pointer_force): Adjust call to cp_convert_to_pointer.
+       (ocp_convert): Likewise.
+       * search.c (binfo_from_vbase): Return the virtual base's binfo.
+       * typeck.c (get_delta_difference): Adjust handling of virtual
+       bases.
+
 2000-11-26  Mark Mitchell  <mark@codesourcery.com>
 
        * tree.c (struct list_hash): Remove.
index ed233a2e92a4c31c336ac76b9002d3b85e7263b3..ab10f46c2ec714cc5f00a2d901ea153d71a284bc 100644 (file)
@@ -4265,7 +4265,7 @@ extern tree current_scope                 PARAMS ((void));
 extern int at_function_scope_p                  PARAMS ((void));
 extern tree lookup_conversions                 PARAMS ((tree));
 extern tree binfo_for_vtable                   PARAMS ((tree));
-extern int  binfo_from_vbase                   PARAMS ((tree));
+extern tree binfo_from_vbase                   PARAMS ((tree));
 extern tree dfs_walk                            PARAMS ((tree,
                                                       tree (*)(tree, void *),
                                                       tree (*) (tree, void *),
index 606f854269e2d30665d6fd044d31015b6ffd2ebc..fe99c8f566e914ac8316cd14ae69ce4e0bf7c577 100644 (file)
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "decl.h"
 
-static tree cp_convert_to_pointer PARAMS ((tree, tree));
+static tree cp_convert_to_pointer PARAMS ((tree, tree, int));
 static tree convert_to_pointer_force PARAMS ((tree, tree));
 static tree build_up_reference PARAMS ((tree, tree, int));
 static void warn_ref_binding PARAMS ((tree, tree, tree));
@@ -67,11 +67,14 @@ static void warn_ref_binding PARAMS ((tree, tree, tree));
      else if dealing with method pointers, delegate
      else convert blindly
    else if converting class, pass off to build_type_conversion
-   else try C-style pointer conversion  */
+   else try C-style pointer conversion.  If FORCE is true then allow
+   conversions via virtual bases (these are permitted by reinterpret_cast,
+   but not static_cast).  */
 
 static tree
-cp_convert_to_pointer (type, expr)
+cp_convert_to_pointer (type, expr, force)
      tree type, expr;
+     int force;
 {
   register tree intype = TREE_TYPE (expr);
   register enum tree_code form;
@@ -184,6 +187,7 @@ cp_convert_to_pointer (type, expr)
          tree b1; 
          tree b2;
          tree binfo;
+         tree virt_binfo;
          enum tree_code code;
 
          b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
@@ -201,11 +205,21 @@ cp_convert_to_pointer (type, expr)
          if (binfo == error_mark_node)
            return error_mark_node;
 
-         if (binfo_from_vbase (binfo))
+          virt_binfo = binfo_from_vbase (binfo);
+          if (virt_binfo)
            {
-             cp_error ("conversion to `%T' from pointer to member of virtual base `%T'",
-                       type, intype);
-             return error_mark_node;
+             if (force)
+               cp_warning ("pointer to member cast via virtual base `%T' of `%T' will only work for objects of dynamic type `%T'",
+                           BINFO_TYPE (virt_binfo),
+                            BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)),
+                            code == MINUS_EXPR ? b2 : b1);
+              else
+                {
+                 cp_error ("pointer to member cast via virtual base `%T' of `%T'",
+                           BINFO_TYPE (virt_binfo),
+                            BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+                 return error_mark_node;
+               }
            }
              
          if (TREE_CODE (expr) == PTRMEM_CST)
@@ -334,7 +348,7 @@ convert_to_pointer_force (type, expr)
        }
     }
 
-  return cp_convert_to_pointer (type, expr);
+  return cp_convert_to_pointer (type, expr, 1);
 }
 
 /* We are passing something to a function which requires a reference.
@@ -777,7 +791,7 @@ ocp_convert (type, expr, convtype, flags)
     }
   if (code == POINTER_TYPE || code == REFERENCE_TYPE
       || TYPE_PTRMEMFUNC_P (type))
-    return fold (cp_convert_to_pointer (type, e));
+    return fold (cp_convert_to_pointer (type, e, 0));
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
       if (IS_AGGR_TYPE (TREE_TYPE (e)))
index a7fdc86888b3b46fad255ce46c7a80cae4083817..ae1d64895ed152ad2f3518d4c7f6aaae965a583e 100644 (file)
@@ -3362,18 +3362,19 @@ binfo_for_vtable (var)
   return binfo;
 }
 
-/* Returns 1 iff BINFO is from a direct or indirect virtual base.  */
+/* Returns the binfo of the first direct or indirect virtual base from
+   which BINFO is derrived, or NULL if binfo is not via virtual.  */
 
-int
+tree
 binfo_from_vbase (binfo)
      tree binfo;
 {
   for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
     {
       if (TREE_VIA_VIRTUAL (binfo))
-       return 1;
+       return binfo;
     }
-  return 0;
+  return NULL_TREE;
 }
 
 /* Returns the BINFO (if any) for the virtual baseclass T of the class
index d0ca2bbcb28696be6538a7caa05f9a73fc815841..39f8b54515ee1321337d427d5df8554e07625e91 100644 (file)
@@ -5912,6 +5912,7 @@ get_delta_difference (from, to, force)
 {
   tree delta = integer_zero_node;
   tree binfo;
+  tree virt_binfo;
   
   if (to == from)
     return delta;
@@ -5937,11 +5938,12 @@ get_delta_difference (from, to, force)
       binfo = get_binfo (to, from, 1);
       if (binfo == 0 || binfo == error_mark_node)
        return delta;
-      if (binfo_from_vbase (binfo))
-       {
-         binfo = binfo_for_vbase (BINFO_TYPE (binfo), from);
-         cp_warning ("pointer to member cast to virtual base `%T' will only work if you are very careful", BINFO_TYPE (binfo));
-       }
+      virt_binfo = binfo_from_vbase (binfo);
+      
+      if (virt_binfo)
+        cp_warning ("pointer to member cast via virtual base `%T' of `%T' will only work for objects of dynamic type `%T'",
+                   BINFO_TYPE (virt_binfo),
+                   BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)), from);
       delta = BINFO_OFFSET (binfo);
       delta = cp_convert (ptrdiff_type_node, delta);
       
@@ -5950,15 +5952,17 @@ get_delta_difference (from, to, force)
                                 delta);
     }
 
-  if (binfo_from_vbase (binfo))
+  virt_binfo = binfo_from_vbase (binfo);
+  if (virt_binfo)
     {
       if (force)
-       {
-         cp_warning ("pointer to member cast from virtual base `%T' will only wokr if you are very careful", BINFO_TYPE (binfo));
-       }
+        cp_warning ("pointer to member cast via virtual base `%T' of `%T' will only work for objects of dynamic type `%T'",
+                    BINFO_TYPE (virt_binfo),
+                    BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)), to);
       else
-       cp_error ("pointer to member conversion from virtual base `%T'",
-                 BINFO_TYPE (binfo));
+       cp_error ("pointer to member conversion via virtual base `%T' of `%T'",
+                 BINFO_TYPE (virt_binfo),
+                  BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
     }
 
   return BINFO_OFFSET (binfo);
index dc86e3872f34965272f2a08e29c50b47d94f991c..1aeaf03a9dd2cbdf154477237bde4ded0a451c27 100644 (file)
@@ -1,3 +1,7 @@
+2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/ptrmem8.C: New test.
+
 2000-11-26  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.c-torture/execute/string-opt-7.c: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/ptrmem8.C b/gcc/testsuite/g++.old-deja/g++.other/ptrmem8.C
new file mode 100644 (file)
index 0000000..f99371a
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 22 Nov 2000 <nathan@codesourcery.com>
+
+// bug 827. We died issuing warnings about dangerous pointer to member
+// conversions.
+
+struct bar
+{
+  int barm;
+    static void a();
+};
+struct filler1 {int fm;};
+struct filler2 {int fm;};
+struct filler3 {int fm;};
+struct filler4 {int fm;};
+
+struct baz : filler1, bar, filler2
+{
+  int bazm;
+};
+
+struct foo : filler3, virtual baz, filler4
+{
+    static void a();
+    void b() {};
+    int m;
+};
+
+typedef void (bar::*barfPtr)();
+typedef void (foo::*foofPtr)();
+typedef int bar::*barmPtr;
+typedef int foo::*foomPtr;
+
+int main ()
+{
+  foofPtr fp = &foo::b;
+  barfPtr bp = (barfPtr)fp;         // WARNING - pointer to member
+  foofPtr fp2 = (foofPtr)bp;        // WARNING - pointer to member
+  
+  if (fp2 != fp)
+    return 1;
+  
+  foo fobj;
+  fobj.filler1::fm = 1;
+  fobj.filler2::fm = 2;
+  fobj.filler3::fm = 3;
+  fobj.filler4::fm = 4;
+  fobj.bazm = 5;
+  fobj.barm = 6;
+  fobj.m = 78;
+  
+  foomPtr fmp = &foo::m;
+  barmPtr bmp = (barmPtr)fmp;          // WARNING - pointer to member
+  foomPtr fmp2 = (foomPtr)bmp;         // WARNING - pointer to member
+  bar *bptr = &fobj;
+  
+  if (fmp != fmp2)
+    return 2;
+  
+  if (bptr->*bmp != 78)
+    return 3;
+  
+  bp = reinterpret_cast <barfPtr> (fp);
+  fp2 = reinterpret_cast <foofPtr> (bp);
+  if (fp2 != fp)
+    return 4;
+  
+  bmp = reinterpret_cast <barmPtr> (fmp);
+  fmp2 = reinterpret_cast <foomPtr> (bmp);
+  if (fmp != fmp2)
+    return 5;
+  
+  return 0;
+}