Commit 33c25e5c by Mark Mitchell Committed by Mark Mitchell

call.c (struct conversion): Add base_p.

	* call.c (struct conversion): Add base_p.
	(convert_like): Add c_cast_p argument.
	(convert_like_with_conversion): Likewise.
	(build_conv): Clear base_p.
	(standard_conversion): Set it, for derived-to-base conversions.
	(convert_like_real): Add c_cast_p parameter.  Handle pointer
	conversions directly rather than relying on ocp_convert.
	(perform_direct_initialization_if_possible): Add c_cast_p
	parameter.
	* cp-tree.h (perform_direct_initialization_if_possible): Change
	prototype.
	(convert_member_func_to_ptr): New function.
	* typeck.c (check_for_casting_away_constness): Add diag_fn
	parameter.
	(build_static_cast_1): New function, split out from ...
	(build_static_cast): ... here.  Use build_static_cast_1.
	(build_reinterpret_cast_1): New function, split out from ...
	(build_reinterpret_cast): ... here.  Use build_reinterpret_cast_1.
	(build_const_cast_1): New function, split out from ...
	(build_const_cast): ... here.  Use build_const_cast_1.
	(build_c_cast): Rewrite to use build_const_cast_1,
	build_static_cast_1, and build_reinterpret_cast_1.
	(convert_member_func_to_ptr): New function.

	* g++.dg/conversion/reinterpret1.C: Adjust error markers.
	* g++.dg/conversion/const2.C: New test.
	* g++.dg/expr/reinterpret2.C: New test.
	* g++.dg/expr/reinterpret3.C: New test.
	* g++.dg/expr/cast2.C: New test.
	* g++.dg/expr/copy1.C: New test.
	* g++.dg/other/conversion1.C: Change error message.
	* g++.dg/parse/comma1.C: Use __extension__ to allow casts from
	function pointers to void *.
	* g++.old-deja/g++.mike/p10148.C: Likewise.

From-SVN: r89300
parent b55d5746
2004-10-19 Mark Mitchell <mark@codesourcery.com>
PR c++/14035
* call.c (struct conversion): Add base_p.
(convert_like): Add c_cast_p argument.
(convert_like_with_conversion): Likewise.
(build_conv): Clear base_p.
(standard_conversion): Set it, for derived-to-base conversions.
(convert_like_real): Add c_cast_p parameter. Handle pointer
conversions directly rather than relying on ocp_convert.
(perform_direct_initialization_if_possible): Add c_cast_p
parameter.
* cp-tree.h (perform_direct_initialization_if_possible): Change
prototype.
(convert_member_func_to_ptr): New function.
* typeck.c (check_for_casting_away_constness): Add diag_fn
parameter.
(build_static_cast_1): New function, split out from ...
(build_static_cast): ... here. Use build_static_cast_1.
(build_reinterpret_cast_1): New function, split out from ...
(build_reinterpret_cast): ... here. Use build_reinterpret_cast_1.
(build_const_cast_1): New function, split out from ...
(build_const_cast): ... here. Use build_const_cast_1.
(build_c_cast): Rewrite to use build_const_cast_1,
build_static_cast_1, and build_reinterpret_cast_1.
(convert_member_func_to_ptr): New function.
2004-10-19 Paolo Bonzini <bonzini@gnu.org> 2004-10-19 Paolo Bonzini <bonzini@gnu.org>
PR c++/18047 PR c++/18047
......
...@@ -92,6 +92,9 @@ struct conversion { ...@@ -92,6 +92,9 @@ struct conversion {
copy constructor must be accessible, even though it is not being copy constructor must be accessible, even though it is not being
used. */ used. */
BOOL_BITFIELD check_copy_constructor_p : 1; BOOL_BITFIELD check_copy_constructor_p : 1;
/* If KIND is ck_ptr, true to indicate that a conversion from a
pointer-to-derived to pointer-to-base is being performed. */
BOOL_BITFIELD base_p : 1;
/* The type of the expression resulting from the conversion. */ /* The type of the expression resulting from the conversion. */
tree type; tree type;
union { union {
...@@ -126,11 +129,14 @@ static tree build_over_call (struct z_candidate *, int); ...@@ -126,11 +129,14 @@ static tree build_over_call (struct z_candidate *, int);
static tree build_java_interface_fn_ref (tree, tree); static tree build_java_interface_fn_ref (tree, tree);
#define convert_like(CONV, EXPR) \ #define convert_like(CONV, EXPR) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \ convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true) /*issue_conversion_warnings=*/true, \
/*c_cast_p=*/false)
#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \ #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \ convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
/*issue_conversion_warnings=*/true) /*issue_conversion_warnings=*/true, \
static tree convert_like_real (conversion *, tree, tree, int, int, bool); /*c_cast_p=*/false)
static tree convert_like_real (conversion *, tree, tree, int, int, bool,
bool);
static void op_error (enum tree_code, enum tree_code, tree, tree, static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, const char *); tree, const char *);
static tree build_object_call (tree, tree); static tree build_object_call (tree, tree);
...@@ -528,6 +534,7 @@ build_conv (conversion_kind code, tree type, conversion *from) ...@@ -528,6 +534,7 @@ build_conv (conversion_kind code, tree type, conversion *from)
t->rank = rank; t->rank = rank;
t->user_conv_p = (code == ck_user || from->user_conv_p); t->user_conv_p = (code == ck_user || from->user_conv_p);
t->bad_p = from->bad_p; t->bad_p = from->bad_p;
t->base_p = false;
return t; return t;
} }
...@@ -721,6 +728,7 @@ standard_conversion (tree to, tree from, tree expr) ...@@ -721,6 +728,7 @@ standard_conversion (tree to, tree from, tree expr)
cp_type_quals (TREE_TYPE (from))); cp_type_quals (TREE_TYPE (from)));
from = build_pointer_type (from); from = build_pointer_type (from);
conv = build_conv (ck_ptr, from, conv); conv = build_conv (ck_ptr, from, conv);
conv->base_p = true;
} }
if (tcode == POINTER_TYPE) if (tcode == POINTER_TYPE)
...@@ -4113,11 +4121,14 @@ build_temp (tree expr, tree type, int flags, ...@@ -4113,11 +4121,14 @@ build_temp (tree expr, tree type, int flags,
being called to continue a conversion chain. It is negative when a being called to continue a conversion chain. It is negative when a
reference binding will be applied, positive otherwise. If reference binding will be applied, positive otherwise. If
ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious
conversions will be emitted if appropriate. */ conversions will be emitted if appropriate. If C_CAST_P is true,
this conversion is coming from a C-style cast; in that case,
conversions to inaccessible bases are permitted. */
static tree static tree
convert_like_real (conversion *convs, tree expr, tree fn, int argnum, convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
int inner, bool issue_conversion_warnings) int inner, bool issue_conversion_warnings,
bool c_cast_p)
{ {
tree totype = convs->type; tree totype = convs->type;
void (*diagnostic_fn)(const char *, ...); void (*diagnostic_fn)(const char *, ...);
...@@ -4133,12 +4144,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -4133,12 +4144,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (t->kind == ck_user || !t->bad_p) if (t->kind == ck_user || !t->bad_p)
{ {
expr = convert_like_real (t, expr, fn, argnum, 1, expr = convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false); /*issue_conversion_warnings=*/false,
/*c_cast_p=*/false);
break; break;
} }
else if (t->kind == ck_ambig) else if (t->kind == ck_ambig)
return convert_like_real (t, expr, fn, argnum, 1, return convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false); /*issue_conversion_warnings=*/false,
/*c_cast_p=*/false);
else if (t->kind == ck_identity) else if (t->kind == ck_identity)
break; break;
} }
...@@ -4237,7 +4250,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -4237,7 +4250,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
expr = convert_like_real (convs->u.next, expr, fn, argnum, expr = convert_like_real (convs->u.next, expr, fn, argnum,
convs->kind == ck_ref_bind ? -1 : 1, convs->kind == ck_ref_bind ? -1 : 1,
/*issue_conversion_warnings=*/false); /*issue_conversion_warnings=*/false,
c_cast_p);
if (expr == error_mark_node) if (expr == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -4322,6 +4336,21 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -4322,6 +4336,21 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
string_conv_p (totype, expr, 1); string_conv_p (totype, expr, 1);
break; break;
case ck_ptr:
if (convs->base_p)
{
tree binfo;
binfo = lookup_base (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (totype),
c_cast_p ? ba_unique : ba_check,
NULL);
if (binfo == error_mark_node)
return error_mark_node;
expr = build_base_path (PLUS_EXPR, expr, binfo, /*nonnull=*/0);
}
return build_nop (totype, expr);
default: default:
break; break;
} }
...@@ -6273,10 +6302,15 @@ perform_implicit_conversion (tree type, tree expr) ...@@ -6273,10 +6302,15 @@ perform_implicit_conversion (tree type, tree expr)
/* Convert EXPR to TYPE (as a direct-initialization) if that is /* Convert EXPR to TYPE (as a direct-initialization) if that is
permitted. If the conversion is valid, the converted expression is permitted. If the conversion is valid, the converted expression is
returned. Otherwise, NULL_TREE is returned, except in the case returned. Otherwise, NULL_TREE is returned, except in the case
that TYPE is a class type; in that case, an error is issued. */ that TYPE is a class type; in that case, an error is issued. If
C_CAST_P is ttrue, then this direction initialization is taking
place as part of a static_cast being attempted as part of a C-style
cast. */
tree tree
perform_direct_initialization_if_possible (tree type, tree expr) perform_direct_initialization_if_possible (tree type,
tree expr,
bool c_cast_p)
{ {
conversion *conv; conversion *conv;
void *p; void *p;
...@@ -6308,7 +6342,8 @@ perform_direct_initialization_if_possible (tree type, tree expr) ...@@ -6308,7 +6342,8 @@ perform_direct_initialization_if_possible (tree type, tree expr)
expr = NULL_TREE; expr = NULL_TREE;
else else
expr = convert_like_real (conv, expr, NULL_TREE, 0, 0, expr = convert_like_real (conv, expr, NULL_TREE, 0, 0,
/*issue_conversion_warnings=*/false); /*issue_conversion_warnings=*/false,
c_cast_p);
/* Free all the conversions we allocated. */ /* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p); obstack_free (&conversion_obstack, p);
...@@ -6449,7 +6484,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) ...@@ -6449,7 +6484,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
expr = convert_like_real (conv, expr, expr = convert_like_real (conv, expr,
/*fn=*/NULL_TREE, /*argnum=*/0, /*fn=*/NULL_TREE, /*argnum=*/0,
/*inner=*/-1, /*inner=*/-1,
/*issue_conversion_warnings=*/true); /*issue_conversion_warnings=*/true,
/*c_cast_p=*/false);
if (!real_lvalue_p (expr)) if (!real_lvalue_p (expr))
{ {
tree init; tree init;
......
...@@ -3585,7 +3585,7 @@ extern tree initialize_reference (tree, tree, tree, tree *); ...@@ -3585,7 +3585,7 @@ extern tree initialize_reference (tree, tree, tree, tree *);
extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals (tree); extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree); extern tree perform_implicit_conversion (tree, tree);
extern tree perform_direct_initialization_if_possible (tree, tree); extern tree perform_direct_initialization_if_possible (tree, tree, bool);
extern tree in_charge_arg_for_name (tree); extern tree in_charge_arg_for_name (tree);
extern tree build_cxx_call (tree, tree); extern tree build_cxx_call (tree, tree);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
...@@ -4290,6 +4290,7 @@ extern tree build_nop (tree, tree); ...@@ -4290,6 +4290,7 @@ extern tree build_nop (tree, tree);
extern tree non_reference (tree); extern tree non_reference (tree);
extern tree lookup_anon_field (tree, tree); extern tree lookup_anon_field (tree, tree);
extern bool invalid_nonstatic_memfn_p (tree); extern bool invalid_nonstatic_memfn_p (tree);
extern tree convert_member_func_to_ptr (tree, tree);
/* in typeck2.c */ /* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree); extern void require_complete_eh_spec_types (tree, tree);
......
...@@ -107,28 +107,9 @@ cp_convert_to_pointer (tree type, tree expr, bool force) ...@@ -107,28 +107,9 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|| VOID_TYPE_P (TREE_TYPE (type)))) || VOID_TYPE_P (TREE_TYPE (type))))
{ {
/* Allow an implicit this pointer for pointer to member if (TYPE_PTRMEMFUNC_P (intype)
functions. */ || TREE_CODE (intype) == METHOD_TYPE)
if (TYPE_PTRMEMFUNC_P (intype)) return convert_member_func_to_ptr (type, expr);
{
if (pedantic || warn_pmf2ptr)
pedwarn ("converting from `%T' to `%T'", intype, type);
if (TREE_CODE (expr) == PTRMEM_CST)
expr = build_address (PTRMEM_CST_MEMBER (expr));
else
{
tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype),
0);
decl = build_address (decl);
expr = get_member_function_from_ptrfunc (&decl, expr);
}
}
else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
{
if (pedantic || warn_pmf2ptr)
pedwarn ("converting from `%T' to `%T'", intype, type);
expr = build_addr_func (expr);
}
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
return build_nop (type, expr); return build_nop (type, expr);
intype = TREE_TYPE (expr); intype = TREE_TYPE (expr);
......
2004-10-19 Mark Mitchell <mark@codesourcery.com>
PR c++/14035
* g++.dg/conversion/reinterpret1.C: Adjust error markers.
* g++.dg/conversion/const2.C: New test.
* g++.dg/expr/reinterpret2.C: New test.
* g++.dg/expr/reinterpret3.C: New test.
* g++.dg/expr/cast2.C: New test.
* g++.dg/expr/copy1.C: New test.
* g++.dg/other/conversion1.C: Change error message.
* g++.dg/parse/comma1.C: Use __extension__ to allow casts from
function pointers to void *.
* g++.old-deja/g++.mike/p10148.C: Likewise.
2004-10-19 Eric Botcazou <ebotcazou@libertysurf.fr> 2004-10-19 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/smod-1.c: Pass -mtune=i486 only on x86. * gcc.dg/smod-1.c: Pass -mtune=i486 only on x86.
......
struct B {};
struct D : public B {};
typedef int B::*bm;
typedef int D::*dm;
bm bp;
void f() {
const_cast<dm>(bp); // { dg-error "" }
}
// PR c++/15076 // PR c++/15076
struct Y { Y(int &); }; // { dg-error "" } struct Y { Y(int &); };
int v; int v;
Y y1(reinterpret_cast<int>(v)); // { dg-error "" } Y y1(reinterpret_cast<int>(v)); // { dg-error "" }
bool b;
void f() {
reinterpret_cast<void*>(b);
}
struct S {};
S s;
void f() {
reinterpret_cast<const S>(s); // { dg-error "" }
}
void (*p)();
void f() {
(void *)p; // { dg-error "" }
}
// PR c++/14035
// { dg-do run }
extern "C" void abort();
struct Blob {
int x, y;
Blob() { }
Blob(const Blob &b) { abort (); }
};
struct Blobby : public Blob { };
struct Wooly {
operator const Blobby & ()
{
return myBlobby;
}
Blobby myBlobby;
};
void catcher(const Blob &blo)
{ }
int main()
{
Wooly wooly;
catcher((const Blob &)wooly);
}
...@@ -13,5 +13,5 @@ int main() ...@@ -13,5 +13,5 @@ int main()
{ {
long long m; long long m;
(void (QObject::*)()) m; // { dg-error "invalid conversion" "" } (void (QObject::*)()) m; // { dg-error "invalid cast" "" }
} }
// PR c++/14278 // PR c++/14278
// { dg-options "" }
struct X { struct X {
X (int p); X (int p);
......
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