* 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
+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.
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));
/* 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;
{
/* 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))
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)
{
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. */
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:
resolve_address_of_overloaded_function (lhstype,
rhs,
complain,
+ allow_ptrmem,
/*template_only=*/0,
/*explicit_targs=*/NULL_TREE);
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;
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.
#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 {
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
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))
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;
/* 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
}
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);
}
/* 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;
}
enum tree_code code;
tree xarg;
{
+ tree exp;
+ int ptrmem = 0;
+
if (processing_template_decl)
return build_min_nt (code, xarg, NULL_TREE);
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. */
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);