diff options
-rw-r--r-- | gcc/cp/ChangeLog | 70 | ||||
-rw-r--r-- | gcc/cp/call.c | 23 | ||||
-rw-r--r-- | gcc/cp/class.c | 23 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 14 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 32 | ||||
-rw-r--r-- | gcc/cp/decl.c | 8 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 22 | ||||
-rw-r--r-- | gcc/cp/error.c | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 8 | ||||
-rw-r--r-- | gcc/cp/init.c | 36 | ||||
-rw-r--r-- | gcc/cp/method.c | 26 | ||||
-rw-r--r-- | gcc/cp/parse.y | 57 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/cp/search.c | 17 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 5 | ||||
-rw-r--r-- | gcc/cp/spew.c | 4 | ||||
-rw-r--r-- | gcc/cp/tree.c | 22 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 679 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/offsetof.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.mike/p10769a.C | 2 |
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(); |