This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Reorganize function-call machinery
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 31 Jul 2002 21:47:14 -0700
- Subject: C++ PATCH: Reorganize function-call machinery
- Reply-to: mark at codesourcery dot com
This patch (in preparation for the new parser) moves name lookup
towards the parser (where it should be) when processing function call
expressions. There is now a reasonably clear separation between the
routines that process parse-tree nodes (SCOPE_REF, IDENTIFIER_NODE)
and those that process expression nodes (VAR_DECL, FUNCTION_DECL,
OVERLOAD).
There is more that can be done in this direction, but this is a good
first step.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-07-31 Mark Mitchell <mark@codesourcery.com>
* 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-31 Mark Mitchell <mark@codesourcery.com>
* 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.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.323
diff -c -p -r1.323 call.c
*** cp/call.c 26 Jul 2002 20:10:40 -0000 1.323
--- cp/call.c 1 Aug 2002 04:43:45 -0000
*************** Boston, MA 02111-1307, USA. */
*** 38,46 ****
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 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));
--- 38,44 ----
extern int inhibit_warnings;
! 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));
*************** static struct z_candidate * splice_viabl
*** 64,76 ****
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));
static struct z_candidate * add_template_candidate_real
! PARAMS ((struct z_candidate *, 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));
static struct z_candidate * add_builtin_candidates
PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
--- 62,74 ----
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,
! tree, tree, int, unification_kind_t));
static struct z_candidate * add_template_candidate_real
! 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, tree, tree));
static struct z_candidate * add_builtin_candidates
PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
*************** static struct z_candidate * build_builti
*** 82,90 ****
PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
int));
static struct z_candidate * add_conv_candidate
! PARAMS ((struct z_candidate *, tree, tree, tree));
static struct z_candidate * add_function_candidate
! PARAMS ((struct z_candidate *, 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));
--- 80,88 ----
PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
int));
static struct z_candidate * add_conv_candidate
! PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree));
static struct z_candidate * add_function_candidate
! (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));
*************** static tree build_conv PARAMS ((enum tre
*** 93,100 ****
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 tree source_type PARAMS ((tree));
static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
static int reference_related_p PARAMS ((tree, tree));
--- 91,98 ----
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
! (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));
*************** build_vfield_ref (datum, type)
*** 129,158 ****
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;
{
! tree field, instance;
!
! if (IDENTIFIER_CTOR_OR_DTOR_P (name))
! return NULL_TREE;
! /* 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 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);
if (instance == error_mark_node)
return error_mark_node;
--- 127,145 ----
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_component_ref_1 (instance, decl, 0);
if (instance == error_mark_node)
return error_mark_node;
*************** build_method_call (instance, name, parms
*** 476,482 ****
tree instance, name, parms, basetype_path;
int flags;
{
! tree basetype, instance_ptr;
#ifdef GATHER_STATISTICS
n_build_method_call++;
--- 463,472 ----
tree instance, name, parms, 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++;
*************** build_method_call (instance, name, parms
*** 485,491 ****
if (instance == error_mark_node
|| name == error_mark_node
|| parms == error_mark_node
! || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
if (processing_template_decl)
--- 475,481 ----
if (instance == error_mark_node
|| name == error_mark_node
|| parms == error_mark_node
! || (instance && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
if (processing_template_decl)
*************** build_method_call (instance, name, parms
*** 508,546 ****
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
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))
error
("destructor name `~%T' does not match type `%T' of expression",
! TREE_OPERAND (name, 0), basetype);
! if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
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),
instance_ptr, sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
! return build_new_method_call (instance, name, parms, basetype_path, flags);
}
/* New overloading code. */
struct z_candidate GTY(()) {
tree fn;
tree convs;
tree second_conv;
int viable;
! tree basetype_path;
tree template;
tree warnings;
struct z_candidate *next;
--- 498,595 ----
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");
! 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 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 (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=*/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;
! /* 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;
*************** convert_class_to_reference (t, s, expr)
*** 981,986 ****
--- 1030,1037 ----
NULL_TREE,
arglist,
build_reference_type (t),
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
LOOKUP_NORMAL,
DEDUCE_CONV);
*************** convert_class_to_reference (t, s, expr)
*** 1001,1010 ****
&& reference_compatible_p (t, TREE_TYPE (t2)))
candidates
= add_function_candidate (candidates, f, s, arglist,
LOOKUP_NORMAL);
-
- if (candidates != old_candidates)
- candidates->basetype_path = TYPE_BINFO (s);
}
}
--- 1052,1060 ----
&& reference_compatible_p (t, TREE_TYPE (t2)))
candidates
= add_function_candidate (candidates, f, s, arglist,
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
LOOKUP_NORMAL);
}
}
*************** implicit_conversion (to, from, expr, fla
*** 1282,1297 ****
functions. */
static struct z_candidate *
! add_candidate (candidates, fn, convs, viable)
! struct z_candidate *candidates;
! tree fn, convs;
! int viable;
{
struct z_candidate *cand
= (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
cand->fn = fn;
cand->convs = convs;
cand->viable = viable;
cand->next = candidates;
--- 1332,1348 ----
functions. */
static struct z_candidate *
! 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;
*************** add_candidate (candidates, fn, convs, vi
*** 1306,1315 ****
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;
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
--- 1357,1366 ----
comes from for purposes of overload resolution. */
static struct z_candidate *
! 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;
*************** add_function_candidate (candidates, fn,
*** 1421,1427 ****
}
out:
! return add_candidate (candidates, fn, convs, viable);
}
/* Create an overload candidate for the conversion function FN which will
--- 1472,1479 ----
}
out:
! return add_candidate (candidates, fn, convs, access_path,
! conversion_path, viable);
}
/* Create an overload candidate for the conversion function FN which will
*************** add_function_candidate (candidates, fn,
*** 1436,1444 ****
instead of the function. */
static struct z_candidate *
! add_conv_candidate (candidates, fn, obj, arglist)
struct z_candidate *candidates;
tree fn, obj, arglist;
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
--- 1488,1499 ----
instead of the function. */
static struct z_candidate *
! 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;
*************** add_conv_candidate (candidates, fn, obj,
*** 1498,1504 ****
if (!sufficient_parms_p (parmnode))
viable = 0;
! return add_candidate (candidates, totype, convs, viable);
}
static struct z_candidate *
--- 1553,1560 ----
if (!sufficient_parms_p (parmnode))
viable = 0;
! return add_candidate (candidates, totype, convs, access_path,
! conversion_path, viable);
}
static struct z_candidate *
*************** build_builtin_candidate (candidates, fnn
*** 1547,1553 ****
viable = 0;
}
! return add_candidate (candidates, fnname, convs, viable);
}
static int
--- 1603,1612 ----
viable = 0;
}
! return add_candidate (candidates, fnname, convs,
! /*access_path=*/NULL_TREE,
! /*conversion_path=*/NULL_TREE,
! viable);
}
static int
*************** add_builtin_candidates (candidates, code
*** 2185,2194 ****
static struct z_candidate*
add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
! arglist, return_type, flags,
! obj, strict)
struct z_candidate *candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
int flags;
tree obj;
unification_kind_t strict;
--- 2244,2255 ----
static struct z_candidate*
add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
! 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;
*************** add_template_candidate_real (candidates,
*** 2253,2262 ****
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
! cand = add_conv_candidate (candidates, fn, obj, arglist);
else
cand = add_function_candidate (candidates, fn, ctype,
! arglist, 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
--- 2314,2325 ----
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
! cand = add_conv_candidate (candidates, fn, obj, access_path,
! conversion_path, arglist);
else
cand = add_function_candidate (candidates, fn, ctype,
! 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
*************** add_template_candidate_real (candidates,
*** 2285,2311 ****
static struct z_candidate *
add_template_candidate (candidates, tmpl, ctype, explicit_targs,
! arglist, return_type, flags, strict)
struct z_candidate *candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
int flags;
unification_kind_t strict;
{
return
add_template_candidate_real (candidates, tmpl, ctype,
! explicit_targs, arglist, return_type, flags,
! NULL_TREE, strict);
}
static struct z_candidate *
! add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
struct z_candidate *candidates;
tree tmpl, obj, arglist, return_type;
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
! arglist, return_type, 0, obj, DEDUCE_CONV);
}
--- 2348,2382 ----
static struct z_candidate *
add_template_candidate (candidates, tmpl, ctype, explicit_targs,
! 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,
! access_path, conversion_path,
! flags, NULL_TREE, strict);
}
static struct z_candidate *
! 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, access_path,
! conversion_path, 0, obj, DEDUCE_CONV);
}
*************** build_user_type_conversion_1 (totype, ex
*** 2446,2463 ****
templates = tree_cons (NULL_TREE, ctor, templates);
candidates =
add_template_candidate (candidates, ctor, totype,
! NULL_TREE, args, NULL_TREE, flags,
DEDUCE_CALL);
! }
else
candidates = add_function_candidate (candidates, ctor, totype,
! args, flags);
if (candidates)
! {
! candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
! candidates->basetype_path = TYPE_BINFO (totype);
! }
}
if (convs)
--- 2517,2536 ----
templates = tree_cons (NULL_TREE, ctor, templates);
candidates =
add_template_candidate (candidates, ctor, totype,
! NULL_TREE, args, NULL_TREE,
! TYPE_BINFO (totype),
! TYPE_BINFO (totype),
! flags,
DEDUCE_CALL);
! }
else
candidates = add_function_candidate (candidates, ctor, totype,
! args, TYPE_BINFO (totype),
! TYPE_BINFO (totype),
! flags);
if (candidates)
! candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
}
if (convs)
*************** build_user_type_conversion_1 (totype, ex
*** 2465,2471 ****
for (; convs; convs = TREE_CHAIN (convs))
{
! tree fns = TREE_VALUE (convs);
int convflags = LOOKUP_NO_CONVERSION;
/* If we are called to convert to a reference type, we are trying to
--- 2538,2545 ----
for (; convs; convs = TREE_CHAIN (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
*************** build_user_type_conversion_1 (totype, ex
*** 2475,2481 ****
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
! for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
struct z_candidate *old_candidates = candidates;
--- 2549,2555 ----
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
! for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
struct z_candidate *old_candidates = candidates;
*************** build_user_type_conversion_1 (totype, ex
*** 2492,2503 ****
templates = tree_cons (NULL_TREE, fn, templates);
candidates =
add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! args, totype, flags,
DEDUCE_CONV);
}
else
candidates = add_function_candidate (candidates, fn, fromtype,
! args, flags);
if (candidates != old_candidates)
{
--- 2566,2582 ----
templates = tree_cons (NULL_TREE, fn, templates);
candidates =
add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! args, totype, TYPE_BINFO (fromtype),
! conversion_path,
! flags,
DEDUCE_CONV);
}
else
candidates = add_function_candidate (candidates, fn, fromtype,
! args,
! TYPE_BINFO (fromtype),
! conversion_path,
! flags);
if (candidates != old_candidates)
{
*************** build_user_type_conversion_1 (totype, ex
*** 2506,2512 ****
0, convflags);
candidates->second_conv = ics;
- candidates->basetype_path = TYPE_BINFO (fromtype);
if (ics == NULL_TREE)
candidates->viable = 0;
--- 2585,2590 ----
*************** build_user_type_conversion_1 (totype, ex
*** 2517,2535 ****
}
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;
! }
candidates = splice_viable (candidates);
cand = tourney (candidates);
--- 2595,2601 ----
}
if (! any_viable (candidates))
! return 0;
candidates = splice_viable (candidates);
cand = tourney (candidates);
*************** resolve_args (args)
*** 2609,2614 ****
--- 2675,2683 ----
}
return args;
}
+
+ /* Return an expression for a call to FN (a namespace-scope function)
+ with the ARGS. */
tree
build_new_function_call (fn, args)
*************** build_new_function_call (fn, args)
*** 2618,2623 ****
--- 2687,2701 ----
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);
*************** build_new_function_call (fn, args)
*** 2625,2631 ****
template_only = 1;
}
! if (really_overloaded_fn (fn))
{
tree t1;
tree templates = NULL_TREE;
--- 2703,2710 ----
template_only = 1;
}
! if (really_overloaded_fn (fn)
! || TREE_CODE (fn) == TEMPLATE_DECL)
{
tree t1;
tree templates = NULL_TREE;
*************** build_new_function_call (fn, args)
*** 2635,2654 ****
if (args == error_mark_node)
return error_mark_node;
! for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
! tree t = OVL_FUNCTION (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,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else if (! template_only)
candidates = add_function_candidate
! (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
--- 2714,2736 ----
if (args == error_mark_node)
return error_mark_node;
! for (t1 = fn; t1; t1 = OVL_NEXT (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,
! /*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, /*access_path=*/NULL_TREE,
! /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
*************** build_new_function_call (fn, args)
*** 2656,2662 ****
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);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
--- 2738,2744 ----
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
error ("no matching function for call to `%D(%A)'",
! DECL_NAME (OVL_CURRENT (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
*************** build_object_call (obj, args)
*** 2719,2732 ****
candidates
= add_template_candidate (candidates, fn, base, NULL_TREE,
mem_args, NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else
candidates = add_function_candidate
! (candidates, fn, base, mem_args, LOOKUP_NORMAL);
!
! if (candidates)
! candidates->basetype_path = TYPE_BINFO (type);
}
}
--- 2801,2814 ----
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, TYPE_BINFO (type),
! TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
*************** build_object_call (obj, args)
*** 2749,2762 ****
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
! candidates = add_template_conv_candidate (candidates,
! fn,
! obj,
! args,
! totype);
}
else
! candidates = add_conv_candidate (candidates, fn, obj, args);
}
}
--- 2831,2845 ----
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
! 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,
! /*conversion_path=*/NULL_TREE,
! /*access_path=*/NULL_TREE);
}
}
*************** conditional_conversion (e1, e2)
*** 2890,2898 ****
}
/* 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. */
tree
build_conditional_expr (arg1, arg2, arg3)
--- 2973,2979 ----
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
! arguments to the conditional expression. */
tree
build_conditional_expr (arg1, arg2, arg3)
*************** build_new_op (code, flags, arg1, arg2, a
*** 3331,3341 ****
candidates
= add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
candidates = add_function_candidate (candidates, fn, NULL_TREE,
! arglist, flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
--- 3412,3427 ----
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,
! /*access_path=*/NULL_TREE,
! /*conversion_path=*/NULL_TREE,
! flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
*************** build_new_op (code, flags, arg1, arg2, a
*** 3349,3360 ****
if (fns)
{
! tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
! for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree this_arglist;
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
this_arglist = mem_arglist;
--- 3435,3448 ----
if (fns)
{
! tree conversion_path = BASELINK_BINFO (fns);
!
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
! 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;
*************** build_new_op (code, flags, arg1, arg2, a
*** 3366,3381 ****
/* A member template. */
templates = tree_cons (NULL_TREE, fn, templates);
candidates
! = add_template_candidate (candidates, fn, basetype, NULL_TREE,
this_arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
candidates = add_function_candidate
! (candidates, fn, basetype, this_arglist, flags);
!
! if (candidates)
! candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
}
}
--- 3454,3470 ----
/* A member template. */
templates = tree_cons (NULL_TREE, fn, templates);
candidates
! = 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, BINFO_TYPE (conversion_path), this_arglist,
! access_path, conversion_path, flags);
}
}
*************** convert_like_real (convs, expr, fn, argn
*** 3863,3869 ****
&& (inner >= 0 || !lvalue_p (expr)))
{
savew = warningcount, savee = errorcount;
! expr = build_new_method_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
--- 3952,3958 ----
&& (inner >= 0 || !lvalue_p (expr)))
{
savew = warningcount, savee = errorcount;
! 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
*************** convert_like_real (convs, expr, fn, argn
*** 3945,3954 ****
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);
if (fn)
{
if (warningcount > savew)
--- 4034,4043 ----
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_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)
*************** build_over_call (cand, args, flags)
*** 4207,4213 ****
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
! enforce_access (cand->basetype_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
--- 4296,4302 ----
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
! enforce_access (cand->access_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
*************** build_over_call (cand, args, flags)
*** 4236,4242 ****
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
! tree t;
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
TREE_TYPE (argtype), fn);
--- 4325,4332 ----
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
! 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);
*************** build_over_call (cand, args, flags)
*** 4248,4257 ****
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);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
--- 4338,4350 ----
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
! /* 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;
*************** in_charge_arg_for_name (name)
*** 4534,4676 ****
return NULL_TREE;
}
! static tree
! build_new_method_call (instance, name, args, basetype_path, flags)
! tree instance, name, args, basetype_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 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));
! }
! template_only = 1;
! }
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));
!
! /* 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;
! }
}
! if (basetype_path == NULL_TREE)
! basetype_path = TYPE_BINFO (basetype);
! if (instance)
{
! 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);
}
! /* 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 (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);
! }
}
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);
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
! for (; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
tree this_arglist;
--- 4627,4817 ----
return NULL_TREE;
}
! /* 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 = 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;
! my_friendly_assert (instance != NULL_TREE, 20020729);
! 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 (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))
! {
! call = build_field_call (instance_ptr, fns, args);
! if (call)
! return call;
! error ("call to non-function `%D'", fns);
! return error_mark_node;
}
! if (!conversion_path)
! conversion_path = BASELINK_BINFO (fns);
! access_binfo = BASELINK_ACCESS_BINFO (fns);
! optype = BASELINK_OPTYPE (fns);
! fns = BASELINK_FUNCTIONS (fns);
! if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
! explicit_targs = TREE_OPERAND (fns, 1);
! fns = TREE_OPERAND (fns, 0);
! template_only = 1;
}
!
! 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))
{
! /* 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;
if (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 = fns; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
tree this_arglist;
*************** build_new_method_call (instance, name, a
*** 4690,4705 ****
/* 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);
}
else if (! template_only)
! candidates = add_function_candidate (candidates, t, base,
! this_arglist, flags);
!
! if (candidates)
! candidates->basetype_path = basetype_path;
}
}
--- 4831,4852 ----
/* A member template. */
templates = tree_cons (NULL_TREE, t, templates);
candidates =
! 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,
! class_type,
! this_arglist,
! access_binfo,
! conversion_path,
! flags);
}
}
*************** build_new_method_call (instance, name, a
*** 4754,4762 ****
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))
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
}
--- 4901,4909 ----
else
{
call = build_over_call (cand, args, flags);
! /* 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);
}
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.63
diff -c -p -r1.63 cp-tree.def
*** cp/cp-tree.def 4 Apr 2002 00:10:55 -0000 1.63
--- cp/cp-tree.def 1 Aug 2002 04:43:45 -0000
*************** the Free Software Foundation, 59 Temple
*** 23,33 ****
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. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
/* A pointer-to-member constant. For a pointer-to-member constant
--- 23,47 ----
Boston, MA 02111-1307, USA. */
! /* 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
*************** DEFTREECODE (DEFAULT_ARG, "default_arg",
*** 186,192 ****
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. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
/* An association between name and entity. Parameters are the scope
--- 200,207 ----
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. 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
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.738
diff -c -p -r1.738 cp-tree.h
*** cp/cp-tree.h 30 Jul 2002 07:49:40 -0000 1.738
--- cp/cp-tree.h 1 Aug 2002 04:43:46 -0000
*************** struct tree_overload GTY(())
*** 385,394 ****
--- 385,409 ----
(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)
*************** extern int sufficient_parms_p
*** 3676,3681 ****
--- 3691,3698 ----
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));
*************** extern void finish_file PARAMS ((void
*** 3950,3955 ****
--- 3967,3974 ----
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));
*************** extern tree unmarked_vtable_pathp
*** 4229,4234 ****
--- 4248,4254 ----
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));
*************** extern void finish_subobject
*** 4281,4293 ****
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_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);
--- 4301,4312 ----
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 (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_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((tree));
extern tree finish_fname (tree);
*************** extern tree build_x_component_ref PARAM
*** 4454,4460 ****
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));
--- 4473,4478 ----
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.119
diff -c -p -r1.119 cvt.c
*** cp/cvt.c 5 Jul 2002 22:10:07 -0000 1.119
--- cp/cvt.c 1 Aug 2002 04:43:46 -0000
*************** ocp_convert (type, expr, convtype, flags
*** 771,780 ****
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);
if (ctor)
return build_cplus_new (type, ctor);
}
--- 771,780 ----
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
else
! 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);
}
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.552
diff -c -p -r1.552 decl2.c
*** cp/decl2.c 27 Jul 2002 21:15:39 -0000 1.552
--- cp/decl2.c 1 Aug 2002 04:43:47 -0000
*************** reparse_absdcl_as_expr (type, decl)
*** 3587,3600 ****
/* 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;
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
--- 3587,3593 ----
/* recurse */
decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
! return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
*************** reparse_absdcl_as_casts (decl, expr)
*** 3647,3653 ****
return expr;
}
! /* Given plain tree nodes for an expression, build up the full semantics. */
tree
build_expr_from_tree (t)
--- 3640,3647 ----
return expr;
}
! /* T is the parse tree for an expression. Return the expression after
! performing semantic analysis. */
tree
build_expr_from_tree (t)
*************** build_expr_from_tree (t)
*** 3671,3679 ****
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))));
case INDIRECT_REF:
return build_x_indirect_ref
--- 3665,3693 ----
return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
! {
! 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
*************** build_expr_from_tree (t)
*** 3881,3889 ****
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
! || ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
! return build_x_function_call (name, args, current_class_ref);
}
case COND_EXPR:
--- 3895,3912 ----
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
! || ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
!
! 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:
*************** build_expr_from_tree (t)
*** 3986,3991 ****
--- 4009,4113 ----
default:
return 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
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.286
diff -c -p -r1.286 init.c
*** cp/init.c 26 Jul 2002 20:10:42 -0000 1.286
--- cp/init.c 1 Aug 2002 04:43:48 -0000
*************** expand_cleanup_for_base (binfo, flag)
*** 852,859 ****
return;
/* Call the destructor. */
! expr = (build_scoped_method_call
! (current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
if (flag)
expr = fold (build (COND_EXPR, void_type_node,
c_common_truthvalue_conversion (flag),
--- 852,862 ----
return;
/* Call the destructor. */
! 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),
*************** expand_default_init (binfo, true_exp, ex
*** 1282,1288 ****
else
ctor_name = base_ctor_identifier;
! rval = build_method_call (exp, ctor_name, parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval))
{
if (building_stmt_tree ())
--- 1285,1291 ----
else
ctor_name = base_ctor_identifier;
! rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval))
{
if (building_stmt_tree ())
*************** build_member_call (type, name, parmlist)
*** 1451,1465 ****
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);
}
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);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
--- 1454,1469 ----
TREE_OPERAND (name, 0) = method_name;
}
my_friendly_assert (is_overloaded_fn (method_name), 980519);
! return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
}
if (DECL_P (name))
name = DECL_NAME (name);
if (TREE_CODE (type) == NAMESPACE_DECL)
! return finish_call_expr (lookup_namespace_name (type, name),
! parmlist,
! /*disallow_virtual=*/true);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
*************** build_member_call (type, name, parmlist)
*** 1486,1495 ****
{
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);
! }
}
if (type == NULL_TREE || ! is_aggr_type (type, 1))
--- 1490,1498 ----
{
tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
! return finish_call_expr (lookup_namespace_name (ns, name),
! parmlist,
! /*disallow_virtual=*/true);
}
if (type == NULL_TREE || ! is_aggr_type (type, 1))
*************** build_new_1 (exp)
*** 2326,2332 ****
args));
else
alloc_call = build_method_call (build_dummy_object (true_type),
! fnname, args, NULL_TREE,
LOOKUP_NORMAL);
}
--- 2329,2336 ----
args));
else
alloc_call = build_method_call (build_dummy_object (true_type),
! fnname, args,
! TYPE_BINFO (true_type),
LOOKUP_NORMAL);
}
*************** build_new_1 (exp)
*** 2415,2424 ****
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);
else
{
/* We are processing something like `new int (10)', which
--- 2419,2428 ----
if (has_array)
init_expr = build_vec_init (init_expr, init, 0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
! 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
*************** build_dtor_call (exp, dtor_kind, flags)
*** 3090,3096 ****
default:
abort ();
}
! return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
--- 3094,3101 ----
default:
abort ();
}
! 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.
*************** push_base_cleanups ()
*** 3282,3290 ****
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
! expr = build_scoped_method_call (current_class_ref, vbase,
! base_dtor_identifier,
! NULL_TREE);
expr = build (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
finish_decl_cleanup (NULL_TREE, expr);
--- 3287,3298 ----
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
! 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);
*************** push_base_cleanups ()
*** 3303,3312 ****
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
! expr = build_scoped_method_call (current_class_ref, base_binfo,
! base_dtor_identifier,
! NULL_TREE);
!
finish_decl_cleanup (NULL_TREE, expr);
}
--- 3311,3320 ----
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
! 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);
}
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.225
diff -c -p -r1.225 method.c
*** cp/method.c 23 Jul 2002 06:22:03 -0000 1.225
--- cp/method.c 1 Aug 2002 04:43:48 -0000
*************** do_build_assign_ref (fndecl)
*** 623,650 ****
}
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);
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
! for (i = 0; i < n_bases; ++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 expr = build_method_call (dst,
! ansi_assopname (NOP_EXPR),
! build_tree_list (NULL_TREE, src),
! binfo,
! LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
! finish_expr_stmt (expr);
}
! for (; fields; fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
--- 623,656 ----
}
else
{
! tree fields;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
! /* Assign to each of thedirect base classes. */
! for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
{
! tree binfo;
! tree converted_parm;
! 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));
}
!
! /* 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;
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.272
diff -c -p -r1.272 parse.y
*** cp/parse.y 22 Jul 2002 14:23:35 -0000 1.272
--- cp/parse.y 1 Aug 2002 04:43:48 -0000
*************** static tree parse_xref_tag (tree, tree,
*** 131,136 ****
--- 131,137 ----
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
*************** do_id:
*** 1534,1542 ****
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
! { $$ = lookup_template_function ($3, $4); }
| operator_name '<' do_id template_arg_list_opt template_close_bracket
! { $$ = lookup_template_function ($3, $4); }
;
object_template_id:
--- 1535,1553 ----
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
! {
! 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
! {
! 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:
*************** primary:
*** 1637,1649 ****
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); }
| notype_unqualified_id LEFT_RIGHT
! { $$ = finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
! { $$ = finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
! { $$ = 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); }
--- 1648,1660 ----
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 ')'
! { $$ = parse_finish_call_expr ($1, $3, 1); }
| notype_unqualified_id LEFT_RIGHT
! { $$ = parse_finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
! { $$ = parse_finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
! { $$ = 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); }
*************** primary:
*** 1705,1713 ****
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
! { $$ = finish_qualified_call_expr ($1, $3); }
| overqualified_id LEFT_RIGHT
! { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE);
--- 1716,1724 ----
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
! { $$ = parse_finish_call_expr ($1, $3, 0); }
| overqualified_id LEFT_RIGHT
! { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE);
*************** parse_begin_function_definition (tree sp
*** 4097,4102 ****
--- 4108,4255 ----
split_specs_attrs (specs_attrs, &specs, &attrs);
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"
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.605
diff -c -p -r1.605 pt.c
*** cp/pt.c 26 Jul 2002 20:10:42 -0000 1.605
--- cp/pt.c 1 Aug 2002 04:43:50 -0000
*************** add_pending_template (d)
*** 3814,3822 ****
}
! /* 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. */
tree
lookup_template_function (fns, arglist)
--- 3814,3822 ----
}
! /* 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)
*************** lookup_template_function (fns, arglist)
*** 3824,3843 ****
{
tree type;
if (fns == NULL_TREE)
{
error ("non-template used as template");
return error_mark_node;
}
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);
}
/* Within the scope of a template class S<T>, the name S gets bound
--- 3824,3849 ----
{
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;
!
! return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
*************** type_unification_real (tparms, targs, xp
*** 8012,8019 ****
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). */
if (xargs)
my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
--- 8018,8024 ----
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. */
if (xargs)
my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.232
diff -c -p -r1.232 search.c
*** cp/search.c 23 Jul 2002 06:22:04 -0000 1.232
--- cp/search.c 1 Aug 2002 04:43:50 -0000
*************** lookup_base (t, base, access, kind_ptr)
*** 310,315 ****
--- 310,316 ----
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)
*************** lookup_base (t, base, access, kind_ptr)
*** 318,330 ****
*kind_ptr = bk_not_base;
return error_mark_node;
}
! my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127);
/* 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,
0, 0, 0, &binfo);
switch (bk)
--- 319,339 ----
*kind_ptr = bk_not_base;
return error_mark_node;
}
! 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 (t_binfo, base, access & ~ba_quiet,
0, 0, 0, &binfo);
switch (bk)
*************** lookup_field_r (binfo, data)
*** 1361,1366 ****
--- 1370,1401 ----
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
*************** lookup_member (xbasetype, name, protect,
*** 1470,1488 ****
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);
! }
!
return rval;
}
--- 1505,1513 ----
TREE_TYPE (rval)));
if (rval && is_overloaded_fn (rval))
! rval = build_baselink (rval_binfo, basetype_path, rval,
! (IDENTIFIER_TYPENAME_P (name)
! ? TREE_TYPE (name): NULL_TREE));
return rval;
}
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.269
diff -c -p -r1.269 semantics.c
*** cp/semantics.c 23 Jul 2002 13:54:05 -0000 1.269
--- cp/semantics.c 1 Aug 2002 04:43:51 -0000
*************** finish_stmt_expr (rtl_expr)
*** 1242,1273 ****
return result;
}
! /* Finish a call to FN with ARGS. Returns a representation of the
! call. */
tree
! finish_call_expr (fn, args, koenig)
! tree fn;
! tree args;
! int koenig;
{
! tree result;
! if (koenig)
{
! 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);
! }
! 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;
}
/* Finish a call to a postfix increment or decrement or EXPR. (Which
--- 1242,1327 ----
return result;
}
! /* 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 (tree fn, tree args, bool disallow_virtual)
{
! if (fn == error_mark_node || args == error_mark_node)
! return error_mark_node;
!
! 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))
{
! 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;
! }
!
! /* 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
*************** finish_object_call_expr (fn, object, arg
*** 1327,1340 ****
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)
--- 1381,1386 ----
*************** finish_object_call_expr (fn, object, arg
*** 1353,1361 ****
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
--- 1399,1406 ----
return error_mark_node;
}
}
!
return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
/* Finish a qualified member function call using OBJECT and ARGS as
*************** finish_pseudo_destructor_call_expr (obje
*** 1394,1415 ****
error ("`%E' is not of type `%T'", object, 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. */
--- 1439,1444 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.413
diff -c -p -r1.413 typeck.c
*** cp/typeck.c 26 Jul 2002 20:10:43 -0000 1.413
--- cp/typeck.c 1 Aug 2002 04:43:52 -0000
*************** build_array_ref (array, idx)
*** 2455,2763 ****
}
}
- /* 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.
--- 2455,2460 ----
*************** build_static_cast (type, expr)
*** 4928,4934 ****
LOOKUP_COMPLAIN, NULL_TREE)));
if (IS_AGGR_TYPE (type))
! return build_cplus_new (type, (build_method_call
(NULL_TREE, complete_ctor_identifier,
build_tree_list (NULL_TREE, expr),
TYPE_BINFO (type), LOOKUP_NORMAL)));
--- 4625,4631 ----
LOOKUP_COMPLAIN, NULL_TREE)));
if (IS_AGGR_TYPE (type))
! 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)));
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5431,5439 ****
/* Do the default thing */;
else
{
! result = build_method_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;
--- 5128,5137 ----
/* Do the default thing */;
else
{
! 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;
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.124
diff -c -p -r1.124 typeck2.c
*** cp/typeck2.c 2 Jul 2002 16:06:49 -0000 1.124
--- cp/typeck2.c 1 Aug 2002 04:43:52 -0000
*************** build_functional_cast (exp, parms)
*** 1309,1316 ****
return get_target_expr (exp);
}
! exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
! TYPE_BINFO (type), LOOKUP_NORMAL);
if (exp == error_mark_node)
return error_mark_node;
--- 1309,1316 ----
return get_target_expr (exp);
}
! 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;
Index: testsuite/g++.dg/inherit/operator1.C
===================================================================
RCS file: testsuite/g++.dg/inherit/operator1.C
diff -N testsuite/g++.dg/inherit/operator1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/operator1.C 1 Aug 2002 04:43:55 -0000
***************
*** 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;
+ }
+
Index: testsuite/g++.dg/lookup/disamb1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/lookup/disamb1.C,v
retrieving revision 1.1
diff -c -p -r1.1 disamb1.C
*** testsuite/g++.dg/lookup/disamb1.C 6 Apr 2002 16:15:19 -0000 1.1
--- testsuite/g++.dg/lookup/disamb1.C 1 Aug 2002 04:43:55 -0000
***************
*** 1,5 ****
// PR c++/525
! // Bug: With -pedantic, we weren't converting this to D1* for the call.
struct A
{
--- 1,5 ----
// PR c++/525
! // Bug: With -pedantic, we weren't converting this to B1* for the call.
struct A
{
Index: testsuite/g++.dg/other/error1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/other/error1.C,v
retrieving revision 1.1
diff -c -p -r1.1 error1.C
*** testsuite/g++.dg/other/error1.C 19 Dec 2001 11:52:59 -0000 1.1
--- testsuite/g++.dg/other/error1.C 1 Aug 2002 04:43:55 -0000
***************
*** 1,6 ****
// { dg-do compile }
! // Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Dec 2001 <nathan@nathan@codesourcery.com>
// PR 90, stupid error message `(this + 160)'
--- 1,6 ----
// { dg-do compile }
! // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Dec 2001 <nathan@nathan@codesourcery.com>
// PR 90, stupid error message `(this + 160)'
*************** class foo {
*** 10,15 ****
int fudge[40];
int bar [40];
inline int access(int i) {
! return bar(i); // { dg-error "`this->foo::bar' cannot" "" }
}
};
--- 10,15 ----
int fudge[40];
int bar [40];
inline int access(int i) {
! return bar(i); // { dg-error "call to non-function `foo::bar'" "" }
}
};
Index: testsuite/g++.dg/template/conv4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/conv4.C,v
retrieving revision 1.1
diff -c -p -r1.1 conv4.C
*** testsuite/g++.dg/template/conv4.C 16 Mar 2002 18:30:16 -0000 1.1
--- testsuite/g++.dg/template/conv4.C 1 Aug 2002 04:43:55 -0000
***************
*** 1,6 ****
// { dg-do compile }
! // Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
// PR 4361. Template conversion operators were not overloaded.
--- 1,6 ----
// { dg-do compile }
! // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
// PR 4361. Template conversion operators were not overloaded.
*************** struct D
*** 21,27 ****
{
int Foo ()
{
! return operator int (); // { dg-error "no matching function" "" }
}
};
--- 21,27 ----
{
int Foo ()
{
! return operator int (); // { dg-error "not defined" "" }
}
};