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
This commit is contained in:
Mark Mitchell 2004-01-19 20:33:29 +00:00 committed by Mark Mitchell
parent 62e882937c
commit 9f880ef94a
10 changed files with 77 additions and 197 deletions

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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
{

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);
}