call.c (build_field_call): Do not look up the field by name.

* 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.

	* 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.

From-SVN: r55920
This commit is contained in:
Mark Mitchell 2002-08-01 04:46:23 +00:00
parent 692f56114c
commit 4ba126e468
20 changed files with 1034 additions and 704 deletions

View File

@ -1,3 +1,65 @@
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-30 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* lang-specs.h: Remove __GXX_ABI_VERSION, moved to gcc.c.

File diff suppressed because it is too large Load Diff

View File

@ -23,11 +23,25 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
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. */
/* 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
@ -186,7 +200,8 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 2)
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. */
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

View File

@ -385,10 +385,25 @@ struct tree_overload GTY(())
(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)
@ -3676,6 +3691,8 @@ extern int sufficient_parms_p PARAMS ((tree));
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));
@ -3950,6 +3967,8 @@ extern void finish_file PARAMS ((void));
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));
@ -4229,6 +4248,7 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
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));
@ -4281,13 +4301,12 @@ extern void finish_subobject PARAMS ((tree));
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_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_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);
@ -4454,7 +4473,6 @@ extern tree build_x_component_ref PARAMS ((tree, tree, tree));
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));

View File

@ -771,10 +771,10 @@ ocp_convert (type, expr, convtype, flags)
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);
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);
}

View File

@ -3587,14 +3587,7 @@ reparse_absdcl_as_expr (type, decl)
/* 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;
return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
@ -3647,7 +3640,8 @@ reparse_absdcl_as_casts (decl, expr)
return expr;
}
/* Given plain tree nodes for an expression, build up the full semantics. */
/* T is the parse tree for an expression. Return the expression after
performing semantic analysis. */
tree
build_expr_from_tree (t)
@ -3671,9 +3665,29 @@ build_expr_from_tree (t)
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))));
{
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
@ -3881,9 +3895,18 @@ build_expr_from_tree (t)
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
return build_x_function_call (name, args, current_class_ref);
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:
@ -3988,6 +4011,105 @@ build_expr_from_tree (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
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by

View File

@ -852,8 +852,11 @@ expand_cleanup_for_base (binfo, flag)
return;
/* Call the destructor. */
expr = (build_scoped_method_call
(current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
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),
@ -1282,7 +1285,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
else
ctor_name = base_ctor_identifier;
rval = build_method_call (exp, ctor_name, parms, binfo, flags);
rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval))
{
if (building_stmt_tree ())
@ -1451,15 +1454,16 @@ build_member_call (type, name, parmlist)
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);
return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
}
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);
return finish_call_expr (lookup_namespace_name (type, name),
parmlist,
/*disallow_virtual=*/true);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
@ -1486,10 +1490,9 @@ build_member_call (type, name, parmlist)
{
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);
}
return finish_call_expr (lookup_namespace_name (ns, name),
parmlist,
/*disallow_virtual=*/true);
}
if (type == NULL_TREE || ! is_aggr_type (type, 1))
@ -2326,7 +2329,8 @@ build_new_1 (exp)
args));
else
alloc_call = build_method_call (build_dummy_object (true_type),
fnname, args, NULL_TREE,
fnname, args,
TYPE_BINFO (true_type),
LOOKUP_NORMAL);
}
@ -2415,10 +2419,10 @@ build_new_1 (exp)
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);
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
@ -3090,7 +3094,8 @@ build_dtor_call (exp, dtor_kind, flags)
default:
abort ();
}
return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
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.
@ -3282,9 +3287,12 @@ push_base_cleanups ()
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
expr = build_scoped_method_call (current_class_ref, vbase,
base_dtor_identifier,
NULL_TREE);
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);
@ -3303,10 +3311,10 @@ push_base_cleanups ()
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
expr = build_scoped_method_call (current_class_ref, base_binfo,
base_dtor_identifier,
NULL_TREE);
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);
}

View File

@ -623,28 +623,34 @@ do_build_assign_ref (fndecl)
}
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);
tree fields;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
for (i = 0; i < n_bases; ++i)
/* Assign to each of thedirect base classes. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++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 binfo;
tree converted_parm;
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);
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));
}
for (; fields; fields = TREE_CHAIN (fields))
/* 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;

View File

@ -131,6 +131,7 @@ static tree parse_xref_tag (tree, tree, int);
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
@ -1534,9 +1535,19 @@ do_id:
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($3, $4); }
{
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
{ $$ = lookup_template_function ($3, $4); }
{
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:
@ -1637,13 +1648,13 @@ primary:
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); }
{ $$ = parse_finish_call_expr ($1, $3, 1); }
| notype_unqualified_id LEFT_RIGHT
{ $$ = finish_call_expr ($1, NULL_TREE, 1); }
{ $$ = parse_finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
{ $$ = finish_call_expr ($1, $3, 0); }
{ $$ = parse_finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
{ $$ = finish_call_expr ($1, NULL_TREE, 0); }
{ $$ = 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); }
@ -1705,9 +1716,9 @@ primary:
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
{ $$ = finish_qualified_call_expr ($1, $3); }
{ $$ = parse_finish_call_expr ($1, $3, 0); }
| overqualified_id LEFT_RIGHT
{ $$ = finish_qualified_call_expr ($1, NULL_TREE); }
{ $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE);
@ -4099,4 +4110,146 @@ parse_begin_function_definition (tree specs_attrs, tree declarator)
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"

View File

@ -3814,9 +3814,9 @@ add_pending_template (d)
}
/* 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. */
/* 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)
@ -3824,20 +3824,26 @@ lookup_template_function (fns, arglist)
{
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;
if (processing_template_decl)
return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
else
return build (TEMPLATE_ID_EXPR, type, fns, arglist);
return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
@ -8012,8 +8018,7 @@ type_unification_real (tparms, targs, xparms, xargs, subr,
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). */
/* ARGS could be NULL. */
if (xargs)
my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);

View File

@ -310,6 +310,7 @@ lookup_base (t, base, access, kind_ptr)
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)
@ -318,13 +319,21 @@ lookup_base (t, base, access, kind_ptr)
*kind_ptr = bk_not_base;
return error_mark_node;
}
my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127);
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 (TYPE_BINFO (t), base, access & ~ba_quiet,
bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
0, 0, 0, &binfo);
switch (bk)
@ -1361,6 +1370,32 @@ lookup_field_r (binfo, data)
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
@ -1470,19 +1505,9 @@ lookup_member (xbasetype, name, protect, want_type)
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);
}
rval = build_baselink (rval_binfo, basetype_path, rval,
(IDENTIFIER_TYPENAME_P (name)
? TREE_TYPE (name): NULL_TREE));
return rval;
}

View File

@ -1242,32 +1242,86 @@ finish_stmt_expr (rtl_expr)
return result;
}
/* Finish a call to FN with ARGS. Returns a representation of the
call. */
/* 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 (fn, args, koenig)
tree fn;
tree args;
int koenig;
finish_call_expr (tree fn, tree args, bool disallow_virtual)
{
tree result;
if (fn == error_mark_node || args == error_mark_node)
return error_mark_node;
if (koenig)
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))
{
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);
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;
}
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;
/* 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
@ -1327,14 +1381,6 @@ finish_object_call_expr (fn, object, args)
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)
@ -1353,9 +1399,8 @@ finish_object_call_expr (fn, object, args)
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
@ -1396,22 +1441,6 @@ finish_pseudo_destructor_call_expr (object, scope, 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. */
tree

View File

@ -2455,309 +2455,6 @@ build_array_ref (array, idx)
}
}
/* 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.
@ -4928,7 +4625,7 @@ build_static_cast (type, expr)
LOOKUP_COMPLAIN, NULL_TREE)));
if (IS_AGGR_TYPE (type))
return build_cplus_new (type, (build_method_call
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)));
@ -5431,9 +5128,10 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else
{
result = build_method_call (lhs, complete_ctor_identifier,
build_tree_list (NULL_TREE, rhs),
TYPE_BINFO (lhstype), LOOKUP_NORMAL);
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;

View File

@ -1309,8 +1309,8 @@ build_functional_cast (exp, parms)
return get_target_expr (exp);
}
exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
TYPE_BINFO (type), LOOKUP_NORMAL);
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;

View File

@ -1,4 +1,11 @@
2002-07-26 Neil Booth <neil@daikokuya.co.uk>
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.
2002-07-26 Neil Booth <neil@daikokuya.cop.uk>
* gcc.dg/cpp/trad/Wunused.c, gcc.dg/cpp/Wunused.c: Add test
for documented behaviour.

View File

@ -113,11 +113,12 @@ Here are some more advanced usage instructions:
1. To run a particular set of tests (rather than all of the tests),
use the make variable "QMTEST_GPP_TESTS". For example,
make QMTEST_GPP_TESTS="gpp.dg" qmtest-g++
make QMTEST_GPP_TESTS="g++.dg" qmtest-g++
will run only the tests in the g++.dg subdirectory, and:
make QMTEST_GPP_TESTS="gpp.dg.special.conpr1 gpp.old-deja.other.access2"
make QMTEST_GPP_TESTS="g++.dg/special/conpr1.C \
g++.old-deja/g++.other/access2.C"
qmtest-g++
will run only the two tests indicated.

View File

@ -0,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;
}

View File

@ -1,5 +1,5 @@
// PR c++/525
// Bug: With -pedantic, we weren't converting this to D1* for the call.
// Bug: With -pedantic, we weren't converting this to B1* for the call.
struct A
{

View File

@ -1,6 +1,6 @@
// { dg-do compile }
// Copyright (C) 2001 Free Software Foundation, Inc.
// 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)'
@ -10,6 +10,6 @@ class foo {
int fudge[40];
int bar [40];
inline int access(int i) {
return bar(i); // { dg-error "`this->foo::bar' cannot" "" }
return bar(i); // { dg-error "call to non-function `foo::bar'" "" }
}
};

View File

@ -1,6 +1,6 @@
// { dg-do compile }
// Copyright (C) 2001 Free Software Foundation, Inc.
// 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.
@ -21,7 +21,7 @@ struct D
{
int Foo ()
{
return operator int (); // { dg-error "no matching function" "" }
return operator int (); // { dg-error "not defined" "" }
}
};