cp-tree.h (PTRMEM_OK_P): New macro.
* cp-tree.h (PTRMEM_OK_P): New macro. (itf_ptrmem_ok): New enumeration value. * class.c (resolve_address_of_overloaded_function): Add PTRMEM argument. Diagnose implicit pointer to member. (instantiate_type): Don't diagnose implicit pointer to member here. Pass itf_ptrmem_ok if ok. Adjust calls to resolve_address_of_overloaded_function. * init.c (build_offset_ref): Set PTRMEM_OK_P. (resolve_offset_ref): Don't diagnose implicit pointer to member here. * semantics.c (finish_parenthesized_expr): Clear OFFSET_REFs here. * typeck.c (build_x_unary_op): Calculate PTRMEM_OK_P. (build_unary_op): Deal with single non-static member in microsoft-land. From-SVN: r35777
This commit is contained in:
parent
c349117324
commit
19420d00dc
@ -1,3 +1,19 @@
|
||||
2000-08-18 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* cp-tree.h (PTRMEM_OK_P): New macro.
|
||||
(itf_ptrmem_ok): New enumeration value.
|
||||
* class.c (resolve_address_of_overloaded_function): Add PTRMEM
|
||||
argument. Diagnose implicit pointer to member.
|
||||
(instantiate_type): Don't diagnose implicit pointer to member
|
||||
here. Pass itf_ptrmem_ok if ok. Adjust calls to
|
||||
resolve_address_of_overloaded_function.
|
||||
* init.c (build_offset_ref): Set PTRMEM_OK_P.
|
||||
(resolve_offset_ref): Don't diagnose implicit pointer to member here.
|
||||
* semantics.c (finish_parenthesized_expr): Clear OFFSET_REFs here.
|
||||
* typeck.c (build_x_unary_op): Calculate PTRMEM_OK_P.
|
||||
(build_unary_op): Deal with single non-static member in
|
||||
microsoft-land.
|
||||
|
||||
2000-08-18 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* decl2.c (arg_assoc_type): Cope with TYPENAME_TYPE.
|
||||
|
@ -132,7 +132,7 @@ static int method_name_cmp PARAMS ((const tree *, const tree *));
|
||||
static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
|
||||
static tree fixed_type_or_null PARAMS ((tree, int *));
|
||||
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
|
||||
int, tree));
|
||||
int, int, tree));
|
||||
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
|
||||
static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
|
||||
static int count_fields PARAMS ((tree));
|
||||
@ -5725,19 +5725,22 @@ pop_lang_context ()
|
||||
/* Given an OVERLOAD and a TARGET_TYPE, return the function that
|
||||
matches the TARGET_TYPE. If there is no satisfactory match, return
|
||||
error_mark_node, and issue an error message if COMPLAIN is
|
||||
non-zero. If TEMPLATE_ONLY, the name of the overloaded function
|
||||
non-zero. Permit pointers to member function if PTRMEM is non-zero.
|
||||
If TEMPLATE_ONLY, the name of the overloaded function
|
||||
was a template-id, and EXPLICIT_TARGS are the explicitly provided
|
||||
template arguments. */
|
||||
|
||||
static tree
|
||||
resolve_address_of_overloaded_function (target_type,
|
||||
overload,
|
||||
complain,
|
||||
complain,
|
||||
ptrmem,
|
||||
template_only,
|
||||
explicit_targs)
|
||||
tree target_type;
|
||||
tree overload;
|
||||
int complain;
|
||||
int ptrmem;
|
||||
int template_only;
|
||||
tree explicit_targs;
|
||||
{
|
||||
@ -5960,6 +5963,14 @@ resolve_address_of_overloaded_function (target_type,
|
||||
/* Good, exactly one match. Now, convert it to the correct type. */
|
||||
fn = TREE_PURPOSE (matches);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
|
||||
&& !ptrmem && !flag_ms_extensions)
|
||||
{
|
||||
if (!complain)
|
||||
return error_mark_node;
|
||||
|
||||
cp_pedwarn ("assuming pointer to member `%D'", fn);
|
||||
}
|
||||
mark_used (fn);
|
||||
|
||||
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
|
||||
@ -5993,7 +6004,9 @@ instantiate_type (lhstype, rhs, flags)
|
||||
int complain = (flags & itf_complain);
|
||||
int strict = (flags & itf_no_attributes)
|
||||
? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
|
||||
tree r;
|
||||
int allow_ptrmem = flags & itf_ptrmem_ok;
|
||||
|
||||
flags &= ~itf_ptrmem_ok;
|
||||
|
||||
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
|
||||
{
|
||||
@ -6053,36 +6066,13 @@ instantiate_type (lhstype, rhs, flags)
|
||||
return instantiate_type (lhstype, rhs, flags);
|
||||
|
||||
case COMPONENT_REF:
|
||||
{
|
||||
r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
|
||||
|
||||
comp:
|
||||
if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)
|
||||
&& complain && !flag_ms_extensions)
|
||||
{
|
||||
/* Note: we check this after the recursive call to avoid
|
||||
complaining about cases where overload resolution fails. */
|
||||
|
||||
tree t = TREE_TYPE (TREE_OPERAND (rhs, 0));
|
||||
tree fn = PTRMEM_CST_MEMBER (r);
|
||||
|
||||
my_friendly_assert (TREE_CODE (r) == PTRMEM_CST, 990811);
|
||||
|
||||
cp_pedwarn
|
||||
("object-dependent reference to `%E' can only be used in a call",
|
||||
DECL_NAME (fn));
|
||||
cp_pedwarn
|
||||
(" to form a pointer to member function, say `&%T::%E'",
|
||||
t, DECL_NAME (fn));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
|
||||
|
||||
case OFFSET_REF:
|
||||
rhs = TREE_OPERAND (rhs, 1);
|
||||
if (BASELINK_P (rhs))
|
||||
return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
|
||||
return instantiate_type (lhstype, TREE_VALUE (rhs),
|
||||
flags | allow_ptrmem);
|
||||
|
||||
/* This can happen if we are forming a pointer-to-member for a
|
||||
member template. */
|
||||
@ -6095,18 +6085,13 @@ instantiate_type (lhstype, rhs, flags)
|
||||
tree fns = TREE_OPERAND (rhs, 0);
|
||||
tree args = TREE_OPERAND (rhs, 1);
|
||||
|
||||
r =
|
||||
return
|
||||
resolve_address_of_overloaded_function (lhstype,
|
||||
fns,
|
||||
complain,
|
||||
allow_ptrmem,
|
||||
/*template_only=*/1,
|
||||
args);
|
||||
if (TREE_CODE (fns) == COMPONENT_REF)
|
||||
{
|
||||
rhs = fns;
|
||||
goto comp;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
case OVERLOAD:
|
||||
@ -6114,6 +6099,7 @@ instantiate_type (lhstype, rhs, flags)
|
||||
resolve_address_of_overloaded_function (lhstype,
|
||||
rhs,
|
||||
complain,
|
||||
allow_ptrmem,
|
||||
/*template_only=*/0,
|
||||
/*explicit_targs=*/NULL_TREE);
|
||||
|
||||
@ -6225,8 +6211,12 @@ instantiate_type (lhstype, rhs, flags)
|
||||
return rhs;
|
||||
|
||||
case ADDR_EXPR:
|
||||
{
|
||||
if (PTRMEM_OK_P (rhs))
|
||||
flags |= itf_ptrmem_ok;
|
||||
|
||||
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
|
||||
|
||||
}
|
||||
case ENTRY_VALUE_EXPR:
|
||||
my_friendly_abort (184);
|
||||
return error_mark_node;
|
||||
|
@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
|
||||
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
|
||||
CTOR_BEGIN_P (in CTOR_STMT)
|
||||
BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
|
||||
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
|
||||
1: IDENTIFIER_VIRTUAL_P.
|
||||
TI_PENDING_TEMPLATE_FLAG.
|
||||
TEMPLATE_PARMS_FOR_INLINE.
|
||||
@ -2666,6 +2667,10 @@ extern int flag_new_for_scope;
|
||||
#define TYPE_PTRMEMFUNC_FLAG(NODE) \
|
||||
(TYPE_LANG_SPECIFIC(NODE)->ptrmemfunc_flag)
|
||||
|
||||
/* Indicates when overload resolution may resolve to a pointer to
|
||||
member function. [expr.unary.op]/3 */
|
||||
#define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE)
|
||||
|
||||
/* A pointer-to-function member type looks like:
|
||||
|
||||
struct {
|
||||
@ -3208,7 +3213,8 @@ typedef enum special_function_kind {
|
||||
typedef enum instantiate_type_flags {
|
||||
itf_none = 0, /* nothing special */
|
||||
itf_complain = 1 << 0, /* complain about errors */
|
||||
itf_no_attributes = 1 << 1 /* ignore attributes on comparisons */
|
||||
itf_no_attributes = 1 << 1, /* ignore attributes on comparisons */
|
||||
itf_ptrmem_ok = 1 << 2, /* pointers to member ok (internal use) */
|
||||
} instantiate_type_flags;
|
||||
|
||||
/* Non-zero means that if a label exists, and no other identifier
|
||||
|
@ -1710,13 +1710,13 @@ build_offset_ref (type, name)
|
||||
expects to encounter OVERLOADs, not raw functions. */
|
||||
t = ovl_cons (t, NULL_TREE);
|
||||
|
||||
return build (OFFSET_REF,
|
||||
unknown_type_node,
|
||||
decl,
|
||||
build (TEMPLATE_ID_EXPR,
|
||||
TREE_TYPE (t),
|
||||
t,
|
||||
TREE_OPERAND (orig_name, 1)));
|
||||
t = build (TEMPLATE_ID_EXPR, TREE_TYPE (t), t,
|
||||
TREE_OPERAND (orig_name, 1));
|
||||
t = build (OFFSET_REF, unknown_type_node, decl, t);
|
||||
|
||||
PTRMEM_OK_P (t) = 1;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
if (!really_overloaded_fn (t))
|
||||
@ -1730,11 +1730,16 @@ build_offset_ref (type, name)
|
||||
mark_used (t);
|
||||
if (DECL_STATIC_FUNCTION_P (t))
|
||||
return t;
|
||||
return build (OFFSET_REF, TREE_TYPE (t), decl, t);
|
||||
t = build (OFFSET_REF, TREE_TYPE (t), decl, t);
|
||||
PTRMEM_OK_P (t) = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
TREE_TYPE (fnfields) = unknown_type_node;
|
||||
return build (OFFSET_REF, unknown_type_node, decl, fnfields);
|
||||
|
||||
t = build (OFFSET_REF, unknown_type_node, decl, fnfields);
|
||||
PTRMEM_OK_P (t) = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
t = member;
|
||||
@ -1772,7 +1777,9 @@ build_offset_ref (type, name)
|
||||
/* In member functions, the form `type::name' is no longer
|
||||
equivalent to `this->type::name', at least not until
|
||||
resolve_offset_ref. */
|
||||
return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
|
||||
t = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
|
||||
PTRMEM_OK_P (t) = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* If a OFFSET_REF made it through to here, then it did
|
||||
@ -1806,16 +1813,15 @@ resolve_offset_ref (exp)
|
||||
}
|
||||
|
||||
if (BASELINK_P (member))
|
||||
{
|
||||
if (! flag_ms_extensions)
|
||||
cp_pedwarn ("assuming & on overloaded member function");
|
||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||
}
|
||||
|
||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
|
||||
{
|
||||
if (! flag_ms_extensions)
|
||||
cp_pedwarn ("assuming & on `%E'", member);
|
||||
if (!flag_ms_extensions)
|
||||
/* A single non-static member, make sure we don't allow a
|
||||
pointer-to-member. */
|
||||
exp = ovl_cons (member, NULL_TREE);
|
||||
|
||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||
}
|
||||
|
||||
|
@ -1331,6 +1331,10 @@ finish_parenthesized_expr (expr)
|
||||
/* This inhibits warnings in truthvalue_conversion. */
|
||||
C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
/* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
|
||||
enclosed in parentheses. */
|
||||
PTRMEM_OK_P (expr) = 0;
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
@ -4260,6 +4260,9 @@ build_x_unary_op (code, xarg)
|
||||
enum tree_code code;
|
||||
tree xarg;
|
||||
{
|
||||
tree exp;
|
||||
int ptrmem = 0;
|
||||
|
||||
if (processing_template_decl)
|
||||
return build_min_nt (code, xarg, NULL_TREE);
|
||||
|
||||
@ -4280,14 +4283,26 @@ build_x_unary_op (code, xarg)
|
||||
if (rval || code != ADDR_EXPR)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (code == ADDR_EXPR)
|
||||
{
|
||||
if (TREE_CODE (xarg) == TARGET_EXPR)
|
||||
if (TREE_CODE (xarg) == OFFSET_REF)
|
||||
{
|
||||
ptrmem = PTRMEM_OK_P (xarg);
|
||||
|
||||
if (!ptrmem && !flag_ms_extensions
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (xarg, 1))) == METHOD_TYPE)
|
||||
/* A single non-static member, make sure we don't allow a
|
||||
pointer-to-member. */
|
||||
xarg = ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE);
|
||||
}
|
||||
else if (TREE_CODE (xarg) == TARGET_EXPR)
|
||||
warning ("taking address of temporary");
|
||||
}
|
||||
exp = build_unary_op (code, xarg, 0);
|
||||
if (TREE_CODE (exp) == ADDR_EXPR)
|
||||
PTRMEM_OK_P (exp) = ptrmem;
|
||||
|
||||
return build_unary_op (code, xarg, 0);
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Just like truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */
|
||||
@ -4635,35 +4650,21 @@ build_unary_op (code, xarg, noconvert)
|
||||
return build1 (ADDR_EXPR, unknown_type_node, arg);
|
||||
}
|
||||
|
||||
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
|
||||
&& OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
|
||||
{
|
||||
if (TREE_CODE (arg) == COMPONENT_REF && flag_ms_extensions
|
||||
&& type_unknown_p (arg)
|
||||
&& OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
|
||||
{
|
||||
/* They're trying to take the address of a unique non-static
|
||||
member function. This is ill-formed, but let's try to DTRT.
|
||||
Note: We only handle unique functions here because we don't
|
||||
want to complain if there's a static overload; non-unique
|
||||
cases will be handled by instantiate_type. But we need to
|
||||
handle this case here to allow casts on the resulting PMF. */
|
||||
member function. This is ill-formed, except in microsoft-land. */
|
||||
|
||||
tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
|
||||
tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
|
||||
|
||||
if (! flag_ms_extensions)
|
||||
{
|
||||
if (current_class_type
|
||||
&& TREE_OPERAND (arg, 0) == current_class_ref)
|
||||
/* An expression like &memfn. */
|
||||
cp_pedwarn ("ISO C++ forbids taking the address of a non-static member function to form a pointer to member function. Say `&%T::%D'", base, name);
|
||||
else
|
||||
cp_pedwarn ("ISO C++ forbids taking the address of a bound member function to form a pointer to member function", base, name);
|
||||
}
|
||||
|
||||
arg = build_offset_ref (base, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (type_unknown_p (arg))
|
||||
return build1 (ADDR_EXPR, unknown_type_node, arg);
|
||||
|
||||
|
||||
/* Handle complex lvalues (when permitted)
|
||||
by reduction to simpler cases. */
|
||||
val = unary_complex_lvalue (code, arg);
|
||||
|
Loading…
Reference in New Issue
Block a user