aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-15 16:10:05 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-15 16:10:05 +0000
commit8de1f703dfcbb8740f3ed1d13b8357dde37c1c69 (patch)
tree59867dcc10601c3cce82c828262ad523c4dfee3a
parent581d57e6c0faef95b511984510372d09ca55210c (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102059 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/call.c66
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/typeck.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/expr/cast4.C25
6 files changed, 98 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ac9f3b46e4a..a52464a20e4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 382d6ea8e8b..1035f88441a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index db70017f5d2..440bdff1c6b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index c6989ee6832..b13c8cf6264 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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),
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6bef685f53d..4787bccf5b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/expr/cast4.C b/gcc/testsuite/g++.dg/expr/cast4.C
new file mode 100644
index 00000000000..72be9a6af19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cast4.C
@@ -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 ();
+}
+