summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog70
-rw-r--r--gcc/cp/call.c23
-rw-r--r--gcc/cp/class.c23
-rw-r--r--gcc/cp/cp-tree.def14
-rw-r--r--gcc/cp/cp-tree.h32
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/cp/decl2.c22
-rw-r--r--gcc/cp/error.c6
-rw-r--r--gcc/cp/except.c8
-rw-r--r--gcc/cp/init.c36
-rw-r--r--gcc/cp/method.c26
-rw-r--r--gcc/cp/parse.y57
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/cp/search.c17
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/cp/spew.c4
-rw-r--r--gcc/cp/tree.c22
-rw-r--r--gcc/cp/typeck.c679
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/abi/offsetof.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p10769a.C2
22 files changed, 642 insertions, 437 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f5fe87b8533..b5e51ed3538 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,73 @@
+2002-08-07 Mark Mitchell <mark@codesourcery.com>
+
+ Rework build_component_ref.
+ * call.c (build_vfield_ref): Do not go through build_component_ref.
+ (build_field_call): Use build_class_member_access_expr.
+ (build_user_type_conversion_1): Use BASELINK_FUNCTIONS.
+ (build_object_call): Likewise.
+ * class.c (convert_to_base): New function.
+ (type_requires_array_cookie): Use BASELINK_FUNCTIONS.
+ (instantiate_type): Handle BASELINKs.
+ * cp-tree.def (BASELINK): New tree code.
+ * cp-tree.h (BASELINK_P): Reimplement.
+ (SET_BASELINK_P): Remove.
+ (BASELINK_BINFO): Reimplement.
+ (BASELINK_FUNCTIONS): Likewise.
+ (BASELINK_ACCESS_BINFO): Likewise.
+ (BASELINK_OPTYPE): Likewise.
+ (convert_to_base): New function.
+ (name_p): Likewise.
+ (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_component_ref): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ * decl.c (grokdeclarator): Handle BASELINKs.
+ * decl2. (build_expr_from_tree): Handle COMPONENT_REFs by using
+ finish_class_member_access_expr.
+ (arg_assoc): Handle BASELINKs.
+ (do_class_using_decl): Likewise.
+ * error.c (dump_decl): Likewise.
+ (dump_expr): Use build_ptrmemfunc_access_expr.
+ * except.c (dtor_nothrow): Use CLASSTYPE_DESTRUCTORS to find
+ destructors.
+ (build_throw): Use BASELINK_FUNCTIONS.
+ * init.c (perform_member_init): Use
+ build_class_member_access_expr.
+ (build_offset_ref): Handle BASELINKs. Use
+ build_class_member_access_expr.
+ * method.c (hack_identifier): Likewise.
+ * parse.y (do_id): Use BASELINK, not TREE_LIST.
+ (primary): Remove uses of build_object_ref.
+ * pt.c (lookup_template_function): Handle BASELINKs.
+ (resolve_overloaded_unification): Likewise.
+ * search.c (build_baselink): Build a BASELINK, not a TREE_LIST.
+ (lookup_field): Use BASELINK, not TREE_LIST.
+ (lookup_fnfiels): Likewise.
+ (setup_class_bindings): Likewise.
+ * semantics.c (finish_object_call_expr): Do not use
+ build_method_call when we already know what function is being
+ called.
+ * spew.c (identifier_type): Use BASELINK, not TREE_LIST.
+ * tree.c (really_overloaded_fn): Use OVL_CHAIN for OVERLOADs, not
+ TREE_CHAIN.
+ (name_p): New function.
+ * typeck.c (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ (get_member_function_from_ptrfunc): Use
+ build_ptrmemfunc_access_expr.
+ (build_binary_op): Likewise.
+ (build_unary_op): Likewise.
+ (build_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+ * typeck2.c (build_m_component_ref): Adjust comment.
+
2002-08-07 Neil Booth <neil@daikokuya.co.uk>
* Make-lang.in (CXX_C_OBJS): Update.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6dea0ddd52d..7f6b32fc053 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -106,21 +106,18 @@ tree
build_vfield_ref (datum, type)
tree datum, type;
{
- tree rval;
-
if (datum == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
- if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type))
- rval = build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
- datum, TYPE_VFIELD (type));
- else
- rval = build_component_ref (datum, DECL_NAME (TYPE_VFIELD (type)), NULL_TREE, 0);
+ if (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
+ && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
+ datum = convert_to_base (datum, type, /*check_access=*/false);
- return rval;
+ return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
+ datum, TYPE_VFIELD (type));
}
/* Build a call to a member of an object. I.e., one that overloads
@@ -139,7 +136,9 @@ build_field_call (tree instance_ptr, tree decl, tree parms)
/* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */
instance = build_indirect_ref (instance_ptr, NULL);
- instance = build_component_ref_1 (instance, decl, 0);
+ instance = build_class_member_access_expr (instance, decl,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
if (instance == error_mark_node)
return error_mark_node;
@@ -2500,7 +2499,7 @@ build_user_type_conversion_1 (totype, expr, flags)
{
tree t;
- ctors = TREE_VALUE (ctors);
+ ctors = BASELINK_FUNCTIONS (ctors);
t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
@@ -2796,10 +2795,10 @@ build_object_call (obj, args)
if (fns)
{
- tree base = BINFO_TYPE (TREE_PURPOSE (fns));
+ tree base = BINFO_TYPE (BASELINK_BINFO (fns));
mem_args = tree_cons (NULL_TREE, build_this (obj), args);
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 81b1a2c25f5..03f73f20561 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -358,6 +358,24 @@ build_base_path (code, expr, binfo, nonnull)
return expr;
}
+/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
+ message is emitted if TYPE is inaccessible. OBJECT is assumed to
+ be non-NULL. */
+
+tree
+convert_to_base (tree object, tree type, bool check_access)
+{
+ tree binfo;
+
+ binfo = lookup_base (TREE_TYPE (object), type,
+ check_access ? ba_check : ba_ignore,
+ NULL);
+ if (!binfo || TREE_CODE (binfo) == error_mark_node)
+ return error_mark_node;
+
+ return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+}
+
/* Virtual function things. */
@@ -4201,7 +4219,7 @@ type_requires_array_cookie (type)
if (!fns || fns == error_mark_node)
return false;
/* Loop through all of the functions. */
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn;
tree second_parm;
@@ -6003,6 +6021,9 @@ instantiate_type (lhstype, rhs, flags)
return error_mark_node;
}
+ if (TREE_CODE (rhs) == BASELINK)
+ rhs = BASELINK_FUNCTIONS (rhs);
+
/* We don't overwrite rhs if it is an overloaded function.
Copying it would destroy the tree link. */
if (TREE_CODE (rhs) != OVERLOAD)
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index a70ad501412..90685af50d4 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -89,6 +89,20 @@ DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1)
these to avoid actually creating instances of the empty classes. */
DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0)
+/* A reference to a member function or member functions from a base
+ class. BASELINK_FUNCTIONS gives the FUNCTION_DECL,
+ TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the
+ functions. BASELINK_BINFO gives the base from which the functions
+ come, i.e., the base to which the `this' pointer must be converted
+ before the functions are called. BASELINK_ACCESS_BINFO gives the
+ base used to name the functions.
+
+ A BASELINK is an expression; the TREE_TYPE of the BASELINK gives
+ the type of the expression. This type is either a FUNCTION_TYPE,
+ METHOD_TYPE, or `unknown_type_node' indicating that the function is
+ overloaded. */
+DEFTREECODE (BASELINK, "baselink", 'e', 3)
+
/* Template definition. The following fields have the specified uses,
although there are other macros in cp-tree.h that should be used for
accessing this data.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b1af9fbc56d..25b6e949d2d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -57,7 +57,6 @@ struct diagnostic_context;
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
- BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
2: IDENTIFIER_OPNAME_P.
@@ -361,32 +360,28 @@ struct tree_overload GTY(())
tree function;
};
-/* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO
- indicating a particular base class, and whose TREE_VALUE is a
- (possibly overloaded) function from that base class. */
+/* Returns true iff NODE is a BASELINK. */
#define BASELINK_P(NODE) \
- (TREE_CODE (NODE) == TREE_LIST && TREE_LANG_FLAG_1 (NODE))
-#define SET_BASELINK_P(NODE) \
- (TREE_LANG_FLAG_1 (NODE) = 1)
-/* The BINFO indicated the base from which the BASELINK_FUNCTIONS came. */
+ (TREE_CODE (NODE) == BASELINK)
+/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */
#define BASELINK_BINFO(NODE) \
- (TREE_PURPOSE (NODE))
-/* The functions referred to by the BASELINK; either a FUNCTION_DECL
- or an OVERLOAD. */
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 0))
+/* The functions referred to by the BASELINK; either a FUNCTION_DECL,
+ a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */
#define BASELINK_FUNCTIONS(NODE) \
- (TREE_VALUE (NODE))
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 1))
/* The BINFO in which the search for the functions indicated by this baselink
began. This base is used to determine the accessibility of functions
selected by overload resolution. */
#define BASELINK_ACCESS_BINFO(NODE) \
- (TREE_TYPE (NODE))
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 2))
/* For a type-conversion operator, the BASELINK_OPTYPE indicates the type
to which the conversion should occur. This value is important if
the BASELINK_FUNCTIONS include a template conversion operator --
the BASELINK_OPTYPE can be used to determine what type the user
requested. */
#define BASELINK_OPTYPE(NODE) \
- (TREE_CHAIN (NODE))
+ (TREE_CHAIN (BASELINK_CHECK (NODE)))
#define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)
@@ -3525,6 +3520,7 @@ extern tree perform_implicit_conversion PARAMS ((tree, tree));
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
+extern tree convert_to_base (tree, tree, bool);
extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
@@ -4238,6 +4234,7 @@ extern tree cp_build_qualified_type_real PARAMS ((tree, int, tsubst_flags
cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
extern tree build_shared_int_cst PARAMS ((int));
extern special_function_kind special_function_p PARAMS ((tree));
+extern bool name_p (tree);
extern int count_trees PARAMS ((tree));
extern int char_type_p PARAMS ((tree));
extern void verify_stmt_tree PARAMS ((tree));
@@ -4277,10 +4274,8 @@ extern tree cxx_sizeof_or_alignof_type PARAMS ((tree, enum tree_code, int));
#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion PARAMS ((tree));
extern tree decay_conversion PARAMS ((tree));
-extern tree build_object_ref PARAMS ((tree, tree, tree));
-extern tree build_component_ref_1 PARAMS ((tree, tree, int));
-extern tree build_component_ref PARAMS ((tree, tree, tree, int));
-extern tree build_x_component_ref PARAMS ((tree, tree, tree));
+extern tree build_class_member_access_expr (tree, tree, tree, bool);
+extern tree finish_class_member_access_expr (tree, tree);
extern tree build_x_indirect_ref PARAMS ((tree, const char *));
extern tree build_indirect_ref PARAMS ((tree, const char *));
extern tree build_array_ref PARAMS ((tree, tree));
@@ -4321,6 +4316,7 @@ extern tree check_return_expr PARAMS ((tree));
build_binary_op(code, arg1, arg2, 1)
#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
+extern tree build_ptrmemfunc_access_expr (tree, tree);
/* in typeck2.c */
extern void cxx_incomplete_type_diagnostic PARAMS ((tree, tree, int));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f64ba299cb5..fcf7e453681 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10001,6 +10001,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
next = 0;
break;
+ case BASELINK:
+ next = &BASELINK_FUNCTIONS (decl);
+ break;
+
default:
internal_error ("`%D' as declarator", decl);
}
@@ -11133,6 +11137,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
declarator = TREE_OPERAND (declarator, 0);
break;
+ case BASELINK:
+ declarator = BASELINK_FUNCTIONS (declarator);
+ break;
+
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 26442068c4e..bdd854f4d5a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3369,17 +3369,8 @@ build_expr_from_tree (t)
case COMPONENT_REF:
{
tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
- tree field = TREE_OPERAND (t, 1);
-
- /* We use a COMPONENT_REF to indicate things of the form `x.b'
- and `x.A::b'. We must distinguish between those cases
- here. */
- if (TREE_CODE (field) == SCOPE_REF)
- return build_object_ref (object,
- TREE_OPERAND (field, 0),
- TREE_OPERAND (field, 1));
- else
- return build_x_component_ref (object, field, NULL_TREE);
+ return finish_class_member_access_expr (object,
+ TREE_OPERAND (t, 1));
}
case THROW_EXPR:
@@ -4283,6 +4274,8 @@ arg_assoc (k, n)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
+ if (TREE_CODE (n) == BASELINK)
+ n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
@@ -4647,6 +4640,13 @@ do_class_using_decl (decl)
}
if (TREE_CODE (name) == TYPE_DECL || TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
+ else if (BASELINK_P (name))
+ {
+ name = BASELINK_FUNCTIONS (name);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (name, 0);
+ name = DECL_NAME (get_first_fn (name));
+ }
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index bf55e25d157..b6caac7d789 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -990,6 +990,10 @@ dump_decl (t, flags)
print_tree_identifier (scratch_buffer, DECL_NAME (t));
break;
+ case BASELINK:
+ dump_decl (BASELINK_FUNCTIONS (t), flags);
+ break;
+
default:
sorry_for_unsupported_tree (t);
/* Fallthrough to error. */
@@ -1826,7 +1830,7 @@ dump_expr (t, flags)
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
{
- tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
if (integer_zerop (idx))
{
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 321a142173b..4b8b5ee8503 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -174,17 +174,13 @@ static int
dtor_nothrow (type)
tree type;
{
- tree fn;
-
if (type == NULL_TREE)
return 0;
if (! TYPE_HAS_DESTRUCTOR (type))
return 1;
- fn = lookup_member (type, dtor_identifier, 0, 0);
- fn = TREE_VALUE (fn);
- return TREE_NOTHROW (fn);
+ return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
/* Build up a call to __cxa_end_catch, to destroy the exception object
@@ -753,7 +749,7 @@ build_throw (exp)
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
- cleanup = TREE_VALUE (cleanup);
+ cleanup = BASELINK_FUNCTIONS (cleanup);
mark_used (cleanup);
cxx_mark_addressable (cleanup);
/* Pretend it's a normal function. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6286a227753..737cd9c15c1 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -232,8 +232,9 @@ perform_member_init (member, init, explicit)
tree decl;
tree type = TREE_TYPE (member);
- decl = build_component_ref (current_class_ref, member, NULL_TREE, explicit);
-
+ decl = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/true);
if (decl == error_mark_node)
return;
@@ -305,8 +306,9 @@ perform_member_init (member, init, explicit)
{
tree expr;
- expr = build_component_ref (current_class_ref, member, NULL_TREE,
- explicit);
+ expr = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
expr = build_delete (type, expr, sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
@@ -1668,10 +1670,15 @@ build_offset_ref (type, name)
decl = maybe_dummy_object (type, &basebinfo);
- member = lookup_member (basebinfo, name, 1, 0);
-
- if (member == error_mark_node)
- return error_mark_node;
+ if (BASELINK_P (name))
+ member = name;
+ else
+ {
+ member = lookup_member (basebinfo, name, 1, 0);
+
+ if (member == error_mark_node)
+ return error_mark_node;
+ }
/* A lot of this logic is now handled in lookup_member. */
if (member && BASELINK_P (member))
@@ -1703,7 +1710,7 @@ build_offset_ref (type, name)
return t;
}
- if (!really_overloaded_fn (t))
+ if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
{
/* Get rid of a potential OVERLOAD around it */
t = OVL_CURRENT (t);
@@ -1848,7 +1855,9 @@ resolve_offset_ref (exp)
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
- return build_component_ref (base, member, binfo, 1);
+ return build_class_member_access_expr (base, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
}
/* Ensure that we have an object. */
@@ -3332,9 +3341,10 @@ push_base_cleanups ()
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{
- tree this_member = (build_component_ref
- (current_class_ref, DECL_NAME (member),
- NULL_TREE, 0));
+ tree this_member = (build_class_member_access_expr
+ (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false));
tree this_type = TREE_TYPE (member);
expr = build_delete (this_type, this_member,
sfk_complete_destructor,
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 42d405f5e29..5fa7433c860 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -161,12 +161,26 @@ hack_identifier (value, name)
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
+ if (processing_template_decl)
+ value = build_min_nt (COMPONENT_REF, current_class_ref, name);
+ else
+ {
+ tree access_type = current_class_type;
+
+ while (!DERIVED_FROM_P (context_for_name_lookup (value),
+ access_type))
+ {
+ access_type = TYPE_CONTEXT (access_type);
+ while (DECL_P (access_type))
+ access_type = DECL_CONTEXT (access_type);
+ }
- /* Mark so that if we are in a constructor, and then find that
- this field was initialized by a base initializer,
- we can emit an error message. */
- TREE_USED (value) = 1;
- value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
+ enforce_access (access_type, value);
+ value
+ = build_class_member_access_expr (current_class_ref, value,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
+ }
}
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
@@ -179,7 +193,7 @@ hack_identifier (value, name)
value = OVL_CURRENT (value);
decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
- value = build_component_ref (decl, name, NULL_TREE, 1);
+ value = finish_class_member_access_expr (decl, name);
}
else if (really_overloaded_fn (value))
;
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index b7b9d30c236..01181d73b4c 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -1520,11 +1520,11 @@ notype_unqualified_id:
do_id:
{
- /* If lastiddecl is a TREE_LIST, it's a baselink, which
- means that we're in an expression like S::f<int>, so
- don't do_identifier; we only do that for unqualified
+ /* If lastiddecl is a BASELINK we're in an
+ expression like S::f<int>, so don't
+ do_identifier; we only do that for unqualified
identifiers. */
- if (!lastiddecl || TREE_CODE (lastiddecl) != TREE_LIST)
+ if (!lastiddecl || !BASELINK_P (lastiddecl))
$$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
else
$$ = $<ttype>-1;
@@ -1718,20 +1718,15 @@ primary:
| overqualified_id LEFT_RIGHT
{ $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| object object_template_id %prec UNARY
- {
- $$ = build_x_component_ref ($$, $2, NULL_TREE);
- }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object object_template_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object object_template_id LEFT_RIGHT
{ $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
| object unqualified_id %prec UNARY
- { $$ = build_x_component_ref ($$, $2, NULL_TREE); }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object overqualified_id %prec UNARY
- { if (processing_template_decl)
- $$ = build_min_nt (COMPONENT_REF, $1, $2);
- else
- $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+ { $$ = finish_class_member_access_expr ($1, $2); }
| object unqualified_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object unqualified_id LEFT_RIGHT
@@ -4147,14 +4142,20 @@ parse_finish_call_expr (tree fn, tree args, int koenig)
else
template_id = NULL_TREE;
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (get_first_fn (name));
- fn = lookup_member (scope, name, /*protect=*/1,
- /*prefer_type=*/0);
- if (BASELINK_P (fn) && template_id)
- BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
- BASELINK_FUNCTIONS (fn),
- template_args);
+ if (BASELINK_P (name))
+ fn = name;
+ else
+ {
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ fn = lookup_member (scope, name, /*protect=*/1,
+ /*prefer_type=*/0);
+ if (BASELINK_P (fn) && template_id)
+ BASELINK_FUNCTIONS (fn)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fn),
+ template_args);
+ }
if (BASELINK_P (fn)
&& current_class_type
&& DERIVED_FROM_P (scope, current_class_type))
@@ -4216,9 +4217,19 @@ parse_finish_call_expr (tree fn, tree args, int koenig)
if (DERIVED_FROM_P (scope, current_class_type)
&& current_class_ref)
- return finish_object_call_expr (fn,
- current_class_ref,
- args);
+ {
+ fn = build_baselink (lookup_base (current_class_type,
+ scope,
+ ba_any,
+ NULL),
+ TYPE_BINFO (current_class_type),
+ fn,
+ /*optype=*/NULL_TREE);
+ return finish_object_call_expr (fn,
+ current_class_ref,
+ args);
+ }
+
access_scope = current_class_type;
while (!DERIVED_FROM_P (scope, access_scope))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 406e54aa1b8..af698747292 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3833,10 +3833,20 @@ lookup_template_function (fns, arglist)
my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
|| TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
|| TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == LOOKUP_EXPR,
20020730);
+ if (BASELINK_P (fns))
+ {
+ BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
+ return fns;
+ }
+
type = TREE_TYPE (fns);
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
@@ -8193,8 +8203,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
arg = TREE_OPERAND (arg, 1);
/* Strip baselink information. */
- while (TREE_CODE (arg) == TREE_LIST)
- arg = TREE_VALUE (arg);
+ if (BASELINK_P (arg))
+ arg = BASELINK_FUNCTIONS (arg);
if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 48c4f8fbe46..071a551fbe3 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -300,8 +300,10 @@ lookup_base_r (binfo, base, access, within_current_scope,
canonical). If KIND_PTR is non-NULL, fill with information about
what kind of base we discovered.
- If ba_quiet bit is set in ACCESS, then do not issue an error, and
- return NULL_TREE for failure. */
+ If the base is inaccessible, or ambiguous, and the ba_quiet bit is
+ not set in ACCESS, then an error is issued and error_mark_node is
+ returned. If the ba_quiet bit is set, then no error is issued and
+ NULL_TREE is returned. */
tree
lookup_base (t, base, access, kind_ptr)
@@ -1385,9 +1387,10 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
|| TREE_CODE (functions) == OVERLOAD,
20020730);
my_friendly_assert (!optype || TYPE_P (optype), 20020730);
+ my_friendly_assert (TREE_TYPE (functions), 20020805);
- baselink = build_tree_list (NULL_TREE, NULL_TREE);
- SET_BASELINK_P (baselink);
+ baselink = build (BASELINK, TREE_TYPE (functions), NULL_TREE,
+ NULL_TREE, NULL_TREE);
BASELINK_BINFO (baselink) = binfo;
BASELINK_ACCESS_BINFO (baselink) = access_binfo;
BASELINK_FUNCTIONS (baselink) = functions;
@@ -1522,7 +1525,7 @@ lookup_field (xbasetype, name, protect, want_type)
tree rval = lookup_member (xbasetype, name, protect, want_type);
/* Ignore functions. */
- if (rval && TREE_CODE (rval) == TREE_LIST)
+ if (rval && BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -1539,7 +1542,7 @@ lookup_fnfields (xbasetype, name, protect)
tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
/* Ignore non-functions. */
- if (rval && TREE_CODE (rval) != TREE_LIST)
+ if (rval && !BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -2436,7 +2439,7 @@ setup_class_bindings (name, type_binding_p)
{
if (BASELINK_P (value_binding))
/* NAME is some overloaded functions. */
- value_binding = TREE_VALUE (value_binding);
+ value_binding = BASELINK_FUNCTIONS (value_binding);
pushdecl_class_level (value_binding);
}
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 58d1647cd68..a1b34d75c78 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1400,7 +1400,10 @@ finish_object_call_expr (fn, object, args)
}
}
- return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+ if (name_p (fn))
+ return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+ else
+ return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
/* Finish a qualified member function call using OBJECT and ARGS as
diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c
index 27bc572b3da..efeae64a711 100644
--- a/gcc/cp/spew.c
+++ b/gcc/cp/spew.c
@@ -595,8 +595,8 @@ identifier_type (decl)
if (looking_for_template && really_overloaded_fn (decl))
{
/* See through a baselink. */
- if (TREE_CODE (decl) == TREE_LIST)
- decl = TREE_VALUE (decl);
+ if (TREE_CODE (decl) == BASELINK)
+ decl = BASELINK_FUNCTIONS (decl);
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 369e46a9f25..ef870765fe8 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -964,7 +964,7 @@ really_overloaded_fn (x)
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);
return (TREE_CODE (x) == OVERLOAD
- && (TREE_CHAIN (x) != NULL_TREE
+ && (OVL_CHAIN (x)
|| DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
}
@@ -2446,8 +2446,8 @@ cxx_unsave_expr_now (tp)
}
/* Returns the kind of special function that DECL (a FUNCTION_DECL)
- is. Note that this sfk_none is zero, so this function can be used
- as a predicate to test whether or not DECL is a special function. */
+ is. Note that sfk_none is zero, so this function can be used as a
+ predicate to test whether or not DECL is a special function. */
special_function_kind
special_function_p (decl)
@@ -2476,6 +2476,22 @@ special_function_p (decl)
return sfk_none;
}
+/* Returns true if and only if NODE is a name, i.e., a node created
+ by the parser when processing an id-expression. */
+
+bool
+name_p (tree node)
+{
+ if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
+ node = TREE_OPERAND (node, 0);
+ return (/* An ordinary unqualified name. */
+ TREE_CODE (node) == IDENTIFIER_NODE
+ /* A destructor name. */
+ || TREE_CODE (node) == BIT_NOT_EXPR
+ /* A qualified name. */
+ || TREE_CODE (node) == SCOPE_REF);
+}
+
/* Returns non-zero if TYPE is a character type, including wchar_t. */
int
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 399005bc691..6ac38224a24 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1758,45 +1758,6 @@ string_conv_p (totype, exp, warn)
return 1;
}
-
-tree
-build_object_ref (datum, basetype, field)
- tree datum, basetype, field;
-{
- tree dtype;
- if (datum == error_mark_node)
- return error_mark_node;
-
- dtype = TREE_TYPE (datum);
- if (TREE_CODE (dtype) == REFERENCE_TYPE)
- dtype = TREE_TYPE (dtype);
- if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
- {
- error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
- basetype, field, dtype);
- return error_mark_node;
- }
- else if (is_aggr_type (basetype, 1))
- {
- tree binfo = NULL_TREE;
- datum = build_scoped_ref (datum, basetype, &binfo);
- return build_x_component_ref (datum, field, binfo);
- }
- return error_mark_node;
-}
-
-/* Like `build_component_ref, but uses an already found field, and converts
- from a reference. Must compute access for current_class_ref.
- Otherwise, ok. */
-
-tree
-build_component_ref_1 (datum, field, protect)
- tree datum, field;
- int protect;
-{
- return convert_from_reference
- (build_component_ref (datum, field, NULL_TREE, protect));
-}
/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
can, for example, use as an lvalue. This code used to be in
@@ -1868,342 +1829,406 @@ lookup_anon_field (t, type)
return NULL_TREE;
}
-/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.
- COMPONENT can be an IDENTIFIER_NODE that is the name of the member
- that we are interested in, or it can be a FIELD_DECL. */
+/* Build an expression representing OBJECT.MEMBER. OBJECT is an
+ expression; MEMBER is a DECL or baselink. If ACCESS_PATH is
+ non-NULL, it indicates the path to the base used to name MEMBER.
+ If PRESERVE_REFERENCE is true, the expression returned will have
+ REFERENCE_TYPE if the MEMBER does. Otherwise, the expression
+ returned will have the type referred to by the reference.
+
+ This function does not perform access control; that is either done
+ earlier by the parser when the name of MEMBER is resolved to MEMBER
+ itself, or later when overload resolution selects one of the
+ functions indicated by MEMBER. */
tree
-build_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
+build_class_member_access_expr (tree object, tree member,
+ tree access_path, bool preserve_reference)
{
- register tree basetype;
- register enum tree_code code;
- register tree field = NULL;
- register tree ref;
- tree field_type;
- int type_quals;
- tree old_datum;
- tree old_basetype;
+ tree object_type;
+ tree member_scope;
+ tree result = NULL_TREE;
- if (processing_template_decl)
- return build_min_nt (COMPONENT_REF, datum, component);
-
- if (datum == error_mark_node
- || TREE_TYPE (datum) == error_mark_node)
+ if (object == error_mark_node || member == error_mark_node)
return error_mark_node;
- /* BASETYPE holds the type of the class containing the COMPONENT. */
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
-
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
- inside it. */
- switch (TREE_CODE (datum))
- {
- case COMPOUND_EXPR:
- {
- tree value = build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect);
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (datum, 0), value);
- }
- case COND_EXPR:
- return build_conditional_expr
- (TREE_OPERAND (datum, 0),
- build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect),
- build_component_ref (TREE_OPERAND (datum, 2), component,
- basetype_path, protect));
-
- case TEMPLATE_DECL:
- error ("invalid use of `%D'", datum);
- datum = error_mark_node;
- break;
-
- default:
- break;
- }
+ my_friendly_assert (DECL_P (member) || BASELINK_P (member),
+ 20020801);
- code = TREE_CODE (basetype);
+ /* [expr.ref]
- if (code == REFERENCE_TYPE)
- {
- datum = convert_from_reference (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
- }
- if (TREE_CODE (datum) == OFFSET_REF)
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ object_type = TREE_TYPE (object);
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
{
- datum = resolve_offset_ref (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ member, object, object_type);
+ return error_mark_node;
}
- /* First, see if there is a field or component with name COMPONENT. */
- if (TREE_CODE (component) == TREE_LIST)
+ /* The standard does not seem to actually say that MEMBER must be a
+ member of OBJECT_TYPE. However, that is clearly what is
+ intended. */
+ if (DECL_P (member))
{
- /* I could not trigger this code. MvL */
- abort ();
-#ifdef DEAD
- my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
-#endif
- return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
+ member_scope = DECL_CLASS_CONTEXT (member);
+ mark_used (member);
+ if (TREE_DEPRECATED (member))
+ warn_deprecated_use (member);
+ }
+ else
+ member_scope = BINFO_TYPE (BASELINK_BINFO (member));
+ /* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
+ presently be the anonymous union. Go outwards until we find a
+ type related to OBJECT_TYPE. */
+ while (ANON_AGGR_TYPE_P (member_scope)
+ && !same_type_ignoring_top_level_qualifiers_p (member_scope,
+ object_type))
+ member_scope = TYPE_CONTEXT (member_scope);
+ if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
+ {
+ error ("`%D' is not a member of `%T'", member, object_type);
+ return error_mark_node;
}
- if (! IS_AGGR_TYPE_CODE (code))
+ /* In [expr.ref], there is an explicit list of the valid choices for
+ MEMBER. We check for each of those cases here. */
+ if (TREE_CODE (member) == VAR_DECL)
{
- if (code != ERROR_MARK)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- component, datum, basetype);
- return error_mark_node;
+ /* A static data member. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
}
+ else if (TREE_CODE (member) == FIELD_DECL)
+ {
+ /* A non-static data member. */
+ bool null_object_p;
+ int type_quals;
+ tree member_type;
- if (!complete_type_or_else (basetype, datum))
- return error_mark_node;
+ null_object_p = (TREE_CODE (object) == INDIRECT_REF
+ && integer_zerop (TREE_OPERAND (object, 0)));
- if (TREE_CODE (component) == BIT_NOT_EXPR)
- {
- if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))
+ /* Convert OBJECT to the type of MEMBER. */
+ if (!same_type_p (object_type, member_scope))
{
- error ("destructor specifier `%T::~%T' must have matching names",
- basetype, TREE_OPERAND (component, 0));
- return error_mark_node;
+ tree binfo;
+ base_kind kind;
+
+ binfo = lookup_base (access_path ? access_path : object_type,
+ member_scope, ba_ignore, &kind);
+ if (binfo == error_mark_node)
+ return error_mark_node;
+
+ /* It is invalid to use to try to get to a virtual base of a
+ NULL object. The most common cause is invalid use of
+ offsetof macro. */
+ if (null_object_p && kind == bk_via_virtual)
+ {
+ error ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ error ("(perhaps the `offsetof' macro was used incorrectly)");
+ return error_mark_node;
+ }
+
+ /* Convert to the base. */
+ object = build_base_path (PLUS_EXPR, object, binfo,
+ /*nonnull=*/1);
+ /* If we found the base successfully then we should be able
+ to convert to it successfully. */
+ my_friendly_assert (object != error_mark_node,
+ 20020801);
}
- if (! TYPE_HAS_DESTRUCTOR (basetype))
+
+ /* Issue a warning about access a member of a NULL object. */
+ if (null_object_p && CLASSTYPE_NON_POD_P (object_type))
{
- error ("type `%T' has no destructor", basetype);
+ warning ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ warning ("(perhaps the `offsetof' macro was used incorrectly)");
return error_mark_node;
}
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
- }
- /* Look up component name in the structure type definition. */
- if (TYPE_VFIELD (basetype)
- && DECL_NAME (TYPE_VFIELD (basetype)) == component)
- /* Special-case this because if we use normal lookups in an ambiguous
- hierarchy, the compiler will abort (because vptr lookups are
- not supposed to be ambiguous. */
- field = TYPE_VFIELD (basetype);
- else if (TREE_CODE (component) == FIELD_DECL)
- field = component;
- else if (TREE_CODE (component) == TYPE_DECL)
+ /* If MEMBER is from an anonymous aggregate, we have converted
+ OBJECT so that it refers to the class containing the
+ anonymous union. Generate a reference to the anonymous union
+ itself, and recur to find MEMBER. */
+ if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)))
+ {
+ tree anonymous_union;
+
+ anonymous_union = lookup_anon_field (TREE_TYPE (object),
+ DECL_CONTEXT (member));
+ object = build_class_member_access_expr (object,
+ anonymous_union,
+ /*access_path=*/NULL_TREE,
+ preserve_reference);
+ }
+
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ member_type = TREE_TYPE (member);
+ if (TREE_CODE (member_type) != REFERENCE_TYPE)
+ {
+ type_quals = (cp_type_quals (member_type)
+ | cp_type_quals (object_type));
+
+ /* A field is const (volatile) if the enclosing object, or the
+ field itself, is const (volatile). But, a mutable field is
+ not const, even within a const object. */
+ if (DECL_MUTABLE_P (member))
+ type_quals &= ~TYPE_QUAL_CONST;
+ member_type = cp_build_qualified_type (member_type, type_quals);
+ }
+
+ result = fold (build (COMPONENT_REF, member_type, object, member));
+
+ /* Mark the expression const or volatile, as appropriate. Even
+ though we've dealt with the type above, we still have to mark the
+ expression itself. */
+ if (type_quals & TYPE_QUAL_CONST)
+ TREE_READONLY (result) = 1;
+ else if (type_quals & TYPE_QUAL_VOLATILE)
+ TREE_THIS_VOLATILE (result) = 1;
+ }
+ else if (BASELINK_P (member))
{
- error ("invalid use of type decl `%#D' as expression", component);
- return error_mark_node;
+ /* The member is a (possibly overloaded) member function. */
+ tree functions;
+
+ /* If the MEMBER is exactly one static member function, then we
+ know the type of the expression. Otherwise, we must wait
+ until overload resolution has been performed. */
+ functions = BASELINK_FUNCTIONS (member);
+ if (TREE_CODE (functions) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (functions))
+ {
+ /* A static member function. */
+ result = functions;
+ mark_used (result);
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
+ }
+ else
+ /* Note that we do not convert OBJECT to the BASELINK_BINFO
+ base. That will happen when the function is called. */
+ result = build (COMPONENT_REF, unknown_type_node, object, member);
}
- else if (TREE_CODE (component) == TEMPLATE_DECL)
+ else if (TREE_CODE (member) == CONST_DECL)
{
- error ("invalid use of template `%#D' as expression", component);
- return error_mark_node;
+ /* The member is an enumerator. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
}
else
{
- tree name = component;
-
- if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- name = TREE_OPERAND (component, 0);
- else if (TREE_CODE (component) == VAR_DECL)
- name = DECL_NAME (component);
- if (TREE_CODE (component) == NAMESPACE_DECL)
- /* Source is in error, but produce a sensible diagnostic. */
- name = DECL_NAME (component);
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, name,
- protect && !VFIELD_NAME_P (name), 0);
- if (field == error_mark_node)
- return error_mark_node;
+ error ("invalid use of `%D'", member);
+ return error_mark_node;
+ }
- if (field == NULL_TREE)
- {
- /* Not found as a data field, look for it as a method. If found,
- then if this is the only possible one, return it, else
- report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, name, 1);
- if (fndecls == error_mark_node)
- return error_mark_node;
- if (fndecls)
- {
- /* If the function is unique and static, we can resolve it
- now. Otherwise, we have to wait and see what context it is
- used in; a component_ref involving a non-static member
- function can only be used in a call (expr.ref). */
-
- if (TREE_CHAIN (fndecls) == NULL_TREE
- && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)
- {
- if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
- {
- tree fndecl = TREE_VALUE (fndecls);
- enforce_access (basetype_path, fndecl);
- mark_used (fndecl);
- return fndecl;
- }
- else
- {
- /* A unique non-static member function. Other parts
- of the compiler expect something with
- unknown_type_node to be really overloaded, so
- let's oblige. */
- TREE_VALUE (fndecls)
- = ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
- }
- }
+ if (!preserve_reference)
+ /* [expr.ref]
+
+ If E2 is declared to have type "reference to T", then ... the
+ type of E1.E2 is T. */
+ result = convert_from_reference (result);
- fndecls = TREE_VALUE (fndecls);
-
- if (IDENTIFIER_TYPENAME_P (name))
- {
- /* We want for a conversion op. We need to remember
- the actual type we wanted, in case we got a set of
- templated conversion operators back. */
- fndecls = ovl_cons (OVL_CURRENT (fndecls),
- OVL_NEXT (fndecls));
- TREE_TYPE (fndecls) = TREE_TYPE (name);
- }
- else if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- fndecls = build_nt (TEMPLATE_ID_EXPR,
- fndecls, TREE_OPERAND (component, 1));
-
- ref = build (COMPONENT_REF, unknown_type_node,
- datum, fndecls);
- return ref;
- }
+ return result;
+}
- error ("`%#T' has no member named `%D'", basetype, name);
- return error_mark_node;
- }
- else if (TREE_TYPE (field) == error_mark_node)
- return error_mark_node;
+/* This function is called by the parser to process a class member
+ access expression of the form OBJECT.NAME. NAME is a node used by
+ the parser to represent a name; it is not yet a DECL. It may,
+ however, be a BASELINK where the BASELINK_FUNCTIONS is a
+ TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and
+ there is no reason to do the lookup twice, so the parser keeps the
+ BASELINK. */
- if (TREE_CODE (field) != FIELD_DECL)
- {
- if (TREE_CODE (field) == TYPE_DECL)
- pedwarn ("invalid use of type decl `%#D' as expression", field);
- else if (DECL_RTL (field) != 0)
- mark_used (field);
- else
- TREE_USED (field) = 1;
+tree
+finish_class_member_access_expr (tree object, tree name)
+{
+ tree object_type;
+ tree member;
+ tree access_path = NULL_TREE;
+
+ if (object == error_mark_node || name == error_mark_node)
+ return error_mark_node;
- /* Do evaluate the object when accessing a static member. */
- if (TREE_SIDE_EFFECTS (datum))
- field = build (COMPOUND_EXPR, TREE_TYPE (field), datum, field);
+ if (processing_template_decl)
+ return build_min_nt (COMPONENT_REF, object, name);
+
+ if (TREE_CODE (object) == OFFSET_REF)
+ object = resolve_offset_ref (object);
- return field;
- }
+ object_type = TREE_TYPE (object);
+ if (TREE_CODE (object_type) == REFERENCE_TYPE)
+ {
+ object = convert_from_reference (object);
+ object_type = TREE_TYPE (object);
}
- if (TREE_DEPRECATED (field))
- warn_deprecated_use (field);
+ /* [expr.ref]
- old_datum = datum;
- old_basetype = basetype;
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
+ {
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ name, object, object_type);
+ return error_mark_node;
+ }
- /* See if we have to do any conversions so that we pick up the field from the
- right context. */
- if (DECL_FIELD_CONTEXT (field) != basetype)
+ if (BASELINK_P (name))
{
- tree context = DECL_FIELD_CONTEXT (field);
- tree base = context;
- while (!same_type_p (base, basetype) && TYPE_NAME (base)
- && ANON_AGGR_TYPE_P (base))
- base = TYPE_CONTEXT (base);
+ /* A member function that has already been looked up. */
+ my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))
+ == TEMPLATE_ID_EXPR),
+ 20020805);
+ member = name;
+ }
+ else
+ {
+ bool is_template_id = false;
+ tree template_args = NULL_TREE;
- /* Handle base classes here... */
- if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
- base_kind kind;
- tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, &kind);
+ is_template_id = true;
+ template_args = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ }
- /* Complain about use of offsetof which will break. */
- if (TREE_CODE (datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (datum, 0))
- && kind == bk_via_virtual)
+ if (TREE_CODE (name) == SCOPE_REF)
+ {
+ tree scope;
+
+ /* A qualified name. The qualifying class or namespace `S' has
+ already been looked up; it is either a TYPE or a
+ NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE
+ or a BIT_NOT_EXPR. */
+ scope = TREE_OPERAND (name, 0);
+ name = TREE_OPERAND (name, 1);
+ my_friendly_assert ((CLASS_TYPE_P (scope)
+ || TREE_CODE (scope) == NAMESPACE_DECL),
+ 20020804);
+ my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
+ || TREE_CODE (name) == BIT_NOT_EXPR),
+ 20020804);
+
+ /* If SCOPE is a namespace, then the qualified name does not
+ name a member of OBJECT_TYPE. */
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
{
- error ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
+ error ("`%D::%D' is not a member of `%T'",
+ scope, member, object_type);
return error_mark_node;
}
- datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
- if (datum == error_mark_node)
+
+ /* Find the base of OBJECT_TYPE corresponding to SCOPE. */
+ access_path = lookup_base (object_type, scope, ba_check, NULL);
+ if (!access_path || access_path == error_mark_node)
+ return error_mark_node;
+
+ /* Look up the member. */
+ member = lookup_member (access_path, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == error_mark_node)
return error_mark_node;
}
- basetype = base;
-
- /* Handle things from anon unions here... */
- if (TYPE_NAME (context) && ANON_AGGR_TYPE_P (context))
+ else if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ /* A destructor. */
+ if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0))
+ {
+ error ("destructor specifier `%T::~%T' must have matching names",
+ object_type, TREE_OPERAND (name, 0));
+ return error_mark_node;
+ }
+ if (! TYPE_HAS_DESTRUCTOR (object_type))
+ {
+ error ("type `%T' has no destructor", object_type);
+ return error_mark_node;
+ }
+ member = CLASSTYPE_DESTRUCTORS (object_type);
+ }
+ else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
- tree subfield = lookup_anon_field (basetype, context);
- tree subdatum = build_component_ref (datum, subfield,
- basetype_path, protect);
- return build_component_ref (subdatum, field, basetype_path, protect);
+ /* An unqualified name. */
+ member = lookup_member (object_type, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == error_mark_node)
+ return error_mark_node;
+ }
+ else
+ {
+ /* The YACC parser sometimes gives us things that are not names.
+ These always indicate errors. The recursive-descent parser
+ does not do this, so this code can go away once that parser
+ replaces the YACC parser. */
+ error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ if (is_template_id)
+ {
+ tree template = member;
+
+ if (BASELINK_P (template))
+ BASELINK_FUNCTIONS (template)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (template),
+ template_args);
+ else
+ {
+ error ("`%D' is not a member template function", name);
+ return error_mark_node;
+ }
}
}
- /* Complain about other invalid uses of offsetof, even though they will
- give the right answer. Note that we complain whether or not they
- actually used the offsetof macro, since there's no way to know at this
- point. So we just give a warning, instead of a pedwarn. */
- if (protect
- && CLASSTYPE_NON_POD_P (old_basetype)
- && TREE_CODE (old_datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (old_datum, 0)))
- warning ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
-
- /* Compute the type of the field, as described in [expr.ref]. */
- type_quals = TYPE_UNQUALIFIED;
- field_type = TREE_TYPE (field);
- if (TREE_CODE (field_type) == REFERENCE_TYPE)
- /* The standard says that the type of the result should be the
- type referred to by the reference. But for now, at least, we
- do the conversion from reference type later. */
- ;
- else
- {
- type_quals = (cp_type_quals (field_type)
- | cp_type_quals (TREE_TYPE (datum)));
-
- /* A field is const (volatile) if the enclosing object, or the
- field itself, is const (volatile). But, a mutable field is
- not const, even within a const object. */
- if (DECL_MUTABLE_P (field))
- type_quals &= ~TYPE_QUAL_CONST;
- field_type = cp_build_qualified_type (field_type, type_quals);
- }
-
- ref = fold (build (COMPONENT_REF, field_type, datum, field));
-
- /* Mark the expression const or volatile, as appropriate. Even
- though we've dealt with the type above, we still have to mark the
- expression itself. */
- if (type_quals & TYPE_QUAL_CONST)
- TREE_READONLY (ref) = 1;
- else if (type_quals & TYPE_QUAL_VOLATILE)
- TREE_THIS_VOLATILE (ref) = 1;
-
- return ref;
+ return build_class_member_access_expr (object, member, access_path,
+ /*preserve_reference=*/false);
}
-/* Variant of build_component_ref for use in expressions, which should
- never have REFERENCE_TYPE. */
+/* Return an expression for the MEMBER_NAME field in the internal
+ representation of PTRMEM, a pointer-to-member function. (Each
+ pointer-to-member function type gets its own RECORD_TYPE so it is
+ more convenient to access the fields by name than by FIELD_DECL.)
+ This routine converts the NAME to a FIELD_DECL and then creates the
+ node for the complete expression. */
tree
-build_x_component_ref (datum, component, basetype_path)
- tree datum, component, basetype_path;
+build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
{
- tree t = build_component_ref (datum, component, basetype_path,
- /*protect=*/1);
-
- if (! processing_template_decl)
- t = convert_from_reference (t);
-
- return t;
+ tree ptrmem_type;
+ tree member;
+ tree member_type;
+
+ /* This code is a stripped down version of
+ build_class_member_access_expr. It does not work to use that
+ routine directly because it expects the object to be of class
+ type. */
+ ptrmem_type = TREE_TYPE (ptrmem);
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
+ member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
+ /*want_type=*/0);
+ member_type = cp_build_qualified_type (TREE_TYPE (member),
+ cp_type_quals (ptrmem_type));
+ return fold (build (COMPONENT_REF, member_type, ptrmem, member));
}
-
+
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
ERRORSTRING is the name of the operator to appear in error messages.
@@ -2505,7 +2530,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
/* Start by extracting all the information from the PMF itself. */
e3 = PFN_FROM_PTRMEMFUNC (function);
- delta = build_component_ref (function, delta_identifier, NULL_TREE, 0);
+ delta = build_ptrmemfunc_access_expr (function, delta_identifier);
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
@@ -3219,7 +3244,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
- op0 = build_component_ref (op0, pfn_identifier, NULL_TREE, 0);
+ op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
result_type = TREE_TYPE (op0);
}
@@ -3253,10 +3278,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
DELTA field is unspecified. */
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
- delta0 = build_component_ref (op0, delta_identifier,
- NULL_TREE, 0);
- delta1 = build_component_ref (op1, delta_identifier,
- NULL_TREE, 0);
+ delta0 = build_ptrmemfunc_access_expr (op0,
+ delta_identifier);
+ delta1 = build_ptrmemfunc_access_expr (op1,
+ delta_identifier);
e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
e2 = cp_build_binary_op (EQ_EXPR,
pfn0,
@@ -4191,7 +4216,7 @@ build_unary_op (code, xarg, noconvert)
}
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
- && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
+ && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
{
/* They're trying to take the address of a unique non-static
member function. This is ill-formed (except in MS-land),
@@ -4204,7 +4229,7 @@ build_unary_op (code, xarg, noconvert)
a useful error here. */
tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
- tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
+ tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
if (! flag_ms_extensions)
{
@@ -5595,8 +5620,8 @@ build_ptrmemfunc (type, pfn, force)
expand_ptrmemfunc_cst (pfn, &delta, &npfn);
else
{
- npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
- delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
+ npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
+ delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
}
/* Just adjust the DELTA field. */
@@ -5711,7 +5736,7 @@ pfn_from_ptrmemfunc (t)
return pfn;
}
- return build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ return build_ptrmemfunc_access_expr (t, pfn_identifier);
}
/* Expression EXPR is about to be implicitly converted to TYPE. Warn
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fac68e917d6..e4d7e3eb0a2 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1196,8 +1196,8 @@ build_m_component_ref (datum, component)
| cp_type_quals (TREE_TYPE (datum)));
/* There's no such thing as a mutable pointer-to-member, so
- we don't need to deal with that here like we do in
- build_component_ref. */
+ things are not as complex as they are for references to
+ non-static data members. */
field_type = cp_build_qualified_type (field_type, type_quals);
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 014919ddd33..c458f430f88 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2002-08-07 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/abi/offsetof.C: Tweak error messages.
+ * g++.old-deja/g++.mike/p10769a.C: Likewise.
+
2002-08-08 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/bitfld-3.c: New test.
diff --git a/gcc/testsuite/g++.dg/abi/offsetof.C b/gcc/testsuite/g++.dg/abi/offsetof.C
index 96f5796ec95..0085e57dd98 100644
--- a/gcc/testsuite/g++.dg/abi/offsetof.C
+++ b/gcc/testsuite/g++.dg/abi/offsetof.C
@@ -18,5 +18,5 @@ struct C: public B { };
int main ()
{
- return ((unsigned long) &((C*)0)->i) != sizeof(void*); // { dg-warning "offsetof" "" }
+ return ((unsigned long) &((C*)0)->i) != sizeof(void*); // { dg-warning "offsetof|invalid" "" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C b/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
index 3dd5dc27e0a..cb49ab7501a 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
@@ -9,7 +9,7 @@ class A {
public:
void f1a() { ok += 3; }
void f1b() { ok += 5; }
- void f2a() { ok += 7; } // gets bogus error XFAIL *-*-*
+ void f2a() { ok += 7; }
void f2b() { }
static void (*table[2][2])();
void main();