Commit 34b5375f by Mark Mitchell Committed by Mark Mitchell

re PR c++/22132 (Wrong code: upcasting a const class pointer to struct the class…

re PR c++/22132 (Wrong code: upcasting a const class pointer to struct the class derives from (C/old-style cast))

	PR c++/22132
	* call.c (implicit_conversion): Add c_cast_p parameter.
	(standard_conversion): Likewise.  Allow conversions between
	differently-qualified pointer types when performing a C-style
	cast.
	(add_function_candidate): Adjust callee.
	(build_builtin_candidate): Likewise.
	(build_user_type_conversion_1): Likewise.
	(conditional_conversion): Likewise.
	(can_convert_arg): Likewise.
	(can_convert_arg_bad): Likewise.
	(perform_implicit_conversion): Likewise.
	* cp-tree.h (comp_ptr_ttypes_const): Declare.
	* typeck.c (comp_ptr_ttypes_const): Give it external linkage.
	Return bool.

	PR c++/22132
	* g++.dg/expr/cast4.C: New test.

From-SVN: r102059
parent e27d6202
2005-07-15 Mark Mitchell <mark@codesourcery.com>
PR c++/22132
* call.c (implicit_conversion): Add c_cast_p parameter.
(standard_conversion): Likewise. Allow conversions between
differently-qualified pointer types when performing a C-style
cast.
(add_function_candidate): Adjust callee.
(build_builtin_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
(conditional_conversion): Likewise.
(can_convert_arg): Likewise.
(can_convert_arg_bad): Likewise.
(perform_implicit_conversion): Likewise.
* cp-tree.h (comp_ptr_ttypes_const): Declare.
* typeck.c (comp_ptr_ttypes_const): Give it external linkage.
Return bool.
2005-07-12 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2005-07-12 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
Nathan Sidwell <nathan@codesourcery.com> Nathan Sidwell <nathan@codesourcery.com>
......
...@@ -169,8 +169,8 @@ static struct z_candidate *add_conv_candidate ...@@ -169,8 +169,8 @@ static struct z_candidate *add_conv_candidate
(struct z_candidate **, tree, tree, tree, tree, tree); (struct z_candidate **, tree, tree, tree, tree, tree);
static struct z_candidate *add_function_candidate static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, tree, tree, int); (struct z_candidate **, tree, tree, tree, tree, tree, int);
static conversion *implicit_conversion (tree, tree, tree, int); static conversion *implicit_conversion (tree, tree, tree, bool, int);
static conversion *standard_conversion (tree, tree, tree, int); static conversion *standard_conversion (tree, tree, tree, bool, int);
static conversion *reference_binding (tree, tree, tree, int); static conversion *reference_binding (tree, tree, tree, int);
static conversion *build_conv (conversion_kind, tree, conversion *); static conversion *build_conv (conversion_kind, tree, conversion *);
static bool is_subseq (conversion *, conversion *); static bool is_subseq (conversion *, conversion *);
...@@ -578,10 +578,12 @@ strip_top_quals (tree t) ...@@ -578,10 +578,12 @@ strip_top_quals (tree t)
/* Returns the standard conversion path (see [conv]) from type FROM to type /* Returns the standard conversion path (see [conv]) from type FROM to type
TO, if any. For proper handling of null pointer constants, you must TO, if any. For proper handling of null pointer constants, you must
also pass the expression EXPR to convert from. */ also pass the expression EXPR to convert from. If C_CAST_P is true,
this conversion is coming from a C-style cast. */
static conversion * static conversion *
standard_conversion (tree to, tree from, tree expr, int flags) standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
int flags)
{ {
enum tree_code fcode, tcode; enum tree_code fcode, tcode;
conversion *conv; conversion *conv;
...@@ -631,7 +633,7 @@ standard_conversion (tree to, tree from, tree expr, int flags) ...@@ -631,7 +633,7 @@ standard_conversion (tree to, tree from, tree expr, int flags)
the standard conversion sequence to perform componentwise the standard conversion sequence to perform componentwise
conversion. */ conversion. */
conversion *part_conv = standard_conversion conversion *part_conv = standard_conversion
(TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, flags); (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags);
if (part_conv) if (part_conv)
{ {
...@@ -737,7 +739,12 @@ standard_conversion (tree to, tree from, tree expr, int flags) ...@@ -737,7 +739,12 @@ standard_conversion (tree to, tree from, tree expr, int flags)
if (same_type_p (from, to)) if (same_type_p (from, to))
/* OK */; /* OK */;
else if (comp_ptr_ttypes (to_pointee, from_pointee)) else if (c_cast_p && comp_ptr_ttypes_const (to, from))
/* In a C-style cast, we ignore CV-qualification because we
are allowed to perform a static_cast followed by a
const_cast. */
conv = build_conv (ck_qual, to, conv);
else if (!c_cast_p && comp_ptr_ttypes (to_pointee, from_pointee))
conv = build_conv (ck_qual, to, conv); conv = build_conv (ck_qual, to, conv);
else if (expr && string_conv_p (to, expr, 0)) else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */ /* converting from string constant to char *. */
...@@ -1197,7 +1204,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) ...@@ -1197,7 +1204,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
if (related_p && !at_least_as_qualified_p (to, from)) if (related_p && !at_least_as_qualified_p (to, from))
return NULL; return NULL;
conv = implicit_conversion (to, from, expr, flags); conv = implicit_conversion (to, from, expr, /*c_cast_p=*/false,
flags);
if (!conv) if (!conv)
return NULL; return NULL;
...@@ -1209,13 +1217,15 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) ...@@ -1209,13 +1217,15 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
return conv; return conv;
} }
/* Returns the implicit conversion sequence (see [over.ics]) from type FROM /* Returns the implicit conversion sequence (see [over.ics]) from type
to type TO. The optional expression EXPR may affect the conversion. FROM to type TO. The optional expression EXPR may affect the
FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is conversion. FLAGS are the usual overloading flags. Only
significant. */ LOOKUP_NO_CONVERSION is significant. If C_CAST_P is true, this
conversion is coming from a C-style cast. */
static conversion * static conversion *
implicit_conversion (tree to, tree from, tree expr, int flags) implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
int flags)
{ {
conversion *conv; conversion *conv;
...@@ -1226,7 +1236,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags) ...@@ -1226,7 +1236,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
if (TREE_CODE (to) == REFERENCE_TYPE) if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags); conv = reference_binding (to, from, expr, flags);
else else
conv = standard_conversion (to, from, expr, flags); conv = standard_conversion (to, from, expr, c_cast_p, flags);
if (conv) if (conv)
return conv; return conv;
...@@ -1383,7 +1393,8 @@ add_function_candidate (struct z_candidate **candidates, ...@@ -1383,7 +1393,8 @@ add_function_candidate (struct z_candidate **candidates,
parmtype = build_pointer_type (parmtype); parmtype = build_pointer_type (parmtype);
} }
t = implicit_conversion (parmtype, argtype, arg, flags); t = implicit_conversion (parmtype, argtype, arg,
/*c_cast_p=*/false, flags);
} }
else else
{ {
...@@ -1456,11 +1467,13 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, ...@@ -1456,11 +1467,13 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
conversion *t; conversion *t;
if (i == 0) if (i == 0)
t = implicit_conversion (totype, argtype, arg, flags); t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
flags);
else if (parmnode == void_list_node) else if (parmnode == void_list_node)
break; break;
else if (parmnode) else if (parmnode)
t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg,
/*c_cast_p=*/false, flags);
else else
{ {
t = build_identity_conv (argtype, arg); t = build_identity_conv (argtype, arg);
...@@ -1514,7 +1527,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, ...@@ -1514,7 +1527,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
if (! args[i]) if (! args[i])
break; break;
t = implicit_conversion (types[i], argtypes[i], args[i], flags); t = implicit_conversion (types[i], argtypes[i], args[i],
/*c_cast_p=*/false, flags);
if (! t) if (! t)
{ {
viable = 0; viable = 0;
...@@ -1531,7 +1545,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, ...@@ -1531,7 +1545,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
{ {
convs[2] = convs[1]; convs[2] = convs[1];
convs[1] = convs[0]; convs[1] = convs[0];
t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); t = implicit_conversion (boolean_type_node, argtypes[2], args[2],
/*c_cast_p=*/false, flags);
if (t) if (t)
convs[0] = t; convs[0] = t;
else else
...@@ -2590,7 +2605,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2590,7 +2605,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
conversion *ics conversion *ics
= implicit_conversion (totype, = implicit_conversion (totype,
TREE_TYPE (TREE_TYPE (cand->fn)), TREE_TYPE (TREE_TYPE (cand->fn)),
0, convflags); 0,
/*c_cast_p=*/false, convflags);
cand->second_conv = ics; cand->second_conv = ics;
...@@ -3060,6 +3076,7 @@ conditional_conversion (tree e1, tree e2) ...@@ -3060,6 +3076,7 @@ conditional_conversion (tree e1, tree e2)
conv = implicit_conversion (build_reference_type (t2), conv = implicit_conversion (build_reference_type (t2),
t1, t1,
e1, e1,
/*c_cast_p=*/false,
LOOKUP_NO_TEMP_BIND); LOOKUP_NO_TEMP_BIND);
if (conv) if (conv)
return conv; return conv;
...@@ -3097,7 +3114,8 @@ conditional_conversion (tree e1, tree e2) ...@@ -3097,7 +3114,8 @@ conditional_conversion (tree e1, tree e2)
Otherwise: E1 can be converted to match E2 if E1 can be implicitly Otherwise: E1 can be converted to match E2 if E1 can be implicitly
converted to the type that expression E2 would have if E2 were converted to the type that expression E2 would have if E2 were
converted to an rvalue (or the type it has, if E2 is an rvalue). */ converted to an rvalue (or the type it has, if E2 is an rvalue). */
return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL); return implicit_conversion (t2, t1, e1, /*c_cast_p=*/false,
LOOKUP_NORMAL);
} }
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three /* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
...@@ -6271,7 +6289,8 @@ can_convert_arg (tree to, tree from, tree arg) ...@@ -6271,7 +6289,8 @@ can_convert_arg (tree to, tree from, tree arg)
/* Get the high-water mark for the CONVERSION_OBSTACK. */ /* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); t = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
LOOKUP_NORMAL);
ok_p = (t && !t->bad_p); ok_p = (t && !t->bad_p);
/* Free all the conversions we allocated. */ /* Free all the conversions we allocated. */
...@@ -6291,7 +6310,8 @@ can_convert_arg_bad (tree to, tree from, tree arg) ...@@ -6291,7 +6310,8 @@ can_convert_arg_bad (tree to, tree from, tree arg)
/* Get the high-water mark for the CONVERSION_OBSTACK. */ /* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
/* Try to perform the conversion. */ /* Try to perform the conversion. */
t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); t = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
LOOKUP_NORMAL);
/* Free all the conversions we allocated. */ /* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p); obstack_free (&conversion_obstack, p);
...@@ -6317,6 +6337,7 @@ perform_implicit_conversion (tree type, tree expr) ...@@ -6317,6 +6337,7 @@ perform_implicit_conversion (tree type, tree expr)
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
conv = implicit_conversion (type, TREE_TYPE (expr), expr, conv = implicit_conversion (type, TREE_TYPE (expr), expr,
/*c_cast_p=*/false,
LOOKUP_NORMAL); LOOKUP_NORMAL);
if (!conv) if (!conv)
{ {
...@@ -6370,6 +6391,7 @@ perform_direct_initialization_if_possible (tree type, ...@@ -6370,6 +6391,7 @@ perform_direct_initialization_if_possible (tree type,
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
conv = implicit_conversion (type, TREE_TYPE (expr), expr, conv = implicit_conversion (type, TREE_TYPE (expr), expr,
c_cast_p,
LOOKUP_NORMAL); LOOKUP_NORMAL);
if (!conv || conv->bad_p) if (!conv || conv->bad_p)
expr = NULL_TREE; expr = NULL_TREE;
......
...@@ -4289,6 +4289,7 @@ extern tree build_modify_expr (tree, enum tree_code, tree); ...@@ -4289,6 +4289,7 @@ extern tree build_modify_expr (tree, enum tree_code, tree);
extern tree convert_for_initialization (tree, tree, tree, int, extern tree convert_for_initialization (tree, tree, tree, int,
const char *, tree, int); const char *, tree, int);
extern int comp_ptr_ttypes (tree, tree); extern int comp_ptr_ttypes (tree, tree);
extern bool comp_ptr_ttypes_const (tree, tree);
extern int ptr_reasonably_similar (tree, tree); extern int ptr_reasonably_similar (tree, tree);
extern tree build_ptrmemfunc (tree, tree, int, bool); extern tree build_ptrmemfunc (tree, tree, int, bool);
extern int cp_type_quals (tree); extern int cp_type_quals (tree);
......
...@@ -47,7 +47,6 @@ static tree convert_for_assignment (tree, tree, const char *, tree, int); ...@@ -47,7 +47,6 @@ static tree convert_for_assignment (tree, tree, const char *, tree, int);
static tree cp_pointer_int_sum (enum tree_code, tree, tree); static tree cp_pointer_int_sum (enum tree_code, tree, tree);
static tree rationalize_conditional_expr (enum tree_code, tree); static tree rationalize_conditional_expr (enum tree_code, tree);
static int comp_ptr_ttypes_real (tree, tree, int); static int comp_ptr_ttypes_real (tree, tree, int);
static int comp_ptr_ttypes_const (tree, tree);
static bool comp_except_types (tree, tree, bool); static bool comp_except_types (tree, tree, bool);
static bool comp_array_types (tree, tree, bool); static bool comp_array_types (tree, tree, bool);
static tree common_base_type (tree, tree); static tree common_base_type (tree, tree);
...@@ -6414,15 +6413,17 @@ ptr_reasonably_similar (tree to, tree from) ...@@ -6414,15 +6413,17 @@ ptr_reasonably_similar (tree to, tree from)
} }
} }
/* Like comp_ptr_ttypes, for const_cast. */ /* Return true if TO and FROM (both of which are POINTER_TYPEs or
pointer-to-member types) are the same, ignoring cv-qualification at
all levels. */
static int bool
comp_ptr_ttypes_const (tree to, tree from) comp_ptr_ttypes_const (tree to, tree from)
{ {
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
{ {
if (TREE_CODE (to) != TREE_CODE (from)) if (TREE_CODE (to) != TREE_CODE (from))
return 0; return false;
if (TREE_CODE (from) == OFFSET_TYPE if (TREE_CODE (from) == OFFSET_TYPE
&& same_type_p (TYPE_OFFSET_BASETYPE (from), && same_type_p (TYPE_OFFSET_BASETYPE (from),
......
2005-07-15 Mark Mitchell <mark@codesourcery.com>
PR c++/22132
* g++.dg/expr/cast4.C: New test.
2005-07-15 Richard Guenther <rguenther@suse.de> 2005-07-15 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/flatten-1.c: New testcase. * gcc.dg/tree-ssa/flatten-1.c: New testcase.
......
// { dg-do run }
// PR c++/22132
extern "C" void abort ();
struct foo {
int a;
int b;
};
class Foobar : public foo {
public:
Foobar() { a = 1; b = 2; };
virtual ~Foobar() {};
};
Foobar obj;
const Foobar* objPtr = &obj;
foo* f = (foo*)objPtr;
int main () {
if (f->a != 1 || f->b != 2)
abort ();
}
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