Commit f9825168 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 6b2adea9
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> 2000-11-26 Mark Mitchell <mark@codesourcery.com>
* tree.c (struct list_hash): Remove. * tree.c (struct list_hash): Remove.
......
...@@ -4265,7 +4265,7 @@ extern tree current_scope PARAMS ((void)); ...@@ -4265,7 +4265,7 @@ extern tree current_scope PARAMS ((void));
extern int at_function_scope_p PARAMS ((void)); extern int at_function_scope_p PARAMS ((void));
extern tree lookup_conversions PARAMS ((tree)); extern tree lookup_conversions PARAMS ((tree));
extern tree binfo_for_vtable 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, extern tree dfs_walk PARAMS ((tree,
tree (*)(tree, void *), tree (*)(tree, void *),
tree (*) (tree, void *), tree (*) (tree, void *),
......
...@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h" #include "toplev.h"
#include "decl.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 convert_to_pointer_force PARAMS ((tree, tree));
static tree build_up_reference PARAMS ((tree, tree, int)); static tree build_up_reference PARAMS ((tree, tree, int));
static void warn_ref_binding PARAMS ((tree, tree, tree)); static void warn_ref_binding PARAMS ((tree, tree, tree));
...@@ -67,11 +67,14 @@ 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 if dealing with method pointers, delegate
else convert blindly else convert blindly
else if converting class, pass off to build_type_conversion 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 static tree
cp_convert_to_pointer (type, expr) cp_convert_to_pointer (type, expr, force)
tree type, expr; tree type, expr;
int force;
{ {
register tree intype = TREE_TYPE (expr); register tree intype = TREE_TYPE (expr);
register enum tree_code form; register enum tree_code form;
...@@ -184,6 +187,7 @@ cp_convert_to_pointer (type, expr) ...@@ -184,6 +187,7 @@ cp_convert_to_pointer (type, expr)
tree b1; tree b1;
tree b2; tree b2;
tree binfo; tree binfo;
tree virt_binfo;
enum tree_code code; enum tree_code code;
b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
...@@ -201,11 +205,21 @@ cp_convert_to_pointer (type, expr) ...@@ -201,11 +205,21 @@ cp_convert_to_pointer (type, expr)
if (binfo == error_mark_node) if (binfo == error_mark_node)
return 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'", if (force)
type, intype); cp_warning ("pointer to member cast via virtual base `%T' of `%T' will only work for objects of dynamic type `%T'",
return error_mark_node; 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) if (TREE_CODE (expr) == PTRMEM_CST)
...@@ -334,7 +348,7 @@ convert_to_pointer_force (type, expr) ...@@ -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. /* We are passing something to a function which requires a reference.
...@@ -777,7 +791,7 @@ ocp_convert (type, expr, convtype, flags) ...@@ -777,7 +791,7 @@ ocp_convert (type, expr, convtype, flags)
} }
if (code == POINTER_TYPE || code == REFERENCE_TYPE if (code == POINTER_TYPE || code == REFERENCE_TYPE
|| TYPE_PTRMEMFUNC_P (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 (code == REAL_TYPE || code == COMPLEX_TYPE)
{ {
if (IS_AGGR_TYPE (TREE_TYPE (e))) if (IS_AGGR_TYPE (TREE_TYPE (e)))
......
...@@ -3362,18 +3362,19 @@ binfo_for_vtable (var) ...@@ -3362,18 +3362,19 @@ binfo_for_vtable (var)
return binfo; 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) binfo_from_vbase (binfo)
tree binfo; tree binfo;
{ {
for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo)) for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
{ {
if (TREE_VIA_VIRTUAL (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 /* Returns the BINFO (if any) for the virtual baseclass T of the class
......
...@@ -5912,6 +5912,7 @@ get_delta_difference (from, to, force) ...@@ -5912,6 +5912,7 @@ get_delta_difference (from, to, force)
{ {
tree delta = integer_zero_node; tree delta = integer_zero_node;
tree binfo; tree binfo;
tree virt_binfo;
if (to == from) if (to == from)
return delta; return delta;
...@@ -5937,11 +5938,12 @@ get_delta_difference (from, to, force) ...@@ -5937,11 +5938,12 @@ get_delta_difference (from, to, force)
binfo = get_binfo (to, from, 1); binfo = get_binfo (to, from, 1);
if (binfo == 0 || binfo == error_mark_node) if (binfo == 0 || binfo == error_mark_node)
return delta; return delta;
if (binfo_from_vbase (binfo)) virt_binfo = binfo_from_vbase (binfo);
{
binfo = binfo_for_vbase (BINFO_TYPE (binfo), from); if (virt_binfo)
cp_warning ("pointer to member cast to virtual base `%T' will only work 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)), from);
delta = BINFO_OFFSET (binfo); delta = BINFO_OFFSET (binfo);
delta = cp_convert (ptrdiff_type_node, delta); delta = cp_convert (ptrdiff_type_node, delta);
...@@ -5950,15 +5952,17 @@ get_delta_difference (from, to, force) ...@@ -5950,15 +5952,17 @@ get_delta_difference (from, to, force)
delta); delta);
} }
if (binfo_from_vbase (binfo)) virt_binfo = binfo_from_vbase (binfo);
if (virt_binfo)
{ {
if (force) if (force)
{ cp_warning ("pointer to member cast via virtual base `%T' of `%T' will only work for objects of dynamic type `%T'",
cp_warning ("pointer to member cast from virtual base `%T' will only wokr if you are very careful", BINFO_TYPE (binfo)); BINFO_TYPE (virt_binfo),
} BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)), to);
else else
cp_error ("pointer to member conversion from virtual base `%T'", cp_error ("pointer to member conversion via virtual base `%T' of `%T'",
BINFO_TYPE (binfo)); BINFO_TYPE (virt_binfo),
BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
} }
return BINFO_OFFSET (binfo); return BINFO_OFFSET (binfo);
......
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> 2000-11-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.c-torture/execute/string-opt-7.c: New test. * gcc.c-torture/execute/string-opt-7.c: New test.
......
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment