From 9f880ef94a9ea767e3ac22badec8dd198d4cfda0 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 19 Jan 2004 20:33:29 +0000 Subject: [PATCH] re PR c++/13592 (C++ parser regression) PR c++/13592 * call.c (build_field_call): Remove. (n_build_method_call): Likewise. (build_method_call): Likewise. (build_new_method_call): Do not call build_field_call. * class.c (n_build_method_call): Remove. (print_class_statistics): Do not print it. * cp-tree.h (build_method_call): Remove declaration. (finish_object_call_expr): Likewise. (build_new_1): Do not use build_method_call. * parser.c (cp_parser_postfix_expression): Use finish_call_expr when the function appearing on the right-hand-side of "." or "->" is not actually a function. * pt.c (tsubst_copy_and_build): Likewise. * semantics.c (finish_object_call_expr): Remove. PR c++/13592 * g++.dg/template/call2.C: New test. From-SVN: r76173 --- gcc/cp/ChangeLog | 18 ++++ gcc/cp/call.c | 137 -------------------------- gcc/cp/class.c | 3 - gcc/cp/cp-tree.h | 4 +- gcc/cp/init.c | 22 +++-- gcc/cp/parser.c | 18 ++-- gcc/cp/pt.c | 17 +++- gcc/cp/semantics.c | 36 ------- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/template/call2.C | 14 +++ 10 files changed, 77 insertions(+), 197 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/call2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dd4b7d17c45..976b0752fd6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2004-01-19 Mark Mitchell + + PR c++/13592 + * call.c (build_field_call): Remove. + (n_build_method_call): Likewise. + (build_method_call): Likewise. + (build_new_method_call): Do not call build_field_call. + * class.c (n_build_method_call): Remove. + (print_class_statistics): Do not print it. + * cp-tree.h (build_method_call): Remove declaration. + (finish_object_call_expr): Likewise. + (build_new_1): Do not use build_method_call. + * parser.c (cp_parser_postfix_expression): Use finish_call_expr + when the function appearing on the right-hand-side of "." or "->" + is not actually a function. + * pt.c (tsubst_copy_and_build): Likewise. + * semantics.c (finish_object_call_expr): Remove. + 2004-01-18 Mark Mitchell PR c++/13710 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7864d088206..ea4e0669fb4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA. */ #include "target.h" #include "convert.h" -static tree build_field_call (tree, tree, tree); static struct z_candidate * tourney (struct z_candidate *); static int equal_functions (tree, tree); static int joust (struct z_candidate *, struct z_candidate *, bool); @@ -128,42 +127,6 @@ build_vfield_ref (tree datum, tree type) datum, TYPE_VFIELD (type)); } -/* Build a call to a member of an object. I.e., one that overloads - operator ()(), or is a pointer-to-function or pointer-to-method. */ - -static tree -build_field_call (tree instance_ptr, tree decl, tree parms) -{ - tree instance; - - if (decl == error_mark_node || decl == NULL_TREE) - return 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_class_member_access_expr (instance, decl, - /*access_path=*/NULL_TREE, - /*preserve_reference=*/false); - - if (instance == error_mark_node) - return error_mark_node; - - if (IS_AGGR_TYPE (TREE_TYPE (instance))) - return build_new_op (CALL_EXPR, LOOKUP_NORMAL, - instance, parms, NULL_TREE); - else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE - || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) - == FUNCTION_TYPE))) - return build_function_call (instance, parms); - } - - return NULL_TREE; -} - /* Returns nonzero iff the destructor name specified in NAME (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many forms... */ @@ -342,102 +305,6 @@ build_call (tree function, tree parms) `operator()()' is defined for the type of that field, then we return that result. */ -#ifdef GATHER_STATISTICS -extern int n_build_method_call; -#endif - -tree -build_method_call (tree instance, tree name, tree parms, - tree basetype_path, int flags) -{ - tree fn; - tree object_type; - tree template_args = NULL_TREE; - bool has_template_args = false; - -#ifdef GATHER_STATISTICS - n_build_method_call++; -#endif - - if (error_operand_p (instance) - || name == error_mark_node - || parms == error_mark_node) - return error_mark_node; - - my_friendly_assert (!processing_template_decl, 20030707); - - 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"); - - if (! check_dtor_name (object_type, name)) - error - ("destructor name `~%T' does not match type `%T' of expression", - TREE_OPERAND (name, 0), object_type); - - if (! TYPE_HAS_DESTRUCTOR (complete_type (object_type))) - return convert_to_void (instance, /*implicit=*/NULL); - instance = default_conversion (instance); - instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); - return build_delete (build_pointer_type (object_type), - instance_ptr, sfk_complete_destructor, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - } - - 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=*/2); - else - fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false); - - if (fn && TREE_CODE (fn) == TREE_LIST) - { - error ("request for member `%D' is ambiguous", name); - print_candidates (fn); - return error_mark_node; - } - - /* If the name could not be found, issue an error. */ - if (!fn) - return unqualified_name_lookup_error (name); - - 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(()) { @@ -5058,9 +4925,6 @@ build_new_method_call (tree instance, tree fns, tree args, if (!BASELINK_P (fns)) { - call = build_field_call (instance_ptr, fns, args); - if (call) - goto finish; error ("call to non-function `%D'", fns); return error_mark_node; } @@ -5221,7 +5085,6 @@ build_new_method_call (tree instance, tree fns, tree args, if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance)) call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call); } - finish:; if (processing_template_decl && call != error_mark_node) return build_min_non_dep diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b376f99aa21..af5afb0c790 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -227,7 +227,6 @@ int n_vtable_searches = 0; int n_vtable_elems = 0; int n_convert_harshness = 0; int n_compute_conversion_costs = 0; -int n_build_method_call = 0; int n_inner_fields_searched = 0; #endif @@ -6288,8 +6287,6 @@ print_class_statistics (void) #ifdef GATHER_STATISTICS fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness); fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs); - fprintf (stderr, "build_method_call = %d (inner = %d)\n", - n_build_method_call, n_inner_fields_searched); if (n_vtables) { fprintf (stderr, "vtables = %d; vtable searches = %d\n", diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ac6ecdfed7c..f7d3a650878 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3299,7 +3299,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG }; #define B_CLR(A,X) ((A)[(X)>>3] &= ~(1 << ((X)&7))) #define B_TST(A,X) ((A)[(X)>>3] & (1 << ((X)&7))) -/* These are uses as bits in flags passed to build_method_call +/* These are uses as bits in flags passed to build_new_method_call to control its error reporting behavior. LOOKUP_PROTECT means flag access violations. @@ -3512,7 +3512,6 @@ extern tree build_vfield_ref (tree, tree); extern tree build_conditional_expr (tree, tree, tree); extern tree build_addr_func (tree); extern tree build_call (tree, tree); -extern tree build_method_call (tree, tree, tree, tree, int); extern bool null_ptr_cst_p (tree); extern bool sufficient_parms_p (tree); extern tree type_decays_to (tree); @@ -4062,7 +4061,6 @@ extern tree perform_koenig_lookup (tree, tree); extern tree finish_call_expr (tree, tree, bool, bool); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); -extern tree finish_object_call_expr (tree, tree, tree); extern tree finish_pseudo_destructor_expr (tree, tree, tree); extern tree finish_unary_op_expr (enum tree_code, tree); extern tree finish_compound_literal (tree, tree); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index e74a5980098..6111f6b768c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1251,8 +1251,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) from TRUE_EXP. In constructors, we don't know anything about the value being initialized. - FLAGS is just passes to `build_method_call'. See that function for - its description. */ + FLAGS is just passed to `build_new_method_call'. See that function + for its description. */ static void expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags) @@ -2031,6 +2031,7 @@ build_new_1 (tree exp) else { tree fnname; + tree fns; fnname = ansi_opname (code); @@ -2049,11 +2050,18 @@ build_new_1 (tree exp) } /* Create the argument list. */ args = tree_cons (NULL_TREE, size, placement); - /* Call the function. */ - alloc_call = build_method_call (build_dummy_object (true_type), - fnname, args, - TYPE_BINFO (true_type), - LOOKUP_NORMAL); + /* Do name-lookup to find the appropriate operator. */ + fns = lookup_fnfields (true_type, fnname, /*protect=*/2); + if (TREE_CODE (fns) == TREE_LIST) + { + error ("request for member `%D' is ambiguous", fnname); + print_candidates (fns); + return error_mark_node; + } + alloc_call = build_new_method_call (build_dummy_object (true_type), + fns, args, + /*conversion_path=*/NULL_TREE, + LOOKUP_NORMAL); } else { diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 481864b1095..a9b62d068b1 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3761,12 +3761,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) = build_min_nt (CALL_EXPR, postfix_expression, args); break; } - - postfix_expression - = (build_new_method_call - (instance, fn, args, NULL_TREE, - (idk == CP_ID_KIND_QUALIFIED - ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); + + if (BASELINK_P (fn)) + postfix_expression + = (build_new_method_call + (instance, fn, args, NULL_TREE, + (idk == CP_ID_KIND_QUALIFIED + ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); + else + postfix_expression + = finish_call_expr (postfix_expression, args, + /*disallow_virtual=*/false, + /*koenig_p=*/false); } else if (TREE_CODE (postfix_expression) == OFFSET_REF || TREE_CODE (postfix_expression) == MEMBER_REF diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 78c2b1348ab..967e9d1da8e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8279,11 +8279,18 @@ tsubst_copy_and_build (tree t, if (TREE_CODE (function) == OFFSET_REF) return build_offset_ref_call_from_tree (function, call_args); if (TREE_CODE (function) == COMPONENT_REF) - return (build_new_method_call - (TREE_OPERAND (function, 0), - TREE_OPERAND (function, 1), - call_args, NULL_TREE, - qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)); + { + if (!BASELINK_P (TREE_OPERAND (function, 1))) + return finish_call_expr (function, call_args, + /*disallow_virtual=*/false, + /*koenig_p=*/false); + else + return (build_new_method_call + (TREE_OPERAND (function, 0), + TREE_OPERAND (function, 1), + call_args, NULL_TREE, + qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)); + } return finish_call_expr (function, call_args, /*disallow_virtual=*/qualified_p, koenig_p); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 00f1a4f2fe9..059ed1591e5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1774,42 +1774,6 @@ finish_this_expr (void) return result; } -/* Finish a member function call using OBJECT and ARGS as arguments to - FN. Returns an expression for the call. */ - -tree -finish_object_call_expr (tree fn, tree object, tree args) -{ - if (DECL_DECLARES_TYPE_P (fn)) - { - if (processing_template_decl) - /* This can happen on code like: - - class X; - template void f(T t) { - t.X(); - } - - We just grab the underlying IDENTIFIER. */ - fn = DECL_NAME (fn); - else - { - error ("calling type `%T' like a method", fn); - return error_mark_node; - } - } - - if (processing_template_decl) - return build_nt (CALL_EXPR, - build_nt (COMPONENT_REF, object, fn), - args); - - if (name_p (fn)) - return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); - else - return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL); -} - /* Finish a pseudo-destructor expression. If SCOPE is NULL, the expression was of the form `OBJECT.~DESTRUCTOR' where DESTRUCTOR is the TYPE for the type given. If SCOPE is non-NULL, the expression diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9bd505d2c67..a473f27af29 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-01-19 Mark Mitchell + + PR c++/13592 + * g++.dg/template/call2.C: New test. + 2004-01-19 Eric Botcazou * gcc.dg/compat/fnptr-by-value-1_x.c, scalar-by-value-1_y.c diff --git a/gcc/testsuite/g++.dg/template/call2.C b/gcc/testsuite/g++.dg/template/call2.C new file mode 100644 index 00000000000..86d5c2e82b5 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/call2.C @@ -0,0 +1,14 @@ +// PR c++/13592 + +struct S { + void operator()(int); +}; + +struct A { + template void foo(); + S s; +}; + +template void A::foo() { + s(0); +}