aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2000-11-27 10:55:32 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2000-11-27 10:55:32 +0000
commitf98251686f1e33a6698e9d118d7f1c6a600c0c23 (patch)
treea663502c969fdc01fa746da34280a67ac26c0011 /gcc
parent6b2adea9b7def69c83c89a2a957a68583a815728 (diff)
downloadgcc-f98251686f1e33a6698e9d118d7f1c6a600c0c23.zip
gcc-f98251686f1e33a6698e9d118d7f1c6a600c0c23.tar.gz
gcc-f98251686f1e33a6698e9d118d7f1c6a600c0c23.tar.bz2
cp-tree.h (binfo_from_vbase): Return the virtual base's binfo.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.c32
-rw-r--r--gcc/cp/search.c9
-rw-r--r--gcc/cp/typeck.c26
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/ptrmem8.C74
7 files changed, 133 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7b36db1..f2b1adc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ed233a2..ab10f46 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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 *),
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 606f854..fe99c8f 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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)))
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index a7fdc86..ae1d648 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d0ca2bb..39f8b54 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dc86e38..1aeaf03 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..f99371a
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/ptrmem8.C
@@ -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;
+}