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>
PR c++/18047
......
......@@ -92,6 +92,9 @@ struct conversion {
copy constructor must be accessible, even though it is not being
used. */
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. */
tree type;
union {
......@@ -125,12 +128,15 @@ static int compare_ics (conversion *, conversion *);
static tree build_over_call (struct z_candidate *, int);
static tree build_java_interface_fn_ref (tree, tree);
#define convert_like(CONV, EXPR) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true)
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true, \
/*c_cast_p=*/false)
#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
/*issue_conversion_warnings=*/true)
static tree convert_like_real (conversion *, tree, tree, int, int, bool);
convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
/*issue_conversion_warnings=*/true, \
/*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,
tree, const char *);
static tree build_object_call (tree, tree);
......@@ -528,6 +534,7 @@ build_conv (conversion_kind code, tree type, conversion *from)
t->rank = rank;
t->user_conv_p = (code == ck_user || from->user_conv_p);
t->bad_p = from->bad_p;
t->base_p = false;
return t;
}
......@@ -721,6 +728,7 @@ standard_conversion (tree to, tree from, tree expr)
cp_type_quals (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (ck_ptr, from, conv);
conv->base_p = true;
}
if (tcode == POINTER_TYPE)
......@@ -4113,11 +4121,14 @@ build_temp (tree expr, tree type, int flags,
being called to continue a conversion chain. It is negative when a
reference binding will be applied, positive otherwise. If
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
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;
void (*diagnostic_fn)(const char *, ...);
......@@ -4133,12 +4144,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (t->kind == ck_user || !t->bad_p)
{
expr = convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false);
/*issue_conversion_warnings=*/false,
/*c_cast_p=*/false);
break;
}
else if (t->kind == ck_ambig)
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)
break;
}
......@@ -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,
convs->kind == ck_ref_bind ? -1 : 1,
/*issue_conversion_warnings=*/false);
/*issue_conversion_warnings=*/false,
c_cast_p);
if (expr == error_mark_node)
return error_mark_node;
......@@ -4321,7 +4335,22 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* Warn about deprecated conversion if appropriate. */
string_conv_p (totype, expr, 1);
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:
break;
}
......@@ -6273,10 +6302,15 @@ perform_implicit_conversion (tree type, tree expr)
/* Convert EXPR to TYPE (as a direct-initialization) if that is
permitted. If the conversion is valid, the converted expression is
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
perform_direct_initialization_if_possible (tree type, tree expr)
perform_direct_initialization_if_possible (tree type,
tree expr,
bool c_cast_p)
{
conversion *conv;
void *p;
......@@ -6308,7 +6342,8 @@ perform_direct_initialization_if_possible (tree type, tree expr)
expr = NULL_TREE;
else
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. */
obstack_free (&conversion_obstack, p);
......@@ -6449,7 +6484,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
expr = convert_like_real (conv, expr,
/*fn=*/NULL_TREE, /*argnum=*/0,
/*inner=*/-1,
/*issue_conversion_warnings=*/true);
/*issue_conversion_warnings=*/true,
/*c_cast_p=*/false);
if (!real_lvalue_p (expr))
{
tree init;
......
......@@ -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 strip_top_quals (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 build_cxx_call (tree, tree);
#ifdef ENABLE_CHECKING
......@@ -4290,6 +4290,7 @@ extern tree build_nop (tree, tree);
extern tree non_reference (tree);
extern tree lookup_anon_field (tree, tree);
extern bool invalid_nonstatic_memfn_p (tree);
extern tree convert_member_func_to_ptr (tree, tree);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);
......
......@@ -107,28 +107,9 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|| VOID_TYPE_P (TREE_TYPE (type))))
{
/* Allow an implicit this pointer for pointer to member
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
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 (TYPE_PTRMEMFUNC_P (intype)
|| TREE_CODE (intype) == METHOD_TYPE)
return convert_member_func_to_ptr (type, expr);
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
return build_nop (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>
* 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
struct Y { Y(int &); }; // { dg-error "" }
struct Y { Y(int &); };
int v;
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()
{
long long m;
(void (QObject::*)()) m; // { dg-error "invalid conversion" "" }
(void (QObject::*)()) m; // { dg-error "invalid cast" "" }
}
// PR c++/14278
// { dg-options "" }
struct X {
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