+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
#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);
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... */
`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(()) {
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;
}
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
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
#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",
#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.
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);
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);
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)
else
{
tree fnname;
+ tree fns;
fnname = ansi_opname (code);
}
/* 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
{
= 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
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);
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
+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
--- /dev/null
+// PR c++/13592
+
+struct S {
+ void operator()(int);
+};
+
+struct A {
+ template <typename> void foo();
+ S s;
+};
+
+template <typename> void A::foo() {
+ s(0);
+}