diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2000-08-18 09:31:11 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2000-08-18 09:31:11 +0000 |
commit | 19420d00dce75db81a29e665a427808ef16d114b (patch) | |
tree | b24281de984b1e9b0eb24d983437a18b4ee38340 /gcc | |
parent | c34911732455bc99d88661e9b4cd287fc4b0cc07 (diff) | |
download | gcc-19420d00dce75db81a29e665a427808ef16d114b.zip gcc-19420d00dce75db81a29e665a427808ef16d114b.tar.gz gcc-19420d00dce75db81a29e665a427808ef16d114b.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/class.c | 66 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 8 | ||||
-rw-r--r-- | gcc/cp/init.c | 42 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 51 |
6 files changed, 105 insertions, 82 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4e71a93..35a2067 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,21 @@ 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. 2000-08-18 Nathan Sidwell <nathan@codesourcery.com> diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 08099c1..f749c74 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5dba2e3..af39281 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index c35babb..097deb7 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9dc6bca..70ef712 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ddd827a..9ab9b87 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); |