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:
Nathan Sidwell 2000-08-18 09:31:11 +00:00 committed by Nathan Sidwell
parent c349117324
commit 19420d00dc
6 changed files with 105 additions and 82 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);