aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-01-19 20:33:29 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-01-19 20:33:29 +0000
commit9f880ef94a9ea767e3ac22badec8dd198d4cfda0 (patch)
treede54ed902338fbf89d7510d0543652e38f2d398f
parent62e882937cf07a66f220adbb9ea1ae171db55ad5 (diff)
downloadgcc-9f880ef94a9ea767e3ac22badec8dd198d4cfda0.zip
gcc-9f880ef94a9ea767e3ac22badec8dd198d4cfda0.tar.gz
gcc-9f880ef94a9ea767e3ac22badec8dd198d4cfda0.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/call.c137
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/init.c22
-rw-r--r--gcc/cp/parser.c18
-rw-r--r--gcc/cp/pt.c17
-rw-r--r--gcc/cp/semantics.c36
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/call2.C14
10 files changed, 77 insertions, 197 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dd4b7d1..976b075 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2004-01-19 Mark Mitchell <mark@codesourcery.com>
+
+ 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 <mark@codesourcery.com>
PR c++/13710
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7864d08..ea4e066 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 b376f99..af5afb0 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 ac6ecdf..f7d3a65 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 e74a598..6111f6b 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 481864b..a9b62d0 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 78c2b13..967e9d1 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 00f1a4f..059ed15 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 <class T> 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 9bd505d..a473f27 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-01-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/13592
+ * g++.dg/template/call2.C: New test.
+
2004-01-19 Eric Botcazou <ebotcazou@libertysurf.fr>
* 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 0000000..86d5c2e82
--- /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 <typename> void foo();
+ S s;
+};
+
+template <typename> void A::foo() {
+ s(0);
+}