re PR c++/18073 (mmintrin.h rejected by C++ frontend)

PR c++/18073
	PR c++/10841
	* cp-tree.h (convert_to_base): Change prototype.
	(build_ptrmemfunc): Likewise.
	(convert_ptrmem): New function.
	* call.c (struct conversion): Adjust documentation for base_p.
	(standard_conversion): Set base_p for ck_pmem conversions as
	appropriate.
	(convert_like_real): Use convert_to_base for ck_pmem and ck_ptr
	conversions.
	* class.c (convert_to_base): Handle both pointers and objects.
	Add nonnull parameter.
	(build_vfield_ref): Adjust call to convert_to_base.
	* cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc.
	(convert_force): Likewise.
	* typeck.c (build_unary_op): Likewise.
	(convert_ptrmem): New function.
	(build_static_cast_1): Use it.
	(build_reinterpret_cast): Allow conversions to vector types.
	(get_delta_difference): Add c_cast_p parameter.
	(build_ptrmemfunc): Likewise.  Adjust calls to
	get_delta_difference.

	PR c++/10841
	* g++.dg/conversion/cast1.C: New test.
	* g++.dg/overload/pmf1.C: Adjust error marker.

From-SVN: r89403
This commit is contained in:
Mark Mitchell 2004-10-21 21:23:42 +00:00 committed by Mark Mitchell
parent 8265f93117
commit 08e17d9d11
9 changed files with 154 additions and 61 deletions

View file

@ -1,3 +1,28 @@
2004-10-21 Mark Mitchell <mark@codesourcery.com>
PR c++/18073
PR c++/10841
* cp-tree.h (convert_to_base): Change prototype.
(build_ptrmemfunc): Likewise.
(convert_ptrmem): New function.
* call.c (struct conversion): Adjust documentation for base_p.
(standard_conversion): Set base_p for ck_pmem conversions as
appropriate.
(convert_like_real): Use convert_to_base for ck_pmem and ck_ptr
conversions.
* class.c (convert_to_base): Handle both pointers and objects.
Add nonnull parameter.
(build_vfield_ref): Adjust call to convert_to_base.
* cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc.
(convert_force): Likewise.
* typeck.c (build_unary_op): Likewise.
(convert_ptrmem): New function.
(build_static_cast_1): Use it.
(build_reinterpret_cast): Allow conversions to vector types.
(get_delta_difference): Add c_cast_p parameter.
(build_ptrmemfunc): Likewise. Adjust calls to
get_delta_difference.
2004-10-21 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/13560

View file

@ -92,8 +92,8 @@ 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. */
/* If KIND is ck_ptr or ck_pmem, 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;
@ -779,6 +779,7 @@ standard_conversion (tree to, tree from, tree expr)
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
conv = build_conv (ck_pmem, from, conv);
conv->base_p = true;
}
else if (tcode == BOOLEAN_TYPE)
{
@ -4270,8 +4271,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
check_constructor_callable (TREE_TYPE (expr), expr);
/* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
expr = perform_implicit_conversion (build_pointer_type (totype),
expr);
expr = convert_to_base (expr, build_pointer_type (totype),
!c_cast_p, /*nonnull=*/true);
expr = build_indirect_ref (expr, "implicit conversion");
return expr;
}
@ -4338,19 +4339,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
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);
}
expr = convert_to_base (expr, totype, !c_cast_p,
/*nonnull=*/false);
return build_nop (totype, expr);
case ck_pmem:
return convert_ptrmem (totype, expr, /*allow_inverse_p=*/false,
c_cast_p);
default:
break;
}

View file

@ -426,22 +426,34 @@ build_simple_base_path (tree expr, tree binfo)
gcc_unreachable ();
}
/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
message is emitted if TYPE is inaccessible. OBJECT is assumed to
be non-NULL. */
/* Convert OBJECT to the base TYPE. OBJECT is an expression whose
type is a class type or a pointer to a class type. In the former
case, TYPE is also a class type; in the latter it is another
pointer type. If CHECK_ACCESS is true, an error message is emitted
if TYPE is inaccessible. If OBJECT has pointer type, the value is
assumed to be non-NULL. */
tree
convert_to_base (tree object, tree type, bool check_access)
convert_to_base (tree object, tree type, bool check_access, bool nonnull)
{
tree binfo;
tree object_type;
binfo = lookup_base (TREE_TYPE (object), type,
if (TYPE_PTR_P (TREE_TYPE (object)))
{
object_type = TREE_TYPE (TREE_TYPE (object));
type = TREE_TYPE (type);
}
else
object_type = TREE_TYPE (object);
binfo = lookup_base (object_type, type,
check_access ? ba_check : ba_unique,
NULL);
if (!binfo || binfo == error_mark_node)
return error_mark_node;
return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
return build_base_path (PLUS_EXPR, object, binfo, nonnull);
}
/* EXPR is an expression with unqualified class type. BASE is a base
@ -485,7 +497,8 @@ build_vfield_ref (tree datum, tree type)
/* First, convert to the requested type. */
if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
datum = convert_to_base (datum, type, /*check_access=*/false);
datum = convert_to_base (datum, type, /*check_access=*/false,
/*nonnull=*/true);
/* Second, the requested type may not be the owner of its own vptr.
If not, convert to the base class that owns it. We cannot use

View file

@ -3594,7 +3594,7 @@ extern void validate_conversion_obstack (void);
/* in class.c */
extern tree build_base_path (enum tree_code, tree, tree, int);
extern tree convert_to_base (tree, tree, bool);
extern tree convert_to_base (tree, tree, bool, bool);
extern tree convert_to_base_statically (tree, tree);
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
@ -4267,7 +4267,7 @@ extern tree dubious_conversion_warnings (tree, tree, const char *, tree,
extern tree convert_for_initialization (tree, tree, tree, int, const char *, tree, int);
extern int comp_ptr_ttypes (tree, tree);
extern int ptr_reasonably_similar (tree, tree);
extern tree build_ptrmemfunc (tree, tree, int);
extern tree build_ptrmemfunc (tree, tree, int, bool);
extern int cp_type_quals (tree);
extern bool cp_has_mutable_p (tree);
extern bool at_least_as_qualified_p (tree, tree);
@ -4291,6 +4291,7 @@ 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);
extern tree convert_ptrmem (tree, tree, bool, bool);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);

View file

@ -217,7 +217,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return build_nop (type, expr);
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
/*c_cast_p=*/false);
else if (TYPE_PTRMEMFUNC_P (intype))
{
if (!warn_pmf2ptr)
@ -241,7 +242,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
if (integer_zerop (expr))
{
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
/*c_cast_p=*/false);
if (TYPE_PTRMEM_P (type))
{
@ -960,10 +962,9 @@ convert_force (tree type, tree expr, int convtype)
|| integer_zerop (e)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
&& TYPE_PTRMEMFUNC_P (type))
{
/* compatible pointer to member functions. */
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
}
/* compatible pointer to member functions. */
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
/*c_cast_p=*/1);
return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
}

View file

@ -52,7 +52,7 @@ static bool comp_except_types (tree, tree, bool);
static bool comp_array_types (tree, tree, bool);
static tree common_base_type (tree, tree);
static tree pointer_diff (tree, tree, tree);
static tree get_delta_difference (tree, tree, int);
static tree get_delta_difference (tree, tree, bool, bool);
static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
@ -4146,7 +4146,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
{
build_ptrmemfunc_type (argtype);
addr = build_ptrmemfunc (argtype, addr, 0);
addr = build_ptrmemfunc (argtype, addr, 0,
/*c_cast_p=*/false);
}
return addr;
@ -4485,6 +4486,38 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
description, src_type, dest_type);
}
/* Convert EXPR (an expression with pointer-to-member type) to TYPE
(another pointer-to-member type in the same hierarchy) and return
the converted expression. If ALLOW_INVERSE_P is permitted, a
pointer-to-derived may be converted to pointer-to-base; otherwise,
only the other direction is permitted. If C_CAST_P is true, this
conversion is taking place as part of a C-style cast. */
tree
convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
bool c_cast_p)
{
if (TYPE_PTRMEM_P (type))
{
tree delta;
if (TREE_CODE (expr) == PTRMEM_CST)
expr = cplus_expand_constant (expr);
delta = get_delta_difference (TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (expr)),
TYPE_PTRMEM_CLASS_TYPE (type),
allow_inverse_p,
c_cast_p);
if (!integer_zerop (delta))
expr = cp_build_binary_op (PLUS_EXPR,
build_nop (ptrdiff_type_node, expr),
delta);
return build_nop (type, expr);
}
else
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
allow_inverse_p, c_cast_p);
}
/* Perform a static_cast from EXPR to TYPE. When C_CAST_P is true,
this static_cast is being attempted as one of the possible casts
allowed by a C-style cast. (In that case, accessibility of base
@ -4691,23 +4724,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
if (can_convert (t1, t2))
{
if (!c_cast_p)
check_for_casting_away_constness (intype, type, diag_fn, desc);
if (TYPE_PTRMEM_P (type))
{
tree delta;
if (TREE_CODE (expr) == PTRMEM_CST)
expr = cplus_expand_constant (expr);
delta = get_delta_difference (c1, c2, /*force=*/1);
if (!integer_zerop (delta))
expr = cp_build_binary_op (PLUS_EXPR,
build_nop (ptrdiff_type_node, expr),
delta);
return build_nop (type, expr);
}
else
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
/*force=*/1);
check_for_casting_away_constness (intype, type, diag_fn,
desc);
return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
c_cast_p);
}
}
@ -4945,6 +4965,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
expr = decl_constant_value (expr);
return fold_if_not_in_template (build_nop (type, expr));
}
else if (TREE_CODE (type) == VECTOR_TYPE)
return fold_if_not_in_template (convert_to_vector (type, expr));
else
{
if (valid_p)
@ -5546,8 +5568,10 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
/* Get difference in deltas for different pointer to member function
types. Returns an integer constant of type PTRDIFF_TYPE_NODE. If
the conversion is invalid, the constant is zero. If FORCE is true,
then allow reverse conversions as well.
the conversion is invalid, the constant is zero. If
ALLOW_INVERSE_P is true, then allow reverse conversions as well.
If C_CAST_P is true this conversion is taking place as part of a
C-style cast.
Note that the naming of FROM and TO is kind of backwards; the return
value is what we add to a TO in order to get a FROM. They are named
@ -5555,7 +5579,9 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
a pointer to member of FROM to a pointer to member of TO. */
static tree
get_delta_difference (tree from, tree to, int force)
get_delta_difference (tree from, tree to,
bool allow_inverse_p,
bool c_cast_p)
{
tree binfo;
tree virt_binfo;
@ -5564,19 +5590,20 @@ get_delta_difference (tree from, tree to, int force)
/* Assume no conversion is required. */
result = integer_zero_node;
binfo = lookup_base (to, from, ba_check, &kind);
binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
if (kind == bk_inaccessible || kind == bk_ambig)
error (" in pointer to member function conversion");
else if (!binfo)
{
if (!force)
if (!allow_inverse_p)
{
error_not_base_type (from, to);
error (" in pointer to member conversion");
}
else
{
binfo = lookup_base (from, to, ba_check, &kind);
binfo = lookup_base (from, to, c_cast_p ? ba_unique : ba_check,
&kind);
if (binfo)
{
virt_binfo = binfo_from_vbase (binfo);
@ -5597,7 +5624,7 @@ get_delta_difference (tree from, tree to, int force)
else
{
/* This is a reinterpret cast, we choose to do nothing. */
if (force)
if (allow_inverse_p)
warning ("pointer to member cast via virtual base %qT",
BINFO_TYPE (virt_binfo));
else
@ -5648,12 +5675,12 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
If FORCE is nonzero, then force this conversion, even if
we would rather not do it. Usually set when using an explicit
cast.
cast. A C-style cast is being processed iff C_CAST_P is true.
Return error_mark_node, if something goes wrong. */
tree
build_ptrmemfunc (tree type, tree pfn, int force)
build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
{
tree fn;
tree pfn_type;
@ -5679,7 +5706,8 @@ build_ptrmemfunc (tree type, tree pfn, int force)
n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type),
TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type),
force);
force,
c_cast_p);
/* We don't have to do any conversion to convert a
pointer-to-member to its own type. But, we don't want to
@ -5754,7 +5782,8 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
/* First, calculate the adjustment to the function's class. */
*delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
*delta = get_delta_difference (fn_class, ptr_class, /*force=*/0,
/*c_cast_p=*/0);
if (!DECL_VIRTUAL_P (fn))
*pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));

View file

@ -1,3 +1,9 @@
2004-10-21 Mark Mitchell <mark@codesourcery.com>
PR c++/10841
* g++.dg/conversion/cast1.C: New test.
* g++.dg/overload/pmf1.C: Adjust error marker.
2004-10-21 Andrew Pinski <pinskia@physics.uc.edu>
PR objc/17923

View file

@ -0,0 +1,22 @@
// PR c++/10841
int main() {
class Base {
public:
int i, j, k;
void f(); };
class Derived : private Base {
public:
int m, n, p;
void g();
};
Derived derived;
Base &base = (Base &)derived;
(int Base::*)&Derived::n;
(int Derived::*)&Base::j;
(void (Base::*)(void))&Derived::g;
(void (Derived::*)(void))&Base::f;
}

View file

@ -17,5 +17,5 @@ void f (C) {} // even though this would be well-formed
int main ()
{
f (aip); // { dg-error "'A' is an inaccessible base of 'B'" "" }
f (aip); // { dg-error "'A' is an inaccessible base of 'B'|conversion" "" }
}