mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
e27d6202c0
commit
34b5375fae
|
|
@ -1,3 +1,21 @@
|
|||
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>
|
||||
Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
|
|
|
|||
|
|
@ -169,8 +169,8 @@ static struct z_candidate *add_conv_candidate
|
|||
(struct z_candidate **, tree, tree, tree, tree, tree);
|
||||
static struct z_candidate *add_function_candidate
|
||||
(struct z_candidate **, tree, tree, tree, tree, tree, int);
|
||||
static conversion *implicit_conversion (tree, tree, tree, int);
|
||||
static conversion *standard_conversion (tree, tree, tree, int);
|
||||
static conversion *implicit_conversion (tree, tree, tree, bool, int);
|
||||
static conversion *standard_conversion (tree, tree, tree, bool, int);
|
||||
static conversion *reference_binding (tree, tree, tree, int);
|
||||
static conversion *build_conv (conversion_kind, tree, conversion *);
|
||||
static bool is_subseq (conversion *, conversion *);
|
||||
|
|
@ -578,10 +578,12 @@ strip_top_quals (tree t)
|
|||
|
||||
/* Returns the standard conversion path (see [conv]) from type FROM to type
|
||||
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 *
|
||||
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;
|
||||
conversion *conv;
|
||||
|
|
@ -631,7 +633,7 @@ standard_conversion (tree to, tree from, tree expr, int flags)
|
|||
the standard conversion sequence to perform componentwise
|
||||
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)
|
||||
{
|
||||
|
|
@ -737,7 +739,12 @@ standard_conversion (tree to, tree from, tree expr, int flags)
|
|||
|
||||
if (same_type_p (from, to))
|
||||
/* 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);
|
||||
else if (expr && string_conv_p (to, expr, 0))
|
||||
/* converting from string constant to char *. */
|
||||
|
|
@ -1197,7 +1204,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
|
|||
if (related_p && !at_least_as_qualified_p (to, from))
|
||||
return NULL;
|
||||
|
||||
conv = implicit_conversion (to, from, expr, flags);
|
||||
conv = implicit_conversion (to, from, expr, /*c_cast_p=*/false,
|
||||
flags);
|
||||
if (!conv)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -1209,13 +1217,15 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
|
|||
return conv;
|
||||
}
|
||||
|
||||
/* Returns the implicit conversion sequence (see [over.ics]) from type FROM
|
||||
to type TO. The optional expression EXPR may affect the conversion.
|
||||
FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is
|
||||
significant. */
|
||||
/* Returns the implicit conversion sequence (see [over.ics]) from type
|
||||
FROM to type TO. The optional expression EXPR may affect the
|
||||
conversion. FLAGS are the usual overloading flags. Only
|
||||
LOOKUP_NO_CONVERSION is significant. If C_CAST_P is true, this
|
||||
conversion is coming from a C-style cast. */
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -1226,7 +1236,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
|
|||
if (TREE_CODE (to) == REFERENCE_TYPE)
|
||||
conv = reference_binding (to, from, expr, flags);
|
||||
else
|
||||
conv = standard_conversion (to, from, expr, flags);
|
||||
conv = standard_conversion (to, from, expr, c_cast_p, flags);
|
||||
|
||||
if (conv)
|
||||
return conv;
|
||||
|
|
@ -1383,7 +1393,8 @@ add_function_candidate (struct z_candidate **candidates,
|
|||
parmtype = build_pointer_type (parmtype);
|
||||
}
|
||||
|
||||
t = implicit_conversion (parmtype, argtype, arg, flags);
|
||||
t = implicit_conversion (parmtype, argtype, arg,
|
||||
/*c_cast_p=*/false, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1456,11 +1467,13 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
|
|||
conversion *t;
|
||||
|
||||
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)
|
||||
break;
|
||||
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
|
||||
{
|
||||
t = build_identity_conv (argtype, arg);
|
||||
|
|
@ -1514,7 +1527,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
|
|||
if (! args[i])
|
||||
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)
|
||||
{
|
||||
viable = 0;
|
||||
|
|
@ -1531,7 +1545,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
|
|||
{
|
||||
convs[2] = convs[1];
|
||||
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)
|
||||
convs[0] = t;
|
||||
else
|
||||
|
|
@ -2590,7 +2605,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
|
|||
conversion *ics
|
||||
= implicit_conversion (totype,
|
||||
TREE_TYPE (TREE_TYPE (cand->fn)),
|
||||
0, convflags);
|
||||
0,
|
||||
/*c_cast_p=*/false, convflags);
|
||||
|
||||
cand->second_conv = ics;
|
||||
|
||||
|
|
@ -3060,6 +3076,7 @@ conditional_conversion (tree e1, tree e2)
|
|||
conv = implicit_conversion (build_reference_type (t2),
|
||||
t1,
|
||||
e1,
|
||||
/*c_cast_p=*/false,
|
||||
LOOKUP_NO_TEMP_BIND);
|
||||
if (conv)
|
||||
return conv;
|
||||
|
|
@ -3097,7 +3114,8 @@ conditional_conversion (tree e1, tree e2)
|
|||
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 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
|
||||
|
|
@ -6271,7 +6289,8 @@ can_convert_arg (tree to, tree from, tree arg)
|
|||
/* Get the high-water mark for the CONVERSION_OBSTACK. */
|
||||
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);
|
||||
|
||||
/* Free all the conversions we allocated. */
|
||||
|
|
@ -6291,7 +6310,8 @@ can_convert_arg_bad (tree to, tree from, tree arg)
|
|||
/* Get the high-water mark for the CONVERSION_OBSTACK. */
|
||||
p = conversion_obstack_alloc (0);
|
||||
/* 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. */
|
||||
obstack_free (&conversion_obstack, p);
|
||||
|
||||
|
|
@ -6317,6 +6337,7 @@ perform_implicit_conversion (tree type, tree expr)
|
|||
p = conversion_obstack_alloc (0);
|
||||
|
||||
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
|
||||
/*c_cast_p=*/false,
|
||||
LOOKUP_NORMAL);
|
||||
if (!conv)
|
||||
{
|
||||
|
|
@ -6370,6 +6391,7 @@ perform_direct_initialization_if_possible (tree type,
|
|||
p = conversion_obstack_alloc (0);
|
||||
|
||||
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
|
||||
c_cast_p,
|
||||
LOOKUP_NORMAL);
|
||||
if (!conv || conv->bad_p)
|
||||
expr = NULL_TREE;
|
||||
|
|
|
|||
|
|
@ -4289,6 +4289,7 @@ extern tree build_modify_expr (tree, enum tree_code, tree);
|
|||
extern tree convert_for_initialization (tree, tree, tree, int,
|
||||
const char *, tree, int);
|
||||
extern int comp_ptr_ttypes (tree, tree);
|
||||
extern bool comp_ptr_ttypes_const (tree, tree);
|
||||
extern int ptr_reasonably_similar (tree, tree);
|
||||
extern tree build_ptrmemfunc (tree, tree, int, bool);
|
||||
extern int cp_type_quals (tree);
|
||||
|
|
|
|||
|
|
@ -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 rationalize_conditional_expr (enum tree_code, tree);
|
||||
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_array_types (tree, tree, bool);
|
||||
static tree common_base_type (tree, tree);
|
||||
|
|
@ -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)
|
||||
{
|
||||
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
|
||||
{
|
||||
if (TREE_CODE (to) != TREE_CODE (from))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (TREE_CODE (from) == OFFSET_TYPE
|
||||
&& same_type_p (TYPE_OFFSET_BASETYPE (from),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* gcc.dg/tree-ssa/flatten-1.c: New testcase.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// { 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 ();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue