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:
parent
8265f93117
commit
08e17d9d11
9 changed files with 154 additions and 61 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
13
gcc/cp/cvt.c
13
gcc/cp/cvt.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
22
gcc/testsuite/g++.dg/conversion/cast1.C
Normal file
22
gcc/testsuite/g++.dg/conversion/cast1.C
Normal 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;
|
||||
}
|
||||
|
|
@ -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" "" }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue