From 4ba126e468db5a4a6fa07d1b9483bc8f0562833b Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 1 Aug 2002 04:46:23 +0000 Subject: [PATCH] call.c (build_field_call): Do not look up the field by name. * call.c (build_field_call): Do not look up the field by name. (build_method_call): Simplify. (struct z_candidate): Add access_path and conversion_path. Remove basetype_path. (convert_class_to_reference): Adjust use of add_function_candidate. (add_candidate): Add conversion_path argument. (add_function_candidate): Use it. (add_conv_dndidate): Likewise. (build_builtin_candidate): Likewise. (add_template_candidate_real): Add conversion_path argument. (add_template_conv_candidate): Likewise. (add_template_candidate): Likewise. (build_user_type_conversion_1): Use it. (build_new_function_call): Remove name lookup code. Adjust use of add_template_candidate and add_function_candidate. (build_new_op): Likewise. (convert_like_real): Use build_special_member_call. (build_over_call): Use cand->conversion_path. (build_special_member_call): New method. (build_new_method_call): Remove name lookup code. * cp-tree.def (OFFSET_REF): Update documentation. (TEMPLATE_ID_EXPR): Likewise. * cp-tree.h (BASELINK_ACCESS_BINFO): New macro. (BASELINK_OPTYPE): Likewise. (build_new_method_call): Adjust prototype. (build_special_member_call): New method. (build_baselink): New method. (build_offset_ref_call_from_tree): Likewise. (build_call_from_tree): Likewise. (finish_qualified_call_expr): Remove. (finish_call_expr): Adjust prototype. (build_x_function_call): Remove. * cvt.c (ocp_convert): Use build_special_member_call. * decl2.c (reparse_absdcl_as_expr): Use finish_call_expr. (build_expr_from_tree): Adjust handling for TEMPLATE_ID_EXPR and CALL_EXPR. (build_offset_ref_call_from_tree): New function. (build_call_from_tree): Likewise. * init.c (expand_cleanup): Use build_special_member_call. (expand_default_init): Likewise. (build_member_call): Use finish_call_expr. (build_new_1): Use build_special_member_call. (push_base_cleanups): Likewise. * method.c (do_build_assign_ref): Likewise. * parse.y (template_id): Do not pass a COMPONENT_REF to lookup_template_function. (primary): Use parse_finish_call_epxr, not finish_call_expr. (parse_finish_call_expr): New function. * pt.c (lookup_template_function): Add assertions. * search.c (lookup_base): Allow T to be a binfo. (build_baselink): New function. (lookup_member): Use it. * semantics.c (finish_call_expr): Do not do name lookup. (finish_object_call_expr): Remove #if 0'd code. (finish_qualified_call_expr): Remove. * typeck.c (build_x_function_call): Remove. (build_static_case): Use build_special_member_call. * typeck2.c (build_functional_cast): Likewise. * g++.dg/inherit/operator1.C: New test. * g++.dg/lookup/disamb1.C: Fix typo in comment. * g++.dg/other/error1.C: Change expected error message. * g++.dg/template/conv4.C: Likewise. From-SVN: r55920 --- gcc/cp/ChangeLog | 62 +++ gcc/cp/call.c | 633 ++++++++++++++--------- gcc/cp/cp-tree.def | 27 +- gcc/cp/cp-tree.h | 24 +- gcc/cp/cvt.c | 8 +- gcc/cp/decl2.c | 150 +++++- gcc/cp/init.c | 54 +- gcc/cp/method.c | 38 +- gcc/cp/parse.y | 169 +++++- gcc/cp/pt.c | 25 +- gcc/cp/search.c | 55 +- gcc/cp/semantics.c | 119 +++-- gcc/cp/typeck.c | 312 +---------- gcc/cp/typeck2.c | 4 +- gcc/testsuite/ChangeLog | 9 +- gcc/testsuite/README.QMTEST | 5 +- gcc/testsuite/g++.dg/inherit/operator1.C | 34 ++ gcc/testsuite/g++.dg/lookup/disamb1.C | 2 +- gcc/testsuite/g++.dg/other/error1.C | 4 +- gcc/testsuite/g++.dg/template/conv4.C | 4 +- 20 files changed, 1034 insertions(+), 704 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/operator1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1b88fc58327..bb5db823651 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,65 @@ +2002-07-31 Mark Mitchell + + * call.c (build_field_call): Do not look up the field by name. + (build_method_call): Simplify. + (struct z_candidate): Add access_path and conversion_path. Remove + basetype_path. + (convert_class_to_reference): Adjust use of + add_function_candidate. + (add_candidate): Add conversion_path argument. + (add_function_candidate): Use it. + (add_conv_dndidate): Likewise. + (build_builtin_candidate): Likewise. + (add_template_candidate_real): Add conversion_path argument. + (add_template_conv_candidate): Likewise. + (add_template_candidate): Likewise. + (build_user_type_conversion_1): Use it. + (build_new_function_call): Remove name lookup code. Adjust use of + add_template_candidate and add_function_candidate. + (build_new_op): Likewise. + (convert_like_real): Use build_special_member_call. + (build_over_call): Use cand->conversion_path. + (build_special_member_call): New method. + (build_new_method_call): Remove name lookup code. + * cp-tree.def (OFFSET_REF): Update documentation. + (TEMPLATE_ID_EXPR): Likewise. + * cp-tree.h (BASELINK_ACCESS_BINFO): New macro. + (BASELINK_OPTYPE): Likewise. + (build_new_method_call): Adjust prototype. + (build_special_member_call): New method. + (build_baselink): New method. + (build_offset_ref_call_from_tree): Likewise. + (build_call_from_tree): Likewise. + (finish_qualified_call_expr): Remove. + (finish_call_expr): Adjust prototype. + (build_x_function_call): Remove. + * cvt.c (ocp_convert): Use build_special_member_call. + * decl2.c (reparse_absdcl_as_expr): Use finish_call_expr. + (build_expr_from_tree): Adjust handling for TEMPLATE_ID_EXPR and + CALL_EXPR. + (build_offset_ref_call_from_tree): New function. + (build_call_from_tree): Likewise. + * init.c (expand_cleanup): Use build_special_member_call. + (expand_default_init): Likewise. + (build_member_call): Use finish_call_expr. + (build_new_1): Use build_special_member_call. + (push_base_cleanups): Likewise. + * method.c (do_build_assign_ref): Likewise. + * parse.y (template_id): Do not pass a COMPONENT_REF to + lookup_template_function. + (primary): Use parse_finish_call_epxr, not finish_call_expr. + (parse_finish_call_expr): New function. + * pt.c (lookup_template_function): Add assertions. + * search.c (lookup_base): Allow T to be a binfo. + (build_baselink): New function. + (lookup_member): Use it. + * semantics.c (finish_call_expr): Do not do name lookup. + (finish_object_call_expr): Remove #if 0'd code. + (finish_qualified_call_expr): Remove. + * typeck.c (build_x_function_call): Remove. + (build_static_case): Use build_special_member_call. + * typeck2.c (build_functional_cast): Likewise. + 2002-07-30 Franz Sirl * lang-specs.h: Remove __GXX_ABI_VERSION, moved to gcc.c. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1599d0b993f..403d8b53ee3 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -38,9 +38,7 @@ Boston, MA 02111-1307, USA. */ extern int inhibit_warnings; -static tree build_new_method_call PARAMS ((tree, tree, tree, tree, int)); - -static tree build_field_call PARAMS ((tree, tree, tree, tree)); +static tree build_field_call PARAMS ((tree, tree, tree)); static struct z_candidate * tourney PARAMS ((struct z_candidate *)); static int equal_functions PARAMS ((tree, tree)); static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int)); @@ -64,13 +62,13 @@ static struct z_candidate * splice_viable PARAMS ((struct z_candidate *)); static int any_viable PARAMS ((struct z_candidate *)); static int any_strictly_viable PARAMS ((struct z_candidate *)); static struct z_candidate * add_template_candidate - PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int, - unification_kind_t)); + PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, + tree, tree, int, unification_kind_t)); static struct z_candidate * add_template_candidate_real - PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int, - tree, unification_kind_t)); + PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, + tree, tree, int, tree, unification_kind_t)); static struct z_candidate * add_template_conv_candidate - PARAMS ((struct z_candidate *, tree, tree, tree, tree)); + PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, tree)); static struct z_candidate * add_builtin_candidates PARAMS ((struct z_candidate *, enum tree_code, enum tree_code, tree, tree *, int)); @@ -82,9 +80,9 @@ static struct z_candidate * build_builtin_candidate PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *, int)); static struct z_candidate * add_conv_candidate - PARAMS ((struct z_candidate *, tree, tree, tree)); + PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree)); static struct z_candidate * add_function_candidate - PARAMS ((struct z_candidate *, tree, tree, tree, int)); + (struct z_candidate *, tree, tree, tree, tree, tree, int); static tree implicit_conversion PARAMS ((tree, tree, tree, int)); static tree standard_conversion PARAMS ((tree, tree, tree)); static tree reference_binding PARAMS ((tree, tree, tree, int)); @@ -93,8 +91,8 @@ static tree build_conv PARAMS ((enum tree_code, tree, tree)); static int is_subseq PARAMS ((tree, tree)); static tree maybe_handle_ref_bind PARAMS ((tree*)); static void maybe_handle_implicit_object PARAMS ((tree*)); -static struct z_candidate * add_candidate PARAMS ((struct z_candidate *, - tree, tree, int)); +static struct z_candidate *add_candidate + (struct z_candidate *, tree, tree, tree, tree, int); static tree source_type PARAMS ((tree)); static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *)); static int reference_related_p PARAMS ((tree, tree)); @@ -129,30 +127,19 @@ build_vfield_ref (datum, type) operator ()(), or is a pointer-to-function or pointer-to-method. */ static tree -build_field_call (basetype_path, instance_ptr, name, parms) - tree basetype_path, instance_ptr, name, parms; +build_field_call (tree instance_ptr, tree decl, tree parms) { - tree field, instance; + tree instance; - if (IDENTIFIER_CTOR_OR_DTOR_P (name)) - return NULL_TREE; + if (decl == error_mark_node || decl == NULL_TREE) + return decl; - /* Speed up the common case. */ - if (instance_ptr == current_class_ptr - && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE) - return NULL_TREE; - - field = lookup_field (basetype_path, name, 1, 0); - - if (field == error_mark_node || field == NULL_TREE) - return field; - - if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL) + if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL) { /* 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, field, 0); + instance = build_component_ref_1 (instance, decl, 0); if (instance == error_mark_node) return error_mark_node; @@ -476,7 +463,10 @@ build_method_call (instance, name, parms, basetype_path, flags) tree instance, name, parms, basetype_path; int flags; { - tree basetype, instance_ptr; + tree fn; + tree object_type; + tree template_args = NULL_TREE; + bool has_template_args = false; #ifdef GATHER_STATISTICS n_build_method_call++; @@ -485,7 +475,7 @@ build_method_call (instance, name, parms, basetype_path, flags) if (instance == error_mark_node || name == error_mark_node || parms == error_mark_node - || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) + || (instance && TREE_TYPE (instance) == error_mark_node)) return error_mark_node; if (processing_template_decl) @@ -508,39 +498,98 @@ build_method_call (instance, name, parms, basetype_path, flags) 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); + if (TREE_CODE (name) == BIT_NOT_EXPR) { + tree instance_ptr; + if (parms) error ("destructors take no parameters"); - basetype = TREE_TYPE (instance); - if (TREE_CODE (basetype) == REFERENCE_TYPE) - basetype = TREE_TYPE (basetype); - if (! check_dtor_name (basetype, name)) + if (! check_dtor_name (object_type, name)) error ("destructor name `~%T' does not match type `%T' of expression", - TREE_OPERAND (name, 0), basetype); + TREE_OPERAND (name, 0), object_type); - if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype))) + if (! TYPE_HAS_DESTRUCTOR (complete_type (object_type))) return cp_convert (void_type_node, instance); instance = default_conversion (instance); instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); - return build_delete (build_pointer_type (basetype), + return build_delete (build_pointer_type (object_type), instance_ptr, sfk_complete_destructor, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); } - return build_new_method_call (instance, name, parms, basetype_path, flags); + if (!CLASS_TYPE_P (object_type)) + { + if ((flags & LOOKUP_COMPLAIN) + && TREE_TYPE (instance) != error_mark_node) + error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", + name, instance, object_type); + return error_mark_node; + } + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + template_args = TREE_OPERAND (name, 1); + has_template_args = true; + name = TREE_OPERAND (name, 0); + } + if (TREE_CODE (name) == OVERLOAD) + name = DECL_NAME (get_first_fn (name)); + else if (DECL_P (name)) + name = DECL_NAME (name); + if (has_template_args) + fn = lookup_fnfields (object_type, name, /*protect=*/0); + else + fn = lookup_member (object_type, name, /*protect=*/0, + /*want_type=*/0); + + /* If the name could not be found, issue an error. */ + if (!fn) + { + unqualified_name_lookup_error (name); + return error_mark_node; + } + + if (BASELINK_P (fn) && has_template_args) + BASELINK_FUNCTIONS (fn) + = build_nt (TEMPLATE_ID_EXPR, + BASELINK_FUNCTIONS (fn), + template_args); + if (BASELINK_P (fn) && basetype_path) + BASELINK_ACCESS_BINFO (fn) = basetype_path; + + return build_new_method_call (instance, fn, parms, + /*conversion_path=*/NULL_TREE, flags); } /* New overloading code. */ struct z_candidate GTY(()) { + /* The FUNCTION_DECL that will be called if this candidate is + selected by overload resolution. */ tree fn; tree convs; tree second_conv; int viable; - tree basetype_path; + /* If FN is a member function, the binfo indicating the path used to + qualify the name of FN at the call site. This path is used to + determine whether or not FN is accessible if it is selected by + overload resolution. The DECL_CONTEXT of FN will always be a + (possibly improper) base of this binfo. */ + tree access_path; + /* If FN is a non-static member function, the binfo indicating the + subobject to which the `this' pointer should be converted if FN + is selected by overload resolution. The type pointed to the by + the `this' pointer must correspond to the most derived class + indicated by the CONVERSION_PATH. */ + tree conversion_path; tree template; tree warnings; struct z_candidate *next; @@ -981,6 +1030,8 @@ convert_class_to_reference (t, s, expr) NULL_TREE, arglist, build_reference_type (t), + TYPE_BINFO (s), + TREE_PURPOSE (conversions), LOOKUP_NORMAL, DEDUCE_CONV); @@ -1001,10 +1052,9 @@ convert_class_to_reference (t, s, expr) && reference_compatible_p (t, TREE_TYPE (t2))) candidates = add_function_candidate (candidates, f, s, arglist, + TYPE_BINFO (s), + TREE_PURPOSE (conversions), LOOKUP_NORMAL); - - if (candidates != old_candidates) - candidates->basetype_path = TYPE_BINFO (s); } } @@ -1282,16 +1332,17 @@ implicit_conversion (to, from, expr, flags) functions. */ static struct z_candidate * -add_candidate (candidates, fn, convs, viable) - struct z_candidate *candidates; - tree fn, convs; - int viable; +add_candidate (struct z_candidate *candidates, + tree fn, tree convs, tree access_path, tree + conversion_path, int viable) { struct z_candidate *cand = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate)); cand->fn = fn; cand->convs = convs; + cand->access_path = access_path; + cand->conversion_path = conversion_path; cand->viable = viable; cand->next = candidates; @@ -1306,10 +1357,10 @@ add_candidate (candidates, fn, convs, viable) comes from for purposes of overload resolution. */ static struct z_candidate * -add_function_candidate (candidates, fn, ctype, arglist, flags) - struct z_candidate *candidates; - tree fn, ctype, arglist; - int flags; +add_function_candidate (struct z_candidate *candidates, + tree fn, tree ctype, tree arglist, + tree access_path, tree conversion_path, + int flags) { tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); int i, len; @@ -1421,7 +1472,8 @@ add_function_candidate (candidates, fn, ctype, arglist, flags) } out: - return add_candidate (candidates, fn, convs, viable); + return add_candidate (candidates, fn, convs, access_path, + conversion_path, viable); } /* Create an overload candidate for the conversion function FN which will @@ -1436,9 +1488,12 @@ add_function_candidate (candidates, fn, ctype, arglist, flags) instead of the function. */ static struct z_candidate * -add_conv_candidate (candidates, fn, obj, arglist) +add_conv_candidate (candidates, fn, obj, arglist, access_path, + conversion_path) struct z_candidate *candidates; tree fn, obj, arglist; + tree access_path; + tree conversion_path; { tree totype = TREE_TYPE (TREE_TYPE (fn)); int i, len, viable, flags; @@ -1498,7 +1553,8 @@ add_conv_candidate (candidates, fn, obj, arglist) if (!sufficient_parms_p (parmnode)) viable = 0; - return add_candidate (candidates, totype, convs, viable); + return add_candidate (candidates, totype, convs, access_path, + conversion_path, viable); } static struct z_candidate * @@ -1547,7 +1603,10 @@ build_builtin_candidate (candidates, fnname, type1, type2, viable = 0; } - return add_candidate (candidates, fnname, convs, viable); + return add_candidate (candidates, fnname, convs, + /*access_path=*/NULL_TREE, + /*conversion_path=*/NULL_TREE, + viable); } static int @@ -2185,10 +2244,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags) static struct z_candidate* add_template_candidate_real (candidates, tmpl, ctype, explicit_targs, - arglist, return_type, flags, - obj, strict) + arglist, return_type, access_path, + conversion_path, flags, obj, strict) struct z_candidate *candidates; tree tmpl, ctype, explicit_targs, arglist, return_type; + tree access_path; + tree conversion_path; int flags; tree obj; unification_kind_t strict; @@ -2253,10 +2314,12 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs, if (obj != NULL_TREE) /* Aha, this is a conversion function. */ - cand = add_conv_candidate (candidates, fn, obj, arglist); + cand = add_conv_candidate (candidates, fn, obj, access_path, + conversion_path, arglist); else cand = add_function_candidate (candidates, fn, ctype, - arglist, flags); + arglist, access_path, + conversion_path, flags); if (DECL_TI_TEMPLATE (fn) != tmpl) /* This situation can occur if a member template of a template class is specialized. Then, instantiate_template might return @@ -2285,27 +2348,35 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs, static struct z_candidate * add_template_candidate (candidates, tmpl, ctype, explicit_targs, - arglist, return_type, flags, strict) + arglist, return_type, access_path, + conversion_path, flags, strict) struct z_candidate *candidates; tree tmpl, ctype, explicit_targs, arglist, return_type; + tree access_path; + tree conversion_path; int flags; unification_kind_t strict; { return add_template_candidate_real (candidates, tmpl, ctype, - explicit_targs, arglist, return_type, flags, - NULL_TREE, strict); + explicit_targs, arglist, return_type, + access_path, conversion_path, + flags, NULL_TREE, strict); } static struct z_candidate * -add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) +add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type, + access_path, conversion_path) struct z_candidate *candidates; tree tmpl, obj, arglist, return_type; + tree access_path; + tree conversion_path; { return add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE, - arglist, return_type, 0, obj, DEDUCE_CONV); + arglist, return_type, access_path, + conversion_path, 0, obj, DEDUCE_CONV); } @@ -2446,18 +2517,20 @@ build_user_type_conversion_1 (totype, expr, flags) templates = tree_cons (NULL_TREE, ctor, templates); candidates = add_template_candidate (candidates, ctor, totype, - NULL_TREE, args, NULL_TREE, flags, + NULL_TREE, args, NULL_TREE, + TYPE_BINFO (totype), + TYPE_BINFO (totype), + flags, DEDUCE_CALL); - } + } else candidates = add_function_candidate (candidates, ctor, totype, - args, flags); + args, TYPE_BINFO (totype), + TYPE_BINFO (totype), + flags); if (candidates) - { - candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); - candidates->basetype_path = TYPE_BINFO (totype); - } + candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); } if (convs) @@ -2465,7 +2538,8 @@ build_user_type_conversion_1 (totype, expr, flags) for (; convs; convs = TREE_CHAIN (convs)) { - tree fns = TREE_VALUE (convs); + tree fns; + tree conversion_path = TREE_PURPOSE (convs); int convflags = LOOKUP_NO_CONVERSION; /* If we are called to convert to a reference type, we are trying to @@ -2475,7 +2549,7 @@ build_user_type_conversion_1 (totype, expr, flags) if (TREE_CODE (totype) == REFERENCE_TYPE) convflags |= LOOKUP_NO_TEMP_BIND; - for (; fns; fns = OVL_NEXT (fns)) + for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); struct z_candidate *old_candidates = candidates; @@ -2492,12 +2566,17 @@ build_user_type_conversion_1 (totype, expr, flags) templates = tree_cons (NULL_TREE, fn, templates); candidates = add_template_candidate (candidates, fn, fromtype, NULL_TREE, - args, totype, flags, + args, totype, TYPE_BINFO (fromtype), + conversion_path, + flags, DEDUCE_CONV); } else candidates = add_function_candidate (candidates, fn, fromtype, - args, flags); + args, + TYPE_BINFO (fromtype), + conversion_path, + flags); if (candidates != old_candidates) { @@ -2506,7 +2585,6 @@ build_user_type_conversion_1 (totype, expr, flags) 0, convflags); candidates->second_conv = ics; - candidates->basetype_path = TYPE_BINFO (fromtype); if (ics == NULL_TREE) candidates->viable = 0; @@ -2517,19 +2595,7 @@ build_user_type_conversion_1 (totype, expr, flags) } if (! any_viable (candidates)) - { -#if 0 - if (flags & LOOKUP_COMPLAIN) - { - if (candidates && ! candidates->next) - /* say why this one won't work or try to be loose */; - else - error ("no viable candidates"); - } -#endif - - return 0; - } + return 0; candidates = splice_viable (candidates); cand = tourney (candidates); @@ -2609,6 +2675,9 @@ resolve_args (args) } return args; } + +/* Return an expression for a call to FN (a namespace-scope function) + with the ARGS. */ tree build_new_function_call (fn, args) @@ -2618,6 +2687,15 @@ build_new_function_call (fn, args) tree explicit_targs = NULL_TREE; int template_only = 0; + /* Check FN and ARGS. */ + my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL + || TREE_CODE (fn) == TEMPLATE_DECL + || TREE_CODE (fn) == OVERLOAD + || TREE_CODE (fn) == TEMPLATE_ID_EXPR, + 20020712); + my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST, + 20020712); + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) { explicit_targs = TREE_OPERAND (fn, 1); @@ -2625,7 +2703,8 @@ build_new_function_call (fn, args) template_only = 1; } - if (really_overloaded_fn (fn)) + if (really_overloaded_fn (fn) + || TREE_CODE (fn) == TEMPLATE_DECL) { tree t1; tree templates = NULL_TREE; @@ -2635,20 +2714,23 @@ build_new_function_call (fn, args) if (args == error_mark_node) return error_mark_node; - for (t1 = fn; t1; t1 = OVL_CHAIN (t1)) + for (t1 = fn; t1; t1 = OVL_NEXT (t1)) { - tree t = OVL_FUNCTION (t1); + tree t = OVL_CURRENT (t1); if (TREE_CODE (t) == TEMPLATE_DECL) { templates = tree_cons (NULL_TREE, t, templates); candidates = add_template_candidate - (candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE, + (candidates, t, NULL_TREE, explicit_targs, args, + NULL_TREE, + /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, DEDUCE_CALL); } else if (! template_only) candidates = add_function_candidate - (candidates, t, NULL_TREE, args, LOOKUP_NORMAL); + (candidates, t, NULL_TREE, args, /*access_path=*/NULL_TREE, + /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL); } if (! any_viable (candidates)) @@ -2656,7 +2738,7 @@ build_new_function_call (fn, args) if (candidates && ! candidates->next) return build_function_call (candidates->fn, args); error ("no matching function for call to `%D(%A)'", - DECL_NAME (OVL_FUNCTION (fn)), args); + DECL_NAME (OVL_CURRENT (fn)), args); if (candidates) print_z_candidates (candidates); return error_mark_node; @@ -2719,14 +2801,14 @@ build_object_call (obj, args) candidates = add_template_candidate (candidates, fn, base, NULL_TREE, mem_args, NULL_TREE, + TYPE_BINFO (type), + TYPE_BINFO (type), LOOKUP_NORMAL, DEDUCE_CALL); } else candidates = add_function_candidate - (candidates, fn, base, mem_args, LOOKUP_NORMAL); - - if (candidates) - candidates->basetype_path = TYPE_BINFO (type); + (candidates, fn, base, mem_args, TYPE_BINFO (type), + TYPE_BINFO (type), LOOKUP_NORMAL); } } @@ -2749,14 +2831,15 @@ build_object_call (obj, args) tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) == TEMPLATE_DECL) { - candidates = add_template_conv_candidate (candidates, - fn, - obj, - args, - totype); + candidates = (add_template_conv_candidate + (candidates, fn, obj, args, totype, + /*access_path=*/NULL_TREE, + /*conversion_path=*/NULL_TREE)); } else - candidates = add_conv_candidate (candidates, fn, obj, args); + candidates = add_conv_candidate (candidates, fn, obj, args, + /*conversion_path=*/NULL_TREE, + /*access_path=*/NULL_TREE); } } @@ -2890,9 +2973,7 @@ conditional_conversion (e1, e2) } /* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three - arguments to the conditional expression. By the time this function - is called, any suitable candidate functions are included in - CANDIDATES. */ + arguments to the conditional expression. */ tree build_conditional_expr (arg1, arg2, arg3) @@ -3331,11 +3412,16 @@ build_new_op (code, flags, arg1, arg2, arg3) candidates = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE, arglist, TREE_TYPE (fnname), + /*access_path=*/NULL_TREE, + /*conversion_path=*/NULL_TREE, flags, DEDUCE_CALL); } else candidates = add_function_candidate (candidates, fn, NULL_TREE, - arglist, flags); + arglist, + /*access_path=*/NULL_TREE, + /*conversion_path=*/NULL_TREE, + flags); } if (IS_AGGR_TYPE (TREE_TYPE (arg1))) @@ -3349,12 +3435,14 @@ build_new_op (code, flags, arg1, arg2, arg3) if (fns) { - tree basetype = BINFO_TYPE (TREE_PURPOSE (fns)); + tree conversion_path = BASELINK_BINFO (fns); + mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); - 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); tree this_arglist; + tree access_path = TYPE_BINFO (TREE_TYPE (arg1)); if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) this_arglist = mem_arglist; @@ -3366,16 +3454,17 @@ build_new_op (code, flags, arg1, arg2, arg3) /* A member template. */ templates = tree_cons (NULL_TREE, fn, templates); candidates - = add_template_candidate (candidates, fn, basetype, NULL_TREE, + = add_template_candidate (candidates, fn, + BINFO_TYPE (conversion_path), + NULL_TREE, this_arglist, TREE_TYPE (fnname), + access_path, conversion_path, flags, DEDUCE_CALL); } else candidates = add_function_candidate - (candidates, fn, basetype, this_arglist, flags); - - if (candidates) - candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1)); + (candidates, fn, BINFO_TYPE (conversion_path), this_arglist, + access_path, conversion_path, flags); } } @@ -3863,7 +3952,7 @@ convert_like_real (convs, expr, fn, argnum, inner) && (inner >= 0 || !lvalue_p (expr))) { savew = warningcount, savee = errorcount; - expr = build_new_method_call + expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype), /* Core issue 84, now a DR, says that we don't allow UDCs @@ -3945,10 +4034,10 @@ convert_like_real (convs, expr, fn, argnum, inner) type is the same class as, or a derived class of, the class of the destination [is treated as direct-initialization]. [dcl.init] */ savew = warningcount, savee = errorcount; - expr = build_new_method_call (NULL_TREE, complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (totype), - LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING); + expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, + build_tree_list (NULL_TREE, expr), + TYPE_BINFO (totype), + LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING); if (fn) { if (warningcount > savew) @@ -4207,7 +4296,7 @@ build_over_call (cand, args, flags) joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1); if (DECL_FUNCTION_MEMBER_P (fn)) - enforce_access (cand->basetype_path, fn); + enforce_access (cand->access_path, fn); if (args && TREE_CODE (args) != TREE_LIST) args = build_tree_list (NULL_TREE, args); @@ -4236,7 +4325,8 @@ build_over_call (cand, args, flags) { tree parmtype = TREE_VALUE (parm); tree argtype = TREE_TYPE (TREE_VALUE (arg)); - tree t; + tree converted_arg; + if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i))) pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers", TREE_TYPE (argtype), fn); @@ -4248,10 +4338,13 @@ build_over_call (cand, args, flags) So we can assume that anything passed as 'this' is non-null, and optimize accordingly. */ my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811); - t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))), - TREE_TYPE (parmtype), ba_ignore, NULL); - t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1); - converted_args = tree_cons (NULL_TREE, t, converted_args); + /* Convert to the base in which the function was declared. */ + my_friendly_assert (cand->conversion_path != NULL_TREE, 20020730); + converted_arg = build_base_path (PLUS_EXPR, + TREE_VALUE (arg), + cand->conversion_path, + 1); + converted_args = tree_cons (NULL_TREE, converted_arg, converted_args); parm = TREE_CHAIN (parm); arg = TREE_CHAIN (arg); ++i; @@ -4534,143 +4627,191 @@ in_charge_arg_for_name (name) return NULL_TREE; } -static tree -build_new_method_call (instance, name, args, basetype_path, flags) - tree instance, name, args, basetype_path; - int flags; +/* Build a call to a constructor, destructor, or an assignment + operator for INSTANCE, an expression with class type. NAME + indicates the special member function to call; ARGS are the + arguments. BINFO indicates the base of INSTANCE that is to be + passed as the `this' parameter to the member function called. + + FLAGS are the LOOKUP_* flags to use when processing the call. + + If NAME indicates a complete object constructor, INSTANCE may be + NULL_TREE. In this case, the caller will call build_cplus_new to + store the newly constructed object into a VAR_DECL. */ + +tree +build_special_member_call (tree instance, tree name, tree args, + tree binfo, int flags) +{ + tree fns; + /* The type of the subobject to be constructed or destroyed. */ + tree class_type; + + my_friendly_assert (name == complete_ctor_identifier + || name == base_ctor_identifier + || name == complete_dtor_identifier + || name == base_dtor_identifier + || name == deleting_dtor_identifier + || name == ansi_assopname (NOP_EXPR), + 20020712); + my_friendly_assert (binfo != NULL_TREE, 20020712); + + class_type = BINFO_TYPE (binfo); + + /* Handle the special case where INSTANCE is NULL_TREE. */ + if (name == complete_ctor_identifier && !instance) + { + instance = build_int_2 (0, 0); + TREE_TYPE (instance) = build_pointer_type (class_type); + instance = build1 (INDIRECT_REF, class_type, instance); + } + else if (name == complete_dtor_identifier + || name == base_dtor_identifier + || name == deleting_dtor_identifier) + my_friendly_assert (args == NULL_TREE, 20020712); + + my_friendly_assert (instance != NULL_TREE, 20020712); + + /* Resolve the name. */ + if (!complete_type_or_else (BINFO_TYPE (binfo), NULL_TREE)) + return error_mark_node; + + fns = lookup_fnfields (binfo, name, 1); + + /* When making a call to a constructor or destructor for a subobject + that uses virtual base classes, pass down a pointer to a VTT for + the subobject. */ + if ((name == base_ctor_identifier + || name == base_dtor_identifier) + && TYPE_USES_VIRTUAL_BASECLASSES (class_type)) + { + tree vtt; + tree sub_vtt; + + /* If the current function is a complete object constructor + or destructor, then we fetch the VTT directly. + Otherwise, we look it up using the VTT we were given. */ + vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type)); + vtt = decay_conversion (vtt); + vtt = build (COND_EXPR, TREE_TYPE (vtt), + build (EQ_EXPR, boolean_type_node, + current_in_charge_parm, integer_zero_node), + current_vtt_parm, + vtt); + if (TREE_VIA_VIRTUAL (binfo)) + binfo = binfo_for_vbase (class_type, current_class_type); + my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110); + sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt, + BINFO_SUBVTT_INDEX (binfo)); + + args = tree_cons (NULL_TREE, sub_vtt, args); + } + + return build_new_method_call (instance, fns, args, binfo, flags); +} + +/* Build a call to "INSTANCE.FN (ARGS)". */ + +tree +build_new_method_call (tree instance, tree fns, tree args, + tree conversion_path, int flags) { struct z_candidate *candidates = 0, *cand; tree explicit_targs = NULL_TREE; - tree basetype, mem_args = NULL_TREE, fns, instance_ptr; - tree pretty_name; + tree basetype = NULL_TREE; + tree access_binfo; + tree optype; + tree mem_args = NULL_TREE, instance_ptr; + tree name, pretty_name; tree user_args; tree templates = NULL_TREE; tree call; int template_only = 0; - if (TREE_CODE (name) == TEMPLATE_ID_EXPR) - { - explicit_targs = TREE_OPERAND (name, 1); - name = TREE_OPERAND (name, 0); - if (DECL_P (name)) - name = DECL_NAME (name); - else - { - if (TREE_CODE (name) == COMPONENT_REF) - name = TREE_OPERAND (name, 1); - if (TREE_CODE (name) == OVERLOAD) - name = DECL_NAME (OVL_CURRENT (name)); - } + my_friendly_assert (instance != NULL_TREE, 20020729); - template_only = 1; - } + if (instance == error_mark_node || fns == error_mark_node + || args == error_mark_node) + return error_mark_node; + /* Process the argument list. */ user_args = args; args = resolve_args (args); - if (args == error_mark_node) return error_mark_node; - if (instance == NULL_TREE) - basetype = BINFO_TYPE (basetype_path); - else + 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)); + instance_ptr = build_this (instance); + + if (!BASELINK_P (fns)) { - 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)); - - /* XXX this should be handled before we get here. */ - if (! IS_AGGR_TYPE (basetype)) - { - if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node) - error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", - name, instance, basetype); - - return error_mark_node; - } + call = build_field_call (instance_ptr, fns, args); + if (call) + return call; + error ("call to non-function `%D'", fns); + return error_mark_node; } - if (basetype_path == NULL_TREE) - basetype_path = TYPE_BINFO (basetype); + if (!conversion_path) + conversion_path = BASELINK_BINFO (fns); + access_binfo = BASELINK_ACCESS_BINFO (fns); + optype = BASELINK_OPTYPE (fns); + fns = BASELINK_FUNCTIONS (fns); - if (instance) + if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) { - instance_ptr = build_this (instance); - - if (! template_only) - { - /* XXX this should be handled before we get here. */ - fns = build_field_call (basetype_path, instance_ptr, name, args); - if (fns) - return fns; - } - } - else - { - instance_ptr = build_int_2 (0, 0); - TREE_TYPE (instance_ptr) = build_pointer_type (basetype); + explicit_targs = TREE_OPERAND (fns, 1); + fns = TREE_OPERAND (fns, 0); + template_only = 1; } - /* Callers should explicitly indicate whether they want to construct - the complete object or just the part without virtual bases. */ - my_friendly_assert (name != ctor_identifier, 20000408); - /* Similarly for destructors. */ - my_friendly_assert (name != dtor_identifier, 20000408); + my_friendly_assert (TREE_CODE (fns) == FUNCTION_DECL + || TREE_CODE (fns) == TEMPLATE_DECL + || TREE_CODE (fns) == OVERLOAD, + 20020712); + + /* XXX this should be handled before we get here. */ + if (! IS_AGGR_TYPE (basetype)) + { + if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node) + error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", + fns, instance, basetype); + + return error_mark_node; + } + + name = DECL_NAME (get_first_fn (fns)); if (IDENTIFIER_CTOR_OR_DTOR_P (name)) { - int constructor_p; - - constructor_p = (name == complete_ctor_identifier - || name == base_ctor_identifier); - pretty_name = (constructor_p - ? constructor_name (basetype) : dtor_identifier); - - /* If we're a call to a constructor or destructor for a - subobject that uses virtual base classes, then we need to - pass down a pointer to a VTT for the subobject. */ - if ((name == base_ctor_identifier - || name == base_dtor_identifier) - && TYPE_USES_VIRTUAL_BASECLASSES (basetype)) - { - tree vtt; - tree sub_vtt; - tree basebinfo = basetype_path; - - /* If the current function is a complete object constructor - or destructor, then we fetch the VTT directly. - Otherwise, we look it up using the VTT we were given. */ - vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type)); - vtt = decay_conversion (vtt); - vtt = build (COND_EXPR, TREE_TYPE (vtt), - build (EQ_EXPR, boolean_type_node, - current_in_charge_parm, integer_zero_node), - current_vtt_parm, - vtt); - if (TREE_VIA_VIRTUAL (basebinfo)) - basebinfo = binfo_for_vbase (basetype, current_class_type); - my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110); - sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt, - BINFO_SUBVTT_INDEX (basebinfo)); - - args = tree_cons (NULL_TREE, sub_vtt, args); - } + /* Callers should explicitly indicate whether they want to construct + the complete object or just the part without virtual bases. */ + my_friendly_assert (name != ctor_identifier, 20000408); + /* Similarly for destructors. */ + my_friendly_assert (name != dtor_identifier, 20000408); + + if (name == complete_ctor_identifier + || name == base_ctor_identifier) + pretty_name = constructor_name (basetype); + else + pretty_name = dtor_identifier; } else pretty_name = name; - fns = lookup_fnfields (basetype_path, name, 1); - - if (fns == error_mark_node) - return error_mark_node; if (fns) { - tree base = BINFO_TYPE (TREE_PURPOSE (fns)); - tree fn = TREE_VALUE (fns); + tree fn; + tree class_type = (conversion_path + ? BINFO_TYPE (conversion_path) + : NULL_TREE); + mem_args = tree_cons (NULL_TREE, instance_ptr, args); - for (; fn; fn = OVL_NEXT (fn)) + for (fn = fns; fn; fn = OVL_NEXT (fn)) { tree t = OVL_CURRENT (fn); tree this_arglist; @@ -4690,16 +4831,22 @@ build_new_method_call (instance, name, args, basetype_path, flags) /* A member template. */ templates = tree_cons (NULL_TREE, t, templates); candidates = - add_template_candidate (candidates, t, base, explicit_targs, - this_arglist, - TREE_TYPE (name), flags, DEDUCE_CALL); + add_template_candidate (candidates, t, + class_type, + explicit_targs, + this_arglist, optype, + access_binfo, + conversion_path, + flags, + DEDUCE_CALL); } else if (! template_only) - candidates = add_function_candidate (candidates, t, base, - this_arglist, flags); - - if (candidates) - candidates->basetype_path = basetype_path; + candidates = add_function_candidate (candidates, t, + class_type, + this_arglist, + access_binfo, + conversion_path, + flags); } } @@ -4754,9 +4901,9 @@ build_new_method_call (instance, name, args, basetype_path, flags) else { call = build_over_call (cand, args, flags); - /* Do evaluate the object parameter in a call to a static member - function. */ - if (TREE_SIDE_EFFECTS (instance)) + /* In an expression of the form `a->f()' where `f' turns out to + be a static member function, `a' is none-the-less evaluated. */ + if (instance && TREE_SIDE_EFFECTS (instance)) call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call); } diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 1bf4c0d2ec6..a70ad501412 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -23,11 +23,25 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Reference to the contents of an offset - (a value whose type is an OFFSET_TYPE). - Operand 0 is the object within which the offset is taken. - Operand 1 is the offset. The language independent OFFSET_REF - just won't work for us. */ +/* 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'. + + 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. + + 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. */ DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2) /* A pointer-to-member constant. For a pointer-to-member constant @@ -186,7 +200,8 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 2) The second is the TREE_LIST or TREE_VEC of explicitly specified arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or an OVERLOAD. If the template-id refers to a member template, the - template may be an IDENTIFIER_NODE. */ + template may be an IDENTIFIER_NODE. In an uninstantiated template, + the template may be a LOOKUP_EXPR. */ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2) /* An association between name and entity. Parameters are the scope diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b4db7be6a58..9f220186ca0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -385,10 +385,25 @@ struct tree_overload GTY(()) (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. */ +#define BASELINK_BINFO(NODE) \ + (TREE_PURPOSE (NODE)) /* The functions referred to by the BASELINK; either a FUNCTION_DECL or an OVERLOAD. */ #define BASELINK_FUNCTIONS(NODE) \ (TREE_VALUE (NODE)) +/* 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)) +/* 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)) #define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c) @@ -3676,6 +3691,8 @@ extern int sufficient_parms_p PARAMS ((tree)); extern tree type_decays_to PARAMS ((tree)); extern tree build_user_type_conversion PARAMS ((tree, tree, int)); extern tree build_new_function_call PARAMS ((tree, tree)); +extern tree build_new_method_call (tree, tree, tree, tree, int); +extern tree build_special_member_call (tree, tree, tree, tree, int); extern tree build_new_op PARAMS ((enum tree_code, int, tree, tree, tree)); extern tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree)); extern int can_convert PARAMS ((tree, tree)); @@ -3950,6 +3967,8 @@ extern void finish_file PARAMS ((void)); extern tree reparse_absdcl_as_expr PARAMS ((tree, tree)); extern tree reparse_absdcl_as_casts PARAMS ((tree, tree)); extern tree build_expr_from_tree PARAMS ((tree)); +extern tree build_offset_ref_call_from_tree (tree, tree); +extern tree build_call_from_tree (tree, tree, bool); extern tree reparse_decl_as_expr PARAMS ((tree, tree)); extern tree finish_decl_parsing PARAMS ((tree)); extern void set_decl_namespace PARAMS ((tree, tree, int)); @@ -4229,6 +4248,7 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *)); extern tree find_vbase_instance PARAMS ((tree, tree)); extern tree binfo_for_vbase PARAMS ((tree, tree)); extern tree binfo_via_virtual PARAMS ((tree, tree)); +extern tree build_baselink (tree, tree, tree, tree); /* in semantics.c */ extern void init_cp_semantics PARAMS ((void)); @@ -4281,13 +4301,12 @@ extern void finish_subobject PARAMS ((tree)); extern tree finish_parenthesized_expr PARAMS ((tree)); extern tree begin_stmt_expr PARAMS ((void)); extern tree finish_stmt_expr PARAMS ((tree)); -extern tree finish_call_expr PARAMS ((tree, tree, int)); +extern tree finish_call_expr (tree, tree, bool); extern tree finish_increment_expr PARAMS ((tree, enum tree_code)); extern tree finish_this_expr PARAMS ((void)); extern tree finish_object_call_expr PARAMS ((tree, tree, tree)); extern tree finish_qualified_object_call_expr PARAMS ((tree, tree, tree)); extern tree finish_pseudo_destructor_call_expr PARAMS ((tree, tree, tree)); -extern tree finish_qualified_call_expr PARAMS ((tree, tree)); extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree)); extern tree finish_id_expr PARAMS ((tree)); extern tree finish_fname (tree); @@ -4454,7 +4473,6 @@ extern tree build_x_component_ref PARAMS ((tree, 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)); -extern tree build_x_function_call PARAMS ((tree, tree, tree)); extern tree get_member_function_from_ptrfunc PARAMS ((tree *, tree)); extern tree build_function_call_real PARAMS ((tree, tree, int, int)); extern tree build_function_call_maybe PARAMS ((tree, tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index bd42b42c4ed..ee01a31a566 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -771,10 +771,10 @@ ocp_convert (type, expr, convtype, flags) the target with the temp (see [dcl.init]). */ ctor = build_user_type_conversion (type, ctor, flags); else - ctor = build_method_call (NULL_TREE, - complete_ctor_identifier, - build_tree_list (NULL_TREE, ctor), - TYPE_BINFO (type), flags); + ctor = build_special_member_call (NULL_TREE, + complete_ctor_identifier, + build_tree_list (NULL_TREE, ctor), + TYPE_BINFO (type), flags); if (ctor) return build_cplus_new (type, ctor); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 94694dd1939..83171984544 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3587,14 +3587,7 @@ reparse_absdcl_as_expr (type, decl) /* recurse */ decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0)); - decl = build_x_function_call (decl, NULL_TREE, current_class_ref); - - if (TREE_CODE (decl) == CALL_EXPR - && (! TREE_TYPE (decl) - || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE)) - decl = require_complete_type (decl); - - return decl; + return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false); } /* This is something of the form `int ((int)(int)(int)1)' that has turned @@ -3647,7 +3640,8 @@ reparse_absdcl_as_casts (decl, expr) return expr; } -/* Given plain tree nodes for an expression, build up the full semantics. */ +/* T is the parse tree for an expression. Return the expression after + performing semantic analysis. */ tree build_expr_from_tree (t) @@ -3671,9 +3665,29 @@ build_expr_from_tree (t) return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE); case TEMPLATE_ID_EXPR: - return (lookup_template_function - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1)))); + { + tree template; + tree args; + tree object; + + template = build_expr_from_tree (TREE_OPERAND (t, 0)); + args = build_expr_from_tree (TREE_OPERAND (t, 1)); + + if (TREE_CODE (template) == COMPONENT_REF) + { + object = TREE_OPERAND (template, 0); + template = TREE_OPERAND (template, 1); + } + else + object = NULL_TREE; + + template = lookup_template_function (template, args); + if (object) + return build (COMPONENT_REF, TREE_TYPE (template), + object, template); + else + return template; + } case INDIRECT_REF: return build_x_indirect_ref @@ -3881,9 +3895,18 @@ build_expr_from_tree (t) name = do_identifier (id, 0, args); } else if (TREE_CODE (name) == TEMPLATE_ID_EXPR - || ! really_overloaded_fn (name)) + || ! really_overloaded_fn (name)) name = build_expr_from_tree (name); - return build_x_function_call (name, args, current_class_ref); + + if (TREE_CODE (name) == OFFSET_REF) + return build_offset_ref_call_from_tree (name, args); + if (TREE_CODE (name) == COMPONENT_REF) + return finish_object_call_expr (TREE_OPERAND (name, 1), + TREE_OPERAND (name, 0), + args); + name = convert_from_reference (name); + return build_call_from_tree (name, args, + /*disallow_virtual=*/false); } case COND_EXPR: @@ -3988,6 +4011,105 @@ build_expr_from_tree (t) } } +/* FN is an OFFSET_REF indicating the function to call in parse-tree + form; it has not yet been semantically analyzed. ARGS are the + arguments to the function. They have already been semantically + analzyed. */ + +tree +build_offset_ref_call_from_tree (tree fn, tree args) +{ + tree object_addr; + + my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725); + + /* A qualified name corresponding to a non-static member + function or a pointer-to-member is represented as an + OFFSET_REF. + + For both of these function calls, FN will be an OFFSET_REF. + + struct A { void f(); }; + void A::f() { (A::f) (); } + + struct B { void g(); }; + void (B::*p)(); + void B::g() { (this->*p)(); } */ + + /* This code is not really correct (for example, it does not + handle the case that `A::f' is overloaded), but it is + historically how we have handled this situation. */ + object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0); + if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL) + fn = resolve_offset_ref (fn); + else + { + fn = TREE_OPERAND (fn, 1); + fn = get_member_function_from_ptrfunc (&object_addr, fn); + } + args = tree_cons (NULL_TREE, object_addr, args); + return build_function_call (fn, args); +} + +/* FN indicates the function to call. Name resolution has been + performed on FN. ARGS are the arguments to the function. They + have already been semantically analyzed. DISALLOW_VIRTUAL is true + if the function call should be determined at compile time, even if + FN is virtual. */ + +tree +build_call_from_tree (tree fn, tree args, bool disallow_virtual) +{ + tree template_args; + tree template_id; + tree f; + + /* Check to see that name lookup has already been performed. */ + my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725); + my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725); + + /* In the future all of this should be eliminated. Instead, + name-lookup for a member function should simply return a + baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or + TEMPLATE_ID_EXPR. */ + + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + { + template_id = fn; + template_args = TREE_OPERAND (fn, 1); + fn = TREE_OPERAND (fn, 0); + } + else + template_id = NULL_TREE; + + f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn; + /* Make sure we have a baselink (rather than simply a + FUNCTION_DECL) for a member function. */ + if (current_class_type + && ((TREE_CODE (f) == FUNCTION_DECL + && DECL_FUNCTION_MEMBER_P (f)) + || (DECL_FUNCTION_TEMPLATE_P (f) + && DECL_FUNCTION_MEMBER_P (f)))) + { + f = lookup_member (current_class_type, DECL_NAME (f), + /*protect=*/1, /*want_type=*/0); + if (f) + fn = f; + } + + if (template_id) + { + if (BASELINK_P (fn)) + BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR, + BASELINK_FUNCTIONS (fn), + template_args); + else + fn = template_id; + } + + return finish_call_expr (fn, args, disallow_virtual); +} + /* This is something of the form `int (*a)++' that has turned out to be an expr. It was only converted into parse nodes, so we need to go through and build up the semantics. Most of the work is done by diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3b99c95ee3e..421a00ac289 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -852,8 +852,11 @@ expand_cleanup_for_base (binfo, flag) return; /* Call the destructor. */ - expr = (build_scoped_method_call - (current_class_ref, binfo, base_dtor_identifier, NULL_TREE)); + expr = build_special_member_call (current_class_ref, + base_dtor_identifier, + NULL_TREE, + binfo, + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); if (flag) expr = fold (build (COND_EXPR, void_type_node, c_common_truthvalue_conversion (flag), @@ -1282,7 +1285,7 @@ expand_default_init (binfo, true_exp, exp, init, flags) else ctor_name = base_ctor_identifier; - rval = build_method_call (exp, ctor_name, parms, binfo, flags); + rval = build_special_member_call (exp, ctor_name, parms, binfo, flags); if (TREE_SIDE_EFFECTS (rval)) { if (building_stmt_tree ()) @@ -1451,15 +1454,16 @@ build_member_call (type, name, parmlist) TREE_OPERAND (name, 0) = method_name; } my_friendly_assert (is_overloaded_fn (method_name), 980519); - return build_x_function_call (name, parmlist, current_class_ref); + return finish_call_expr (name, parmlist, /*disallow_virtual=*/true); } if (DECL_P (name)) name = DECL_NAME (name); if (TREE_CODE (type) == NAMESPACE_DECL) - return build_x_function_call (lookup_namespace_name (type, name), - parmlist, current_class_ref); + return finish_call_expr (lookup_namespace_name (type, name), + parmlist, + /*disallow_virtual=*/true); if (TREE_CODE (name) == TEMPLATE_ID_EXPR) { @@ -1486,10 +1490,9 @@ build_member_call (type, name, parmlist) { tree ns = lookup_name (type, 0); if (ns && TREE_CODE (ns) == NAMESPACE_DECL) - { - return build_x_function_call (build_offset_ref (type, name), - parmlist, current_class_ref); - } + return finish_call_expr (lookup_namespace_name (ns, name), + parmlist, + /*disallow_virtual=*/true); } if (type == NULL_TREE || ! is_aggr_type (type, 1)) @@ -2326,7 +2329,8 @@ build_new_1 (exp) args)); else alloc_call = build_method_call (build_dummy_object (true_type), - fnname, args, NULL_TREE, + fnname, args, + TYPE_BINFO (true_type), LOOKUP_NORMAL); } @@ -2415,10 +2419,10 @@ build_new_1 (exp) if (has_array) init_expr = build_vec_init (init_expr, init, 0); else if (TYPE_NEEDS_CONSTRUCTING (type)) - init_expr = build_method_call (init_expr, - complete_ctor_identifier, - init, TYPE_BINFO (true_type), - LOOKUP_NORMAL); + init_expr = build_special_member_call (init_expr, + complete_ctor_identifier, + init, TYPE_BINFO (true_type), + LOOKUP_NORMAL); else { /* We are processing something like `new int (10)', which @@ -3090,7 +3094,8 @@ build_dtor_call (exp, dtor_kind, flags) default: abort (); } - return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags); + return build_method_call (exp, name, NULL_TREE, + TYPE_BINFO (TREE_TYPE (exp)), flags); } /* Generate a call to a destructor. TYPE is the type to cast ADDR to. @@ -3282,9 +3287,12 @@ push_base_cleanups () if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type)) { - expr = build_scoped_method_call (current_class_ref, vbase, - base_dtor_identifier, - NULL_TREE); + expr = build_special_member_call (current_class_ref, + base_dtor_identifier, + NULL_TREE, + vbase, + (LOOKUP_NORMAL + | LOOKUP_NONVIRTUAL)); expr = build (COND_EXPR, void_type_node, cond, expr, void_zero_node); finish_decl_cleanup (NULL_TREE, expr); @@ -3303,10 +3311,10 @@ push_base_cleanups () || TREE_VIA_VIRTUAL (base_binfo)) continue; - expr = build_scoped_method_call (current_class_ref, base_binfo, - base_dtor_identifier, - NULL_TREE); - + expr = build_special_member_call (current_class_ref, + base_dtor_identifier, + NULL_TREE, base_binfo, + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); finish_decl_cleanup (NULL_TREE, expr); } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 73cdd40b8eb..81bcc951ce3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -623,28 +623,34 @@ do_build_assign_ref (fndecl) } else { - tree fields = TYPE_FIELDS (current_class_type); - int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); - tree binfos = TYPE_BINFO_BASETYPES (current_class_type); + tree fields; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; - for (i = 0; i < n_bases; ++i) + /* Assign to each of thedirect base classes. */ + for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i) { - /* We must deal with the binfo's directly as a direct base - might be inaccessible due to ambiguity. */ - tree binfo = TREE_VEC_ELT (binfos, i); - tree src = build_base_path (PLUS_EXPR, parm, binfo, 1); - tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1); + tree binfo; + tree converted_parm; - tree expr = build_method_call (dst, - ansi_assopname (NOP_EXPR), - build_tree_list (NULL_TREE, src), - binfo, - LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); - finish_expr_stmt (expr); + binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i); + /* We must convert PARM directly to the base class + explicitly since the base class may be ambiguous. */ + converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1); + /* Call the base class assignment operator. */ + finish_expr_stmt + (build_special_member_call (current_class_ref, + ansi_assopname (NOP_EXPR), + build_tree_list (NULL_TREE, + converted_parm), + binfo, + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); } - for (; fields; fields = TREE_CHAIN (fields)) + + /* Assign to each of the non-static data members. */ + for (fields = TYPE_FIELDS (current_class_type); + fields; + fields = TREE_CHAIN (fields)) { tree comp, init, t; tree field = fields; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 94314e5564b..0fa97743734 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -131,6 +131,7 @@ static tree parse_xref_tag (tree, tree, int); static tree parse_handle_class_head (tree, tree, tree, int, int *); static void parse_decl_instantiation (tree, tree, tree); static int parse_begin_function_definition (tree, tree); +static tree parse_finish_call_expr (tree, tree, int); /* Cons up an empty parameter list. */ static inline tree @@ -1534,9 +1535,19 @@ do_id: template_id: PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket - { $$ = lookup_template_function ($3, $4); } + { + tree template_name = $3; + if (TREE_CODE (template_name) == COMPONENT_REF) + template_name = TREE_OPERAND (template_name, 1); + $$ = lookup_template_function (template_name, $4); + } | operator_name '<' do_id template_arg_list_opt template_close_bracket - { $$ = lookup_template_function ($3, $4); } + { + tree template_name = $3; + if (TREE_CODE (template_name) == COMPONENT_REF) + template_name = TREE_OPERAND (template_name, 1); + $$ = lookup_template_function (template_name, $4); + } ; object_template_id: @@ -1637,13 +1648,13 @@ primary: We could store lastiddecl in $1 to avoid another lookup, but that would result in many additional reduce/reduce conflicts. */ | notype_unqualified_id '(' nonnull_exprlist ')' - { $$ = finish_call_expr ($1, $3, 1); } + { $$ = parse_finish_call_expr ($1, $3, 1); } | notype_unqualified_id LEFT_RIGHT - { $$ = finish_call_expr ($1, NULL_TREE, 1); } + { $$ = parse_finish_call_expr ($1, NULL_TREE, 1); } | primary '(' nonnull_exprlist ')' - { $$ = finish_call_expr ($1, $3, 0); } + { $$ = parse_finish_call_expr ($1, $3, 0); } | primary LEFT_RIGHT - { $$ = finish_call_expr ($1, NULL_TREE, 0); } + { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); } | VA_ARG '(' expr_no_commas ',' type_id ')' { $$ = build_x_va_arg ($3, groktypename ($5.t)); check_for_new_type ("__builtin_va_arg", $5); } @@ -1705,9 +1716,9 @@ primary: | overqualified_id %prec HYPERUNARY { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); } | overqualified_id '(' nonnull_exprlist ')' - { $$ = finish_qualified_call_expr ($1, $3); } + { $$ = parse_finish_call_expr ($1, $3, 0); } | overqualified_id LEFT_RIGHT - { $$ = finish_qualified_call_expr ($1, NULL_TREE); } + { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); } | object object_template_id %prec UNARY { $$ = build_x_component_ref ($$, $2, NULL_TREE); @@ -4099,4 +4110,146 @@ parse_begin_function_definition (tree specs_attrs, tree declarator) return begin_function_definition (specs, attrs, declarator); } +/* Like finish_call_expr, but the name for FN has not yet been + resolved. */ + +static tree +parse_finish_call_expr (tree fn, tree args, int koenig) +{ + bool disallow_virtual; + tree template_args; + tree template_id; + tree f; + + if (TREE_CODE (fn) == OFFSET_REF) + return build_offset_ref_call_from_tree (fn, args); + + if (TREE_CODE (fn) == SCOPE_REF) + { + tree scope; + tree name; + + scope = TREE_OPERAND (fn, 0); + name = TREE_OPERAND (fn, 1); + + if (scope == error_mark_node || name == error_mark_node) + return error_mark_node; + if (!processing_template_decl) + { + if (TREE_CODE (scope) == NAMESPACE_DECL) + fn = lookup_namespace_name (scope, name); + else + { + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + template_id = name; + template_args = TREE_OPERAND (name, 1); + name = TREE_OPERAND (name, 0); + } + 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 (fn) + && current_class_type + && DERIVED_FROM_P (scope, current_class_type)) + { + scope = lookup_base (current_class_type, scope, + ba_ignore | ba_quiet, NULL); + if (scope) + { + BASELINK_ACCESS_BINFO (fn) = scope; + BASELINK_BINFO (fn) + = lookup_base (scope, + BINFO_TYPE (BASELINK_BINFO (fn)), + ba_ignore | ba_quiet, + NULL); + } + } + } + } + disallow_virtual = true; + } + else + disallow_virtual = false; + + if (koenig && TREE_CODE (fn) == IDENTIFIER_NODE) + { + /* Do the Koenig lookup. */ + fn = do_identifier (fn, 2, args); + /* If name lookup didn't find any matching declarations, we've + got an unbound identifier. */ + if (TREE_CODE (fn) == IDENTIFIER_NODE) + { + /* For some reason, do_identifier does not resolve + conversion operator names if the only matches would be + template conversion operators. So, we do it here. */ + if (IDENTIFIER_TYPENAME_P (fn) && current_class_type) + { + f = lookup_member (current_class_type, fn, + /*protect=*/1, /*want_type=*/0); + if (f) + return finish_call_expr (f, args, + /*disallow_virtual=*/false); + } + /* If the name still could not be resolved, then the program + is ill-formed. */ + if (TREE_CODE (fn) == IDENTIFIER_NODE) + { + unqualified_name_lookup_error (fn); + return error_mark_node; + } + } + else if (TREE_CODE (fn) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (fn) + || TREE_CODE (fn) == OVERLOAD) + { + tree scope = DECL_CONTEXT (get_first_fn (fn)); + if (scope && TYPE_P (scope)) + { + tree access_scope; + + if (DERIVED_FROM_P (scope, current_class_type) + && current_class_ref) + return finish_object_call_expr (fn, + current_class_ref, + args); + + access_scope = current_class_type; + while (!DERIVED_FROM_P (scope, access_scope)) + { + access_scope = TYPE_CONTEXT (access_scope); + while (DECL_P (access_scope)) + access_scope = DECL_CONTEXT (access_scope); + } + + fn = build_baselink (NULL_TREE, + TYPE_BINFO (access_scope), + fn, + /*optype=*/NULL_TREE); + } + } + } + + if (TREE_CODE (fn) == COMPONENT_REF) + /* If the parser sees `(x->y)(bar)' we get here because the + parentheses confuse the parser. Treat this like + `x->y(bar)'. */ + return finish_object_call_expr (TREE_OPERAND (fn, 1), + TREE_OPERAND (fn, 0), + args); + + if (processing_template_decl) + return build_nt (CALL_EXPR, fn, args, NULL_TREE); + + return build_call_from_tree (fn, args, disallow_virtual); +} + #include "gt-cp-parse.h" diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ca8b2c2225a..d279ed0a72d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3814,9 +3814,9 @@ add_pending_template (d) } -/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which - may be either a _DECL or an overloaded function or an - IDENTIFIER_NODE), and ARGLIST. */ +/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS and + ARGLIST. Valid choices for FNS are given in the cp-tree.def + documentation for TEMPLATE_ID_EXPR. */ tree lookup_template_function (fns, arglist) @@ -3824,20 +3824,26 @@ lookup_template_function (fns, arglist) { tree type; + if (fns == error_mark_node || arglist == error_mark_node) + return error_mark_node; + if (fns == NULL_TREE) { error ("non-template used as template"); return error_mark_node; } + my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL + || TREE_CODE (fns) == OVERLOAD + || TREE_CODE (fns) == IDENTIFIER_NODE + || TREE_CODE (fns) == LOOKUP_EXPR, + 20020730); + type = TREE_TYPE (fns); if (TREE_CODE (fns) == OVERLOAD || !type) type = unknown_type_node; - - if (processing_template_decl) - return build_min (TEMPLATE_ID_EXPR, type, fns, arglist); - else - return build (TEMPLATE_ID_EXPR, type, fns, arglist); + + return build (TEMPLATE_ID_EXPR, type, fns, arglist); } /* Within the scope of a template class S, the name S gets bound @@ -8012,8 +8018,7 @@ type_unification_real (tparms, targs, xparms, xargs, subr, my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289); my_friendly_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST, 290); - /* ARGS could be NULL (via a call from parse.y to - build_x_function_call). */ + /* ARGS could be NULL. */ if (xargs) my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291); my_friendly_assert (ntparms > 0, 292); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 692a0e3ac0a..48c4f8fbe46 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -310,6 +310,7 @@ lookup_base (t, base, access, kind_ptr) base_kind *kind_ptr; { tree binfo = NULL; /* The binfo we've found so far. */ + tree t_binfo = NULL; base_kind bk; if (t == error_mark_node || base == error_mark_node) @@ -318,13 +319,21 @@ lookup_base (t, base, access, kind_ptr) *kind_ptr = bk_not_base; return error_mark_node; } - my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127); + my_friendly_assert (TYPE_P (base), 20011127); + if (!TYPE_P (t)) + { + t_binfo = t; + t = BINFO_TYPE (t); + } + else + t_binfo = TYPE_BINFO (t); + /* Ensure that the types are instantiated. */ t = complete_type (TYPE_MAIN_VARIANT (t)); base = complete_type (TYPE_MAIN_VARIANT (base)); - bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet, + bk = lookup_base_r (t_binfo, base, access & ~ba_quiet, 0, 0, 0, &binfo); switch (bk) @@ -1361,6 +1370,32 @@ lookup_field_r (binfo, data) return NULL_TREE; } +/* Return a "baselink" which BASELINK_BINFO, BASELINK_ACCESS_BINFO, + BASELINK_FUNCTIONS, and BASELINK_OPTYPE set to BINFO, ACCESS_BINFO, + FUNCTIONS, and OPTYPE respectively. */ + +tree +build_baselink (tree binfo, tree access_binfo, tree functions, tree optype) +{ + tree baselink; + + my_friendly_assert (TREE_CODE (functions) == FUNCTION_DECL + || TREE_CODE (functions) == TEMPLATE_DECL + || TREE_CODE (functions) == TEMPLATE_ID_EXPR + || TREE_CODE (functions) == OVERLOAD, + 20020730); + my_friendly_assert (!optype || TYPE_P (optype), 20020730); + + baselink = build_tree_list (NULL_TREE, NULL_TREE); + SET_BASELINK_P (baselink); + BASELINK_BINFO (baselink) = binfo; + BASELINK_ACCESS_BINFO (baselink) = access_binfo; + BASELINK_FUNCTIONS (baselink) = functions; + BASELINK_OPTYPE (baselink) = optype; + + return baselink; +} + /* Look for a member named NAME in an inheritance lattice dominated by XBASETYPE. If PROTECT is 0 or two, we do not check access. If it is 1, we enforce accessibility. If PROTECT is zero, then, for an @@ -1470,19 +1505,9 @@ lookup_member (xbasetype, name, protect, want_type) TREE_TYPE (rval))); if (rval && is_overloaded_fn (rval)) - { - /* Note that the binfo we put in the baselink is the binfo where - we found the functions, which we need for overload - resolution, but which should not be passed to enforce_access; - rather, enforce_access wants a binfo which refers to the - scope in which we started looking for the function. This - will generally be the binfo passed into this function as - xbasetype. */ - - rval = tree_cons (rval_binfo, rval, NULL_TREE); - SET_BASELINK_P (rval); - } - + rval = build_baselink (rval_binfo, basetype_path, rval, + (IDENTIFIER_TYPENAME_P (name) + ? TREE_TYPE (name): NULL_TREE)); return rval; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ad127bf1747..7098aae6c3e 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1242,32 +1242,86 @@ finish_stmt_expr (rtl_expr) return result; } -/* Finish a call to FN with ARGS. Returns a representation of the - call. */ +/* Generate an expression for `FN (ARGS)'. + + If DISALLOW_VIRTUAL is true, the call to FN will be not generated + as a virtual call, even if FN is virtual. (This flag is set when + encountering an expression where the function name is explicitly + qualified. For example a call to `X::f' never generates a virtual + call.) + + Returns code for the call. */ tree -finish_call_expr (fn, args, koenig) - tree fn; - tree args; - int koenig; +finish_call_expr (tree fn, tree args, bool disallow_virtual) { - tree result; + if (fn == error_mark_node || args == error_mark_node) + return error_mark_node; - if (koenig) + if (processing_template_decl) + return build_nt (CALL_EXPR, fn, args, NULL_TREE); + + /* ARGS should be a list of arguments. */ + my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST, + 20020712); + + if (BASELINK_P (fn)) { - if (TREE_CODE (fn) == BIT_NOT_EXPR) - fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0)); - else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR) - fn = do_identifier (fn, 2, args); + tree object; + + /* A call to a member function. From [over.call.func]: + + If the keyword this is in scope and refers to the class of + that member function, or a derived class thereof, then the + function call is transformed into a qualified function call + using (*this) as the postfix-expression to the left of the + . operator.... [Otherwise] a contrived object of type T + becomes the implied object argument. + + This paragraph is unclear about this situation: + + struct A { void f(); }; + struct B : public A {}; + struct C : public A { void g() { B::f(); }}; + + In particular, for `B::f', this paragraph does not make clear + whether "the class of that member function" refers to `A' or + to `B'. We believe it refers to `B'. */ + if (current_class_type + && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), + current_class_type) + && current_class_ref) + object = current_class_ref; + else + { + tree representative_fn; + + representative_fn = BASELINK_FUNCTIONS (fn); + if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR) + representative_fn = TREE_OPERAND (representative_fn, 0); + representative_fn = get_first_fn (representative_fn); + object = build_dummy_object (DECL_CONTEXT (representative_fn)); + } + + return build_new_method_call (object, fn, args, NULL_TREE, + (disallow_virtual + ? LOOKUP_NONVIRTUAL : 0)); + } + else if (is_overloaded_fn (fn)) + /* A call to a namespace-scope function. */ + return build_new_function_call (fn, args); + else if (CLASS_TYPE_P (TREE_TYPE (fn))) + { + /* If the "function" is really an object of class type, it might + have an overloaded `operator ()'. */ + tree result; + result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE); + if (result) + return result; } - result = build_x_function_call (fn, args, current_class_ref); - if (TREE_CODE (result) == CALL_EXPR - && (! TREE_TYPE (result) - || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE)) - result = require_complete_type (result); - - return result; + /* A call where the function is unknown. */ + return build_function_call (fn, args); } /* Finish a call to a postfix increment or decrement or EXPR. (Which @@ -1327,14 +1381,6 @@ finish_object_call_expr (fn, object, args) tree object; tree args; { -#if 0 - /* This is a future direction of this code, but because - build_x_function_call cannot always undo what is done in - build_component_ref entirely yet, we cannot do this. */ - - tree real_fn = build_component_ref (object, fn, NULL_TREE, 1); - return finish_call_expr (real_fn, args); -#else if (DECL_DECLARES_TYPE_P (fn)) { if (processing_template_decl) @@ -1353,9 +1399,8 @@ finish_object_call_expr (fn, object, args) return error_mark_node; } } - + return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); -#endif } /* Finish a qualified member function call using OBJECT and ARGS as @@ -1396,22 +1441,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor) return cp_convert (void_type_node, object); } -/* Finish a call to a globally qualified member function FN using - ARGS. Returns an expression for the call. */ - -tree -finish_qualified_call_expr (fn, args) - tree fn; - tree args; -{ - if (processing_template_decl) - return build_min_nt (CALL_EXPR, fn, args, NULL_TREE); - else - return build_member_call (TREE_OPERAND (fn, 0), - TREE_OPERAND (fn, 1), - args); -} - /* Finish an expression of the form CODE EXPR. */ tree diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 07199d60b41..def5e687509 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2455,309 +2455,6 @@ build_array_ref (array, idx) } } -/* Build a function call to function FUNCTION with parameters PARAMS. - PARAMS is a list--a chain of TREE_LIST nodes--in which the - TREE_VALUE of each node is a parameter-expression. The PARAMS do - not include any object pointer that may be required. FUNCTION's - data type may be a function type or a pointer-to-function. - - For C++: If FUNCTION's data type is a TREE_LIST, then the tree list - is the list of possible methods that FUNCTION could conceivably - be. If the list of methods comes from a class, then it will be - a list of lists (where each element is associated with the class - that produced it), otherwise it will be a simple list (for - functions overloaded in global scope). - - In the first case, TREE_VALUE (function) is the head of one of those - lists, and TREE_PURPOSE is the name of the function. - - In the second case, TREE_PURPOSE (function) is the function's - name directly. - - DECL is the class instance variable, usually CURRENT_CLASS_REF. - - When calling a TEMPLATE_DECL, we don't require a complete return - type. */ - -tree -build_x_function_call (function, params, decl) - tree function, params, decl; -{ - tree type; - tree template_id = NULL_TREE; - int is_method; - - if (function == error_mark_node) - return error_mark_node; - - if (processing_template_decl) - return build_min_nt (CALL_EXPR, function, params, NULL_TREE); - - /* Save explicit template arguments if found */ - if (TREE_CODE (function) == TEMPLATE_ID_EXPR) - { - template_id = function; - function = TREE_OPERAND (function, 0); - } - - type = TREE_TYPE (function); - - if (TREE_CODE (type) == OFFSET_TYPE - && TREE_TYPE (type) == unknown_type_node - && TREE_CODE (function) == TREE_LIST - && TREE_CHAIN (function) == NULL_TREE) - { - /* Undo (Foo:bar)()... */ - type = TYPE_OFFSET_BASETYPE (type); - function = TREE_VALUE (function); - my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999); - my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999); - function = TREE_VALUE (function); - if (TREE_CODE (function) == OVERLOAD) - function = OVL_FUNCTION (function); - my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999); - function = DECL_NAME (function); - return build_method_call (decl, function, params, - TYPE_BINFO (type), LOOKUP_NORMAL); - } - - if (TREE_CODE (function) == OFFSET_REF - && TREE_CODE (type) != METHOD_TYPE) - function = resolve_offset_ref (function); - - if ((TREE_CODE (function) == FUNCTION_DECL - && DECL_STATIC_FUNCTION_P (function)) - || (DECL_FUNCTION_TEMPLATE_P (function) - && DECL_STATIC_FUNCTION_P (DECL_TEMPLATE_RESULT (function)))) - return build_member_call (DECL_CONTEXT (function), - template_id - ? template_id : DECL_NAME (function), - params); - - is_method = ((TREE_CODE (function) == TREE_LIST - && current_class_type != NULL_TREE - && (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) - == function)) - || (TREE_CODE (function) == OVERLOAD - && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (function))) - || TREE_CODE (function) == IDENTIFIER_NODE - || TREE_CODE (type) == METHOD_TYPE - || TYPE_PTRMEMFUNC_P (type)); - - /* A friend template. Make it look like a toplevel declaration. */ - if (! is_method && TREE_CODE (function) == TEMPLATE_DECL) - function = ovl_cons (function, NULL_TREE); - - /* Handle methods, friends, and overloaded functions, respectively. */ - if (is_method) - { - tree basetype = NULL_TREE; - - if (TREE_CODE (function) == OVERLOAD) - function = OVL_CURRENT (function); - - if (TREE_CODE (function) == FUNCTION_DECL - || DECL_FUNCTION_TEMPLATE_P (function)) - { - basetype = DECL_CONTEXT (function); - - if (DECL_NAME (function)) - function = DECL_NAME (function); - else - function = TYPE_IDENTIFIER (DECL_CONTEXT (function)); - } - else if (TREE_CODE (function) == TREE_LIST) - { - my_friendly_assert (TREE_CODE (TREE_VALUE (function)) - == FUNCTION_DECL, 312); - basetype = DECL_CONTEXT (TREE_VALUE (function)); - function = TREE_PURPOSE (function); - } - else if (TREE_CODE (function) != IDENTIFIER_NODE) - { - if (TREE_CODE (function) == OFFSET_REF) - { - if (TREE_OPERAND (function, 0)) - decl = TREE_OPERAND (function, 0); - } - /* Call via a pointer to member function. */ - if (decl == NULL_TREE) - { - error ("pointer to member function called, but not in class scope"); - return error_mark_node; - } - /* What other type of POINTER_TYPE could this be? */ - if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE - && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function)) - && TREE_CODE (function) != OFFSET_REF) - function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, - function); - goto do_x_function; - } - - /* this is an abbreviated method call. - must go through here in case it is a virtual function. - @@ Perhaps this could be optimized. */ - - if (basetype && (! current_class_type - || ! DERIVED_FROM_P (basetype, current_class_type))) - return build_member_call (basetype, function, params); - - if (decl == NULL_TREE) - { - if (current_class_type == NULL_TREE) - { - error ("object missing in call to method `%D'", function); - return error_mark_node; - } - /* Yow: call from a static member function. */ - decl = build_dummy_object (current_class_type); - } - - /* Put back explicit template arguments, if any. */ - if (template_id) - function = template_id; - return build_method_call (decl, function, params, - NULL_TREE, LOOKUP_NORMAL); - } - else if (TREE_CODE (function) == COMPONENT_REF - && type == unknown_type_node) - { - /* Undo what we did in build_component_ref. */ - decl = TREE_OPERAND (function, 0); - function = TREE_OPERAND (function, 1); - - if (TREE_CODE (function) == OVERLOAD - && TREE_TYPE (function) != unknown_type_node) - /* It was a conversion operator. We can't use DECL_NAME, as - that might refer to a templated function. */ - function = mangle_conv_op_name_for_type (TREE_TYPE (function)); - else if (TREE_CODE (function) == TEMPLATE_ID_EXPR) - { - my_friendly_assert (!template_id, 20011228); - - template_id = function; - } - else - { - function = DECL_NAME (OVL_CURRENT (function)); - - if (template_id) - { - TREE_OPERAND (template_id, 0) = function; - function = template_id; - } - } - - return build_method_call (decl, function, params, - NULL_TREE, LOOKUP_NORMAL); - } - else if (really_overloaded_fn (function)) - { - if (OVL_FUNCTION (function) == NULL_TREE) - { - error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?", - TREE_PURPOSE (function)); - return error_mark_node; - } - else - { - /* Put back explicit template arguments, if any. */ - if (template_id) - function = template_id; - return build_new_function_call (function, params); - } - } - else - /* Remove a potential OVERLOAD around it */ - function = OVL_CURRENT (function); - - do_x_function: - if (TREE_CODE (function) == OFFSET_REF) - { - /* If the component is a data element (or a virtual function), we play - games here to make things work. */ - tree decl_addr; - - if (TREE_OPERAND (function, 0)) - decl = TREE_OPERAND (function, 0); - else - decl = current_class_ref; - - decl_addr = build_unary_op (ADDR_EXPR, decl, 0); - - /* Sigh. OFFSET_REFs are being used for too many things. - They're being used both for -> and ->*, and we want to resolve - the -> cases here, but leave the ->*. We could use - resolve_offset_ref for those, too, but it would call - get_member_function_from_ptrfunc and decl_addr wouldn't get - updated properly. Nasty. */ - if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL) - function = resolve_offset_ref (function); - else - function = TREE_OPERAND (function, 1); - - function = get_member_function_from_ptrfunc (&decl_addr, function); - params = tree_cons (NULL_TREE, decl_addr, params); - return build_function_call (function, params); - } - - type = TREE_TYPE (function); - if (type != error_mark_node) - { - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - - if (IS_AGGR_TYPE (type)) - return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE); - } - - if (is_method) - { - tree fntype = TREE_TYPE (function); - tree ctypeptr = NULL_TREE; - - /* Explicitly named method? */ - if (TREE_CODE (function) == FUNCTION_DECL) - ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function)); - /* Expression with ptr-to-method type? It could either be a plain - usage, or it might be a case where the ptr-to-method is being - passed in as an argument. */ - else if (TYPE_PTRMEMFUNC_P (fntype)) - { - tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE - (TYPE_PTRMEMFUNC_FN_TYPE (fntype))); - ctypeptr = build_pointer_type (rec); - } - /* Unexpected node type? */ - else - abort (); - if (decl == NULL_TREE) - { - if (current_function_decl - && DECL_STATIC_FUNCTION_P (current_function_decl)) - error ("invalid call to member function needing `this' in static member function scope"); - else - error ("pointer to member function called, but not in class scope"); - return error_mark_node; - } - if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE - && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl))) - { - tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr), - ba_check, NULL); - - decl = build_unary_op (ADDR_EXPR, decl, 0); - decl = build_base_path (PLUS_EXPR, decl, binfo, 1); - } - else - decl = build_c_cast (ctypeptr, decl); - params = tree_cons (NULL_TREE, decl, params); - } - - return build_function_call (function, params); -} - /* Resolve a pointer to member function. INSTANCE is the object instance to use, if the member points to a virtual member. @@ -4928,7 +4625,7 @@ build_static_cast (type, expr) LOOKUP_COMPLAIN, NULL_TREE))); if (IS_AGGR_TYPE (type)) - return build_cplus_new (type, (build_method_call + return build_cplus_new (type, (build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), LOOKUP_NORMAL))); @@ -5431,9 +5128,10 @@ build_modify_expr (lhs, modifycode, rhs) /* Do the default thing */; else { - result = build_method_call (lhs, complete_ctor_identifier, - build_tree_list (NULL_TREE, rhs), - TYPE_BINFO (lhstype), LOOKUP_NORMAL); + result = build_special_member_call (lhs, complete_ctor_identifier, + build_tree_list (NULL_TREE, rhs), + TYPE_BINFO (lhstype), + LOOKUP_NORMAL); if (result == NULL_TREE) return error_mark_node; return result; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index fa6474330c9..fac68e917d6 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1309,8 +1309,8 @@ build_functional_cast (exp, parms) return get_target_expr (exp); } - exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms, - TYPE_BINFO (type), LOOKUP_NORMAL); + exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms, + TYPE_BINFO (type), LOOKUP_NORMAL); if (exp == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cad29abf7be..864248be1c5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,11 @@ -2002-07-26 Neil Booth +2002-07-31 Mark Mitchell + + * g++.dg/inherit/operator1.C: New test. + * g++.dg/lookup/disamb1.C: Fix typo in comment. + * g++.dg/other/error1.C: Change expected error message. + * g++.dg/template/conv4.C: Likewise. + +2002-07-26 Neil Booth * gcc.dg/cpp/trad/Wunused.c, gcc.dg/cpp/Wunused.c: Add test for documented behaviour. diff --git a/gcc/testsuite/README.QMTEST b/gcc/testsuite/README.QMTEST index 00fcc4f7359..1e44d939e2e 100644 --- a/gcc/testsuite/README.QMTEST +++ b/gcc/testsuite/README.QMTEST @@ -113,11 +113,12 @@ Here are some more advanced usage instructions: 1. To run a particular set of tests (rather than all of the tests), use the make variable "QMTEST_GPP_TESTS". For example, - make QMTEST_GPP_TESTS="gpp.dg" qmtest-g++ + make QMTEST_GPP_TESTS="g++.dg" qmtest-g++ will run only the tests in the g++.dg subdirectory, and: - make QMTEST_GPP_TESTS="gpp.dg.special.conpr1 gpp.old-deja.other.access2" + make QMTEST_GPP_TESTS="g++.dg/special/conpr1.C \ + g++.old-deja/g++.other/access2.C" qmtest-g++ will run only the two tests indicated. diff --git a/gcc/testsuite/g++.dg/inherit/operator1.C b/gcc/testsuite/g++.dg/inherit/operator1.C new file mode 100644 index 00000000000..6ef669c219e --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/operator1.C @@ -0,0 +1,34 @@ +// Test that conversions to base classes happen when calling +// operators. + +// { dg-do run } + +extern "C" void abort (); + +struct B1; +struct B2; + +B2* p; +B1* p2; + +struct B1 { + virtual void f () {} +}; + +struct B2 { + int i; + bool operator!() { if (this != p) abort (); return true; } + operator void*() { if (this != p) abort (); return this; } +}; + +struct B3 : public B1, public B2 { +}; + +int main () { + B3 b; + p = (B2*) &b; + p2 = (B1*) &b; + bool b1 = b; + bool b2 = !b; +} + diff --git a/gcc/testsuite/g++.dg/lookup/disamb1.C b/gcc/testsuite/g++.dg/lookup/disamb1.C index 8a3be65581b..638eb2fcdca 100644 --- a/gcc/testsuite/g++.dg/lookup/disamb1.C +++ b/gcc/testsuite/g++.dg/lookup/disamb1.C @@ -1,5 +1,5 @@ // PR c++/525 -// Bug: With -pedantic, we weren't converting this to D1* for the call. +// Bug: With -pedantic, we weren't converting this to B1* for the call. struct A { diff --git a/gcc/testsuite/g++.dg/other/error1.C b/gcc/testsuite/g++.dg/other/error1.C index 2fabd7ccf37..a55fcc60cf6 100644 --- a/gcc/testsuite/g++.dg/other/error1.C +++ b/gcc/testsuite/g++.dg/other/error1.C @@ -1,6 +1,6 @@ // { dg-do compile } -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 Free Software Foundation, Inc. // Contributed by Nathan Sidwell 18 Dec 2001 // PR 90, stupid error message `(this + 160)' @@ -10,6 +10,6 @@ class foo { int fudge[40]; int bar [40]; inline int access(int i) { - return bar(i); // { dg-error "`this->foo::bar' cannot" "" } + return bar(i); // { dg-error "call to non-function `foo::bar'" "" } } }; diff --git a/gcc/testsuite/g++.dg/template/conv4.C b/gcc/testsuite/g++.dg/template/conv4.C index 4db3dca603b..01f158aeff3 100644 --- a/gcc/testsuite/g++.dg/template/conv4.C +++ b/gcc/testsuite/g++.dg/template/conv4.C @@ -1,6 +1,6 @@ // { dg-do compile } -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 Free Software Foundation, Inc. // Contributed by Nathan Sidwell 29 Dec 2001 // PR 4361. Template conversion operators were not overloaded. @@ -21,7 +21,7 @@ struct D { int Foo () { - return operator int (); // { dg-error "no matching function" "" } + return operator int (); // { dg-error "not defined" "" } } };