aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2000-08-18 09:31:11 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2000-08-18 09:31:11 +0000
commit19420d00dce75db81a29e665a427808ef16d114b (patch)
treeb24281de984b1e9b0eb24d983437a18b4ee38340 /gcc
parentc34911732455bc99d88661e9b4cd287fc4b0cc07 (diff)
downloadgcc-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/ChangeLog16
-rw-r--r--gcc/cp/class.c66
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/init.c42
-rw-r--r--gcc/cp/semantics.c4
-rw-r--r--gcc/cp/typeck.c51
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);