From: mmitchel Date: Fri, 4 Jul 2003 05:05:19 +0000 (+0000) Subject: * call.c (build_addr_func): Handle bound pointers-to-members. X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;h=a63bc44c929fedcaa9e37ca282aad20d62d8827f;p=pf3gnuchains%2Fgcc-fork.git * call.c (build_addr_func): Handle bound pointers-to-members. (build_method_call): Do not call resolve_offset_ref. (implicit_conversion): Likewise. (resolve_scoped_fn_name): Use finish_non_static_data_member, not resolve_offset_ref. (resolve_args): Do not call resolve_offset_ref. (build_conditional_expr): Likewise. (build_new_method_call): Likewise. * cp-tree.def (OFFSET_REF): Update documentation. (cp_convert_to_pointer): Update handling of conversions from pointers to members to pointers. (ocp_convert): Do not call resolve_offset_ref. (convert_to_void): Likewise. (build_expr_type_conversion): Likewise. (delete_sanity): Likewise. (resolve_offset_ref): Simplify greatly. (build_vec_delete): Do not call resolve_offset_ref. * parser.c (cp_parser_postfix_expression): Call resolve_offset_ref if appropriate. (cp_parser_unary_expression): Use cp_parser_simple_cast_expression. (cp_parser_delete_expression): Likewise. (cp_parser_cast_expression): Likewise. (cp_parser_pm_expression): Use cp_parser_binary_op. (cp_parser_simple_cast_expression): New function. * rtti.c (build_dynamic_cast_1): Do not call resolve_offset_ref. * semantics.c (finish_increment_expr): Likewise. (finish_typeof): Likewise. * tree.c (lvalue_p_1): Do not handle OFFSET_REF. * typeck.c (require_complete_type): Do not handle OFFSET_REFs. (decay_conversion): Do not call resolve_offset_ref. (finish_class_member_access_expr): Likewise. (convert_arguments): Likewise. (build_x_binary_op): Handle DOTSTAR_EXPR. (condition_conversion): Do not call resolve_offset_ref. (unary_complex_lvalue): Likewise. (build_static_cast): Likewise. (build_reinterpret_cast): Likewise. (build_const_cast): Likewise. (build_c_cast): Likewise. (build_modify_expr): Likewise. (convert_for_assignment): Likewise. (convert_for_initialization): Likewise. * typeck2.c (build_x_arrow): Likewise. (build_m_component_ref): Simplify. * g++.old-deja/g++.jason/typeid1.C: Add dg-error marker. * g++.old-deja/g++.mike/net36.C: Tweak error messages. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68911 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ba6abbe154e..076dcbd300e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -6,6 +6,52 @@ 2003-07-03 Mark Mitchell + * call.c (build_addr_func): Handle bound pointers-to-members. + (build_method_call): Do not call resolve_offset_ref. + (implicit_conversion): Likewise. + (resolve_scoped_fn_name): Use finish_non_static_data_member, not + resolve_offset_ref. + (resolve_args): Do not call resolve_offset_ref. + (build_conditional_expr): Likewise. + (build_new_method_call): Likewise. + * cp-tree.def (OFFSET_REF): Update documentation. + (cp_convert_to_pointer): Update handling of conversions from + pointers to members to pointers. + (ocp_convert): Do not call resolve_offset_ref. + (convert_to_void): Likewise. + (build_expr_type_conversion): Likewise. + (delete_sanity): Likewise. + (resolve_offset_ref): Simplify greatly. + (build_vec_delete): Do not call resolve_offset_ref. + * parser.c (cp_parser_postfix_expression): Call resolve_offset_ref + if appropriate. + (cp_parser_unary_expression): Use + cp_parser_simple_cast_expression. + (cp_parser_delete_expression): Likewise. + (cp_parser_cast_expression): Likewise. + (cp_parser_pm_expression): Use cp_parser_binary_op. + (cp_parser_simple_cast_expression): New function. + * rtti.c (build_dynamic_cast_1): Do not call resolve_offset_ref. + * semantics.c (finish_increment_expr): Likewise. + (finish_typeof): Likewise. + * tree.c (lvalue_p_1): Do not handle OFFSET_REF. + * typeck.c (require_complete_type): Do not handle OFFSET_REFs. + (decay_conversion): Do not call resolve_offset_ref. + (finish_class_member_access_expr): Likewise. + (convert_arguments): Likewise. + (build_x_binary_op): Handle DOTSTAR_EXPR. + (condition_conversion): Do not call resolve_offset_ref. + (unary_complex_lvalue): Likewise. + (build_static_cast): Likewise. + (build_reinterpret_cast): Likewise. + (build_const_cast): Likewise. + (build_c_cast): Likewise. + (build_modify_expr): Likewise. + (convert_for_assignment): Likewise. + (convert_for_initialization): Likewise. + * typeck2.c (build_x_arrow): Likewise. + (build_m_component_ref): Simplify. + * call.c (build_scoped_method_call): Use convert_to_void. (build_method_call): Likewise. * class.c (check_field_decls): Remove dead code. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index bc1179b6cb0..e8a54dc0113 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -317,21 +317,13 @@ build_addr_func (tree function) functions. */ if (TREE_CODE (type) == METHOD_TYPE) { - tree addr; - - type = build_pointer_type (type); - - if (!cxx_mark_addressable (function)) - return error_mark_node; - - addr = build1 (ADDR_EXPR, type, function); - - /* Address of a static or external variable or function counts - as a constant */ - if (staticp (function)) - TREE_CONSTANT (addr) = 1; - - function = addr; + if (TREE_CODE (function) == OFFSET_REF) + { + tree object = build_address (TREE_OPERAND (function, 0)); + return get_member_function_from_ptrfunc (&object, + TREE_OPERAND (function, 1)); + } + function = build_address (function); } else function = default_conversion (function); @@ -477,8 +469,6 @@ build_method_call (tree instance, tree name, tree parms, if (processing_template_decl) return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE); - if (TREE_CODE (instance) == OFFSET_REF) - instance = resolve_offset_ref (instance); if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) instance = convert_from_reference (instance); object_type = TREE_TYPE (instance); @@ -1295,14 +1285,6 @@ implicit_conversion (tree to, tree from, tree expr, int flags) { tree conv; - /* Resolve expressions like `A::p' that we thought might become - pointers-to-members. */ - if (expr && TREE_CODE (expr) == OFFSET_REF) - { - expr = resolve_offset_ref (expr); - from = TREE_TYPE (expr); - } - if (from == error_mark_node || to == error_mark_node || expr == error_mark_node) return NULL_TREE; @@ -2790,7 +2772,7 @@ resolve_scoped_fn_name (tree scope, tree name) /* It might be the name of a function pointer member. */ if (fn && TREE_CODE (fn) == FIELD_DECL) - fn = resolve_offset_ref (build_offset_ref (scope, fn)); + fn = finish_non_static_data_member (fn, scope); } if (!fn) @@ -2831,8 +2813,6 @@ resolve_args (tree args) error ("invalid use of void expression"); return error_mark_node; } - else if (TREE_CODE (arg) == OFFSET_REF) - arg = resolve_offset_ref (arg); arg = convert_from_reference (arg); TREE_VALUE (t) = arg; } @@ -3565,8 +3545,6 @@ prep_operand (tree operand) { if (operand) { - if (TREE_CODE (operand) == OFFSET_REF) - operand = resolve_offset_ref (operand); operand = convert_from_reference (operand); if (CLASS_TYPE_P (TREE_TYPE (operand)) && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand))) @@ -5025,8 +5003,6 @@ build_new_method_call (tree instance, tree fns, tree args, if (args == error_mark_node) return error_mark_node; - if (TREE_CODE (instance) == OFFSET_REF) - instance = resolve_offset_ref (instance); if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) instance = convert_from_reference (instance); basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance)); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 7d657317031..e988a4e25f9 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -26,22 +26,22 @@ Boston, MA 02111-1307, USA. */ /* An OFFSET_REF is used in two situations: 1. An expression of the form `A::m' where `A' is a class and `m' is - a non-static data member. In this case, operand 0 will be a - TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL - (corresponding to `m'. + a non-static member. In this case, operand 0 will be a TYPE + (corresponding to `A') and operand 1 will be a FIELD_DECL, + BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m'). The expression is a pointer-to-member if its address is taken, but simply denotes a member of the object if its address isnot taken. In the latter case, resolve_offset_ref is used to convert it to a representation of the member referred to by the OFFSET_REF. + + This form is only used during the parsing phase; once semantic + analysis has taken place they are eliminated. 2. An expression of the form `x.*p'. In this case, operand 0 will be an expression corresponding to `x' and operand 1 will be an - expression with pointer-to-member type. - - OFFSET_REFs are only used during the parsing phase; once semantic - analysis has taken place they are eliminated. */ + expression with pointer-to-member type. */ DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2) /* A pointer-to-member constant. For a pointer-to-member constant diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 29f02226af0..24a3416d42c 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -109,24 +109,26 @@ cp_convert_to_pointer (tree type, tree expr, bool force) functions. */ if (TYPE_PTRMEMFUNC_P (intype)) { - tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype)); - tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0); - expr = build (OFFSET_REF, fntype, decl, expr); + if (pedantic || warn_pmf2ptr) + pedwarn ("converting from `%T' to `%T'", intype, type); + if (TREE_CODE (expr) == PTRMEM_CST) + expr = build_address (PTRMEM_CST_MEMBER (expr)); + else + { + tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), + 0); + decl = build_address (decl); + expr = get_member_function_from_ptrfunc (&decl, expr); + } } - - if (TREE_CODE (expr) == OFFSET_REF - && TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) - expr = resolve_offset_ref (expr); - if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) - expr = build_addr_func (expr); - if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) { - if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE) - if (pedantic || warn_pmf2ptr) - pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr), - type); - return build1 (NOP_EXPR, type, expr); + if (pedantic || warn_pmf2ptr) + pedwarn ("converting from `%T' to `%T'", intype, type); + expr = build_addr_func (expr); } + if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + return build_nop (type, expr); intype = TREE_TYPE (expr); } @@ -233,6 +235,19 @@ cp_convert_to_pointer (tree type, tree expr, bool force) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); else if (TYPE_PTRMEMFUNC_P (intype)) { + if (!warn_pmf2ptr) + { + if (TREE_CODE (expr) == PTRMEM_CST) + return cp_convert_to_pointer (type, + PTRMEM_CST_MEMBER (expr), + force); + else if (TREE_CODE (expr) == OFFSET_REF) + { + tree object = TREE_OPERAND (expr, 0); + return get_member_function_from_ptrfunc (&object, + TREE_OPERAND (expr, 1)); + } + } error ("cannot convert `%E' from type `%T' to type `%T'", expr, intype, type); return error_mark_node; @@ -663,9 +678,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags) code = TREE_CODE (type); } - if (TREE_CODE (e) == OFFSET_REF) - e = resolve_offset_ref (e); - if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); @@ -879,10 +891,6 @@ convert_to_void (tree expr, const char *implicit) break; } - case OFFSET_REF: - expr = resolve_offset_ref (expr); - break; - default:; } { @@ -1023,8 +1031,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain) && !(desires & WANT_NULL)) warning ("converting NULL to non-pointer type"); - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); expr = convert_from_reference (expr); basetype = TREE_TYPE (expr); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index f7010378897..78e84ca0056 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -481,8 +481,6 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete) return t; } - if (TREE_CODE (exp) == OFFSET_REF) - exp = resolve_offset_ref (exp); exp = convert_from_reference (exp); t = build_expr_type_conversion (WANT_POINTER, exp, true); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b88f1f24243..e1a19b1aedc 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1689,121 +1689,45 @@ build_offset_ref (tree type, tree name) tree resolve_offset_ref (tree exp) { - tree type = TREE_TYPE (exp); - tree base = NULL_TREE; tree member; - tree basetype, addr; - - if (TREE_CODE (exp) == OFFSET_REF) - { - member = TREE_OPERAND (exp, 1); - base = TREE_OPERAND (exp, 0); - } - else - { - my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214); - if (TYPE_OFFSET_BASETYPE (type) != current_class_type) - { - error ("object missing in use of pointer-to-member construct"); - return error_mark_node; - } - member = exp; - type = TREE_TYPE (type); - base = current_class_ref; - } - - if (BASELINK_P (member) || TREE_CODE (member) == TEMPLATE_ID_EXPR) - return build_unary_op (ADDR_EXPR, exp, 0); - - if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE) - { - if (!flag_ms_extensions) - /* A single non-static member, make sure we don't allow a - pointer-to-member. */ - exp = ovl_cons (member, NULL_TREE); - - return build_unary_op (ADDR_EXPR, exp, 0); - } - - if ((TREE_CODE (member) == VAR_DECL - && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)) - && ! TYPE_PTRMEM_P (TREE_TYPE (member))) - || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE) - { - /* These were static members. */ - if (!cxx_mark_addressable (member)) - return error_mark_node; - return member; - } - if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE) - return member; + my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703); - /* Syntax error can cause a member which should - have been seen as static to be grok'd as non-static. */ - if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE) - { - cp_error_at ("member `%D' is non-static but referenced as a static member", - member); - error ("at this point in file"); - return error_mark_node; - } + member = TREE_OPERAND (exp, 1); - /* The first case is really just a reference to a member of `this'. */ - if (TREE_CODE (member) == FIELD_DECL - && (base == current_class_ref || is_dummy_object (base))) - { - tree binfo = NULL_TREE; + /* If MEMBER is non-static, then the program has fallen afoul of + [expr.prim]: - /* Try to get to basetype from 'this'; if that doesn't work, - nothing will. */ - base = current_class_ref; + An id-expression that denotes a nonstatic data member or + nonstatic member function of a class can only be used: - /* First convert to the intermediate base specified, if appropriate. */ - if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) - base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo); + -- as part of a class member access (_expr.ref_) in which the + object-expression refers to the member's class or a class + derived from that class, or - return build_class_member_access_expr (base, member, - /*access_path=*/NULL_TREE, - /*preserve_reference=*/false); - } + -- to form a pointer to member (_expr.unary.op_), or - /* Ensure that we have an object. */ - if (is_dummy_object (base)) - addr = error_mark_node; - else - /* If this is a reference to a member function, then return the - address of the member function (which may involve going - through the object's vtable), otherwise, return an expression - for the dereferenced pointer-to-member construct. */ - addr = build_unary_op (ADDR_EXPR, base, 0); + -- in the body of a nonstatic member function of that class or + of a class derived from that class (_class.mfct.nonstatic_), or - if (TYPE_PTRMEM_P (TREE_TYPE (member))) + -- in a mem-initializer for a constructor for that class or for + a class derived from that class (_class.base.init_). */ + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member)) { - if (addr == error_mark_node) - { - error ("object missing in `%E'", exp); - return error_mark_node; - } - - basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member))); - basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)), - basetype, ba_check, NULL); - addr = build_base_path (PLUS_EXPR, addr, basetype, 1); - - member = cp_convert (ptrdiff_type_node, member); - - addr = build (PLUS_EXPR, build_pointer_type (type), addr, member); - return build_indirect_ref (addr, 0); + /* In Microsoft mode, treat a non-static member function as if + it were a pointer-to-member. */ + if (flag_ms_extensions) + return build_unary_op (ADDR_EXPR, exp, 0); + error ("invalid use of non-static member function `%D'", member); + return error_mark_node; } - else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) + else if (TREE_CODE (member) == FIELD_DECL) { - return get_member_function_from_ptrfunc (&addr, member); + error ("invalid use of non-static data member `%D'", member); + return error_mark_node; } - abort (); - /* NOTREACHED */ - return NULL_TREE; + + return member; } /* If DECL is a `const' declaration, and its value is a known @@ -3300,9 +3224,6 @@ build_vec_delete (tree base, tree maxindex, tree rval; tree base_init = NULL_TREE; - if (TREE_CODE (base) == OFFSET_REF) - base = resolve_offset_ref (base); - type = TREE_TYPE (base); if (TREE_CODE (type) == POINTER_TYPE) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6155af404cd..d19e40383e5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1667,6 +1667,8 @@ static bool cp_parser_check_declarator_template_parameters (cp_parser *, tree); static bool cp_parser_check_template_parameters (cp_parser *, unsigned); +static tree cp_parser_simple_cast_expression + (cp_parser *); static tree cp_parser_binary_expression (cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn); static tree cp_parser_global_scope_opt @@ -3846,8 +3848,15 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) BASELINK_ACCESS_BINFO (postfix_expression), /*preserve_reference=*/false)); else if (done) - return build_offset_ref (qualifying_class, - postfix_expression); + { + /* The expression is a qualified name whose address is not + being taken. */ + postfix_expression = build_offset_ref (qualifying_class, + postfix_expression); + if (TREE_CODE (postfix_expression) == OFFSET_REF) + postfix_expression = resolve_offset_ref (postfix_expression); + return postfix_expression; + } } } @@ -4379,7 +4388,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p) /* Save away the PEDANTIC flag. */ cp_parser_extension_opt (parser, &saved_pedantic); /* Parse the cast-expression. */ - expr = cp_parser_cast_expression (parser, /*address_p=*/false); + expr = cp_parser_simple_cast_expression (parser); /* Restore the PEDANTIC flag. */ pedantic = saved_pedantic; @@ -4394,8 +4403,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p) /* Consume the `__real__' or `__imag__' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the cast-expression. */ - expression = cp_parser_cast_expression (parser, - /*address_p=*/false); + expression = cp_parser_simple_cast_expression (parser); /* Create the complete representation. */ return build_x_unary_op ((keyword == RID_REALPART ? REALPART_EXPR : IMAGPART_EXPR), @@ -4817,7 +4825,7 @@ cp_parser_delete_expression (cp_parser* parser) array_p = false; /* Parse the cast-expression. */ - expression = cp_parser_cast_expression (parser, /*address_p=*/false); + expression = cp_parser_simple_cast_expression (parser); return delete_sanity (expression, NULL_TREE, array_p, global_scope_p); } @@ -4897,7 +4905,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p) ctor of T, but looks like a cast to function returning T without a dependent expression. */ if (!cp_parser_error_occurred (parser)) - expr = cp_parser_cast_expression (parser, /*address_p=*/false); + expr = cp_parser_simple_cast_expression (parser); if (cp_parser_parse_definitely (parser)) { @@ -4943,42 +4951,14 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p) static tree cp_parser_pm_expression (cp_parser* parser) { - tree cast_expr; - tree pm_expr; - - /* Parse the cast-expresion. */ - cast_expr = cp_parser_cast_expression (parser, /*address_p=*/false); - pm_expr = cast_expr; - /* Now look for pointer-to-member operators. */ - while (true) - { - cp_token *token; - enum cpp_ttype token_type; - - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - token_type = token->type; - /* If it's not `.*' or `->*' there's no pointer-to-member - operation. */ - if (token_type != CPP_DOT_STAR - && token_type != CPP_DEREF_STAR) - break; - - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - - /* Parse another cast-expression. */ - cast_expr = cp_parser_cast_expression (parser, /*address_p=*/false); - - /* Build the representation of the pointer-to-member - operation. */ - if (token_type == CPP_DEREF_STAR) - pm_expr = build_x_binary_op (MEMBER_REF, pm_expr, cast_expr); - else - pm_expr = build_m_component_ref (pm_expr, cast_expr); - } + static const cp_parser_token_tree_map map = { + { CPP_DEREF_STAR, MEMBER_REF }, + { CPP_DOT_STAR, DOTSTAR_EXPR }, + { CPP_EOF, ERROR_MARK } + }; - return pm_expr; + return cp_parser_binary_expression (parser, map, + cp_parser_simple_cast_expression); } /* Parse a multiplicative-expression. @@ -14025,6 +14005,14 @@ cp_parser_single_declaration (cp_parser* parser, return decl; } +/* Parse a cast-expression that is not the operand of a unary "&". */ + +static tree +cp_parser_simple_cast_expression (cp_parser *parser) +{ + return cp_parser_cast_expression (parser, /*address_p=*/false); +} + /* Parse a functional cast to TYPE. Returns an expression representing the cast. */ diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 74b7c90689c..af494e39848 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -473,12 +473,6 @@ build_dynamic_cast_1 (tree type, tree expr) goto fail; } - if (TREE_CODE (expr) == OFFSET_REF) - { - expr = resolve_offset_ref (expr); - exprtype = TREE_TYPE (expr); - } - if (tc == POINTER_TYPE) expr = convert_from_reference (expr); else if (TREE_CODE (exprtype) != REFERENCE_TYPE) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 382bee509b9..36645903196 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1476,13 +1476,6 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual) tree finish_increment_expr (tree expr, enum tree_code code) { - /* If we get an OFFSET_REF, turn it into what it really means (e.g., - a COMPONENT_REF). This way if we've got, say, a reference to a - static member that's being operated on, we don't end up trying to - find a member operator for the class it's in. */ - - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); return build_x_unary_op (code, expr); } @@ -2083,9 +2076,6 @@ finish_typeof (tree expr) return type; } - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); - type = TREE_TYPE (expr); if (!type || type == unknown_type_node) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6c6d9b94839..9f8a119a181 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -133,10 +133,6 @@ lvalue_p_1 (tree ref, /* A currently unresolved scope ref. */ case SCOPE_REF: abort (); - case OFFSET_REF: - if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) - return clk_ordinary; - /* Fall through. */ case MAX_EXPR: case MIN_EXPR: op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4900cbffb17..96b74fa43ac 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -105,17 +105,6 @@ require_complete_type (tree value) if (COMPLETE_TYPE_P (type)) return value; - /* If we see X::Y, we build an OFFSET_TYPE which has - not been laid out. Try to avoid an error by interpreting - it as this->X::Y, if reasonable. */ - if (TREE_CODE (value) == OFFSET_REF - && current_class_ref != 0 - && TREE_OPERAND (value, 0) == current_class_ref) - { - value = resolve_offset_ref (value); - return require_complete_type (value); - } - if (complete_type_or_else (type, value)) return value; else @@ -1486,11 +1475,6 @@ expr_sizeof (tree e) cxx_incomplete_type_error (e, TREE_TYPE (e)); return c_sizeof (char_type_node); } - /* It's invalid to say `sizeof (X::i)' for `i' a non-static data - member unless you're in a non-static member of X. So hand off to - resolve_offset_ref. [expr.prim] */ - else if (TREE_CODE (e) == OFFSET_REF) - e = resolve_offset_ref (e); if (e == error_mark_node) return e; @@ -1511,9 +1495,6 @@ decay_conversion (tree exp) register tree type; register enum tree_code code; - if (TREE_CODE (exp) == OFFSET_REF) - exp = resolve_offset_ref (exp); - type = TREE_TYPE (exp); code = TREE_CODE (type); @@ -1555,7 +1536,10 @@ decay_conversion (tree exp) return error_mark_node; } if (code == METHOD_TYPE) - abort (); + { + error ("invalid use of non-static member function"); + return error_mark_node; + } if (code == FUNCTION_TYPE || is_overloaded_fn (exp)) return build_unary_op (ADDR_EXPR, exp, 0); if (code == ARRAY_TYPE) @@ -2047,9 +2031,6 @@ finish_class_member_access_expr (tree object, tree name) if (processing_template_decl) return build_min_nt (COMPONENT_REF, object, name); - if (TREE_CODE (object) == OFFSET_REF) - object = resolve_offset_ref (object); - object_type = TREE_TYPE (object); if (TREE_CODE (object_type) == REFERENCE_TYPE) { @@ -2749,9 +2730,6 @@ convert_arguments (typelist, values, fndecl, flags) break; } - if (TREE_CODE (val) == OFFSET_REF) - val = resolve_offset_ref (val); - /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */ if (TREE_CODE (val) == NOP_EXPR @@ -2865,6 +2843,9 @@ build_x_binary_op (code, arg1, arg2) if (processing_template_decl) return build_min_nt (code, arg1, arg2); + if (code == DOTSTAR_EXPR) + return build_m_component_ref (arg1, arg2); + return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); } @@ -3973,8 +3954,6 @@ condition_conversion (expr) tree t; if (processing_template_decl) return expr; - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); t = perform_implicit_conversion (boolean_type_node, expr); t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); return t; @@ -4560,15 +4539,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) return error_mark_node; } if (!PTRMEM_OK_P (arg)) - { - /* This cannot form a pointer to method, so we must - resolve the offset ref, and take the address of the - result. For instance, - &(C::m) */ - arg = resolve_offset_ref (arg); - - return build_unary_op (code, arg, 0); - } + return build_unary_op (code, arg, 0); if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) { @@ -4792,9 +4763,6 @@ build_static_cast (tree type, tree expr) if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); - if (processing_template_decl) { tree t = build_min (STATIC_CAST_EXPR, type, expr); @@ -4965,9 +4933,6 @@ build_reinterpret_cast (tree type, tree expr) if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); - if (processing_template_decl) { tree t = build_min (REINTERPRET_CAST_EXPR, type, expr); @@ -5055,9 +5020,6 @@ build_const_cast (tree type, tree expr) if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); - if (processing_template_decl) { tree t = build_min (CONST_CAST_EXPR, type, expr); @@ -5139,9 +5101,6 @@ build_c_cast (tree type, tree expr) && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) value = TREE_OPERAND (value, 0); - if (TREE_CODE (value) == OFFSET_REF) - value = resolve_offset_ref (value); - if (TREE_CODE (type) == ARRAY_TYPE) { /* Allow casting from T1* to T2[] because Cfront allows it. @@ -5361,12 +5320,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond); } - case OFFSET_REF: - lhs = resolve_offset_ref (lhs); - if (lhs == error_mark_node) - return error_mark_node; - olhstype = lhstype = TREE_TYPE (lhs); - default: break; } @@ -6008,9 +5961,6 @@ convert_for_assignment (tree type, tree rhs, if (codel == OFFSET_TYPE) abort (); - if (TREE_CODE (rhs) == OFFSET_REF) - rhs = resolve_offset_ref (rhs); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); @@ -6117,13 +6067,6 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, || (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)) return error_mark_node; - if (TREE_CODE (rhs) == OFFSET_REF) - { - rhs = resolve_offset_ref (rhs); - if (rhs == error_mark_node) - return error_mark_node; - } - if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE) rhs = convert_from_reference (rhs); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 0587816f3ee..9d9ade15045 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -993,12 +993,6 @@ build_x_arrow (tree datum) if (processing_template_decl) return build_min_nt (ARROW_EXPR, rval); - if (TREE_CODE (rval) == OFFSET_REF) - { - rval = resolve_offset_ref (datum); - type = TREE_TYPE (rval); - } - if (TREE_CODE (type) == REFERENCE_TYPE) { rval = convert_from_reference (rval); @@ -1048,72 +1042,32 @@ build_x_arrow (tree datum) return error_mark_node; } -/* Make an expression to refer to the COMPONENT field of - structure or union value DATUM. COMPONENT is an arbitrary - expression. DATUM has not already been checked out to be of - aggregate type. - - For C++, COMPONENT may be a TREE_LIST. This happens when we must - return an object of member type to a method of the current class, - but there is not yet enough typing information to know which one. - As a special case, if there is only one method by that name, - it is returned. Otherwise we return an expression which other - routines will have to know how to deal with later. */ +/* Return an expression for "DATUM .* COMPONENT". DATUM has not + already been checked out to be of aggregate type. */ tree build_m_component_ref (tree datum, tree component) { - tree type; + tree ptrmem_type; tree objtype; - tree field_type; - int type_quals; + tree type; tree binfo; - if (processing_template_decl) - return build_min_nt (DOTSTAR_EXPR, datum, component); - datum = decay_conversion (datum); if (datum == error_mark_node || component == error_mark_node) return error_mark_node; - objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); - - if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) - { - type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component))); - field_type = type; - } - else if (TYPE_PTRMEM_P (TREE_TYPE (component))) - { - type = TREE_TYPE (TREE_TYPE (component)); - field_type = TREE_TYPE (type); - - /* Compute the type of the field, as described in [expr.ref]. */ - type_quals = TYPE_UNQUALIFIED; - 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))); - - /* There's no such thing as a mutable pointer-to-member, so - 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); - } - } - else + ptrmem_type = TREE_TYPE (component); + if (!TYPE_PTRMEM_P (ptrmem_type) + && !TYPE_PTRMEMFUNC_P (ptrmem_type)) { error ("`%E' cannot be used as a member pointer, since it is of type `%T'", - component, TREE_TYPE (component)); + component, ptrmem_type); return error_mark_node; } - + + objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); if (! IS_AGGR_TYPE (objtype)) { error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'", @@ -1121,21 +1075,35 @@ build_m_component_ref (tree datum, tree component) return error_mark_node; } - binfo = lookup_base (objtype, TYPE_METHOD_BASETYPE (type), + type = TYPE_PTRMEM_POINTED_TO_TYPE (ptrmem_type); + binfo = lookup_base (objtype, TYPE_PTRMEM_CLASS_TYPE (ptrmem_type), ba_check, NULL); if (!binfo) { error ("member type `%T::' incompatible with object type `%T'", - TYPE_METHOD_BASETYPE (type), objtype); + type, objtype); return error_mark_node; } else if (binfo == error_mark_node) return error_mark_node; - component = build (OFFSET_REF, field_type, datum, component); - if (TREE_CODE (type) == OFFSET_TYPE) - component = resolve_offset_ref (component); - return component; + if (TYPE_PTRMEM_P (ptrmem_type)) + { + /* Compute the type of the field, as described in [expr.ref]. + There's no such thing as a mutable pointer-to-member, so + things are not as complex as they are for references to + non-static data members. */ + type = cp_build_qualified_type (type, + (cp_type_quals (type) + | cp_type_quals (TREE_TYPE (datum)))); + + datum = build_base_path (PLUS_EXPR, build_address (datum), binfo, 1); + component = cp_convert (ptrdiff_type_node, component); + datum = build (PLUS_EXPR, build_pointer_type (type), datum, component); + return build_indirect_ref (datum, 0); + } + else + return build (OFFSET_REF, type, datum, component); } /* Return a tree node for the expression TYPENAME '(' PARMS ')'. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2db902de72..344cb3976e8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-07-03 Mark Mitchell + + * g++.old-deja/g++.jason/typeid1.C: Add dg-error marker. + * g++.old-deja/g++.mike/net36.C: Tweak error messages. + 2003-07-03 Roger Sayle * gcc.dg/builtins-25.c: New testcase. diff --git a/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C b/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C index 83a0b0924e3..678ab5fcdd5 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C @@ -8,5 +8,5 @@ int main() { double f (int); const std::type_info &r = typeid (f); std::cout << typeid(f).name() << std::endl; - std::cout << typeid(foo::f).name() << std::endl; + std::cout << typeid(foo::f).name() << std::endl; /* { dg-error "" } */ } diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net36.C b/gcc/testsuite/g++.old-deja/g++.mike/net36.C index 7d21d56bdfb..3ffa60e37a2 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/net36.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/net36.C @@ -11,7 +11,7 @@ typedef void (A::*handler) (X*); class B { public: - void setHandler(handler); // { dg-error "" } candidate + void setHandler(handler); }; void f(B* b) {