Commit 51924768 by Jason Merrill Committed by Jason Merrill

Revamp references to member functions.

	* method.c (hack_identifier): Call build_component_ref for a
	reference to a member function.
	* typeck.c (build_component_ref): Only return a single function
	if it's static.  Otherwise, return a COMPONENT_REF.
	(build_x_function_call): Handle a COMPONENT_REF.
	(build_unary_op): Handle all unknown-type things.
	* decl2.c (arg_assoc): Handle COMPONENT_REF.
	* class.c (instantiate_type): Complain if the function we get is a
	nonstatic member function.  Remove code for finding "compatible"
	functions.
	* pt.c (tsubst_copy): Handle NOP_EXPR.
	* tree.c (build_dummy_object): New fn.
	(maybe_dummy_object): New fn.
	(is_dummy_object): New fn.
	* cp-tree.h: Declare them.
	* cvt.c (cp_convert_to_pointer): Use maybe_dummy_object.
	* error.c (dump_expr, case OFFSET_REF): Use is_dummy_object.
	* init.c (build_member_call): Use maybe_dummy_object and
	is_dummy_object.
	(build_offset_ref): Use maybe_dummy_object.
	(resolve_offset_ref): Use is_dummy_object.
	* typeck.c (build_x_function_call): Call build_dummy_object.
	(unary_complex_lvalue): Call is_dummy_object.
	* typeck.c (build_component_addr): Make sure field is a field.
	* call.c (build_new_op): Delete obsolete code.
	* pt.c (tsubst, TEMPLATE*PARM*): Abort if we don't have any args.

From-SVN: r23186
parent 4f2905fb
1998-10-19 Jason Merrill <jason@yorick.cygnus.com>
Revamp references to member functions.
* method.c (hack_identifier): Call build_component_ref for a
reference to a member function.
* typeck.c (build_component_ref): Only return a single function
if it's static. Otherwise, return a COMPONENT_REF.
(build_x_function_call): Handle a COMPONENT_REF.
(build_unary_op): Handle all unknown-type things.
* decl2.c (arg_assoc): Handle COMPONENT_REF.
* class.c (instantiate_type): Complain if the function we get is a
nonstatic member function. Remove code for finding "compatible"
functions.
* pt.c (tsubst_copy): Handle NOP_EXPR.
* tree.c (build_dummy_object): New fn.
(maybe_dummy_object): New fn.
(is_dummy_object): New fn.
* cp-tree.h: Declare them.
* cvt.c (cp_convert_to_pointer): Use maybe_dummy_object.
* error.c (dump_expr, case OFFSET_REF): Use is_dummy_object.
* init.c (build_member_call): Use maybe_dummy_object and
is_dummy_object.
(build_offset_ref): Use maybe_dummy_object.
(resolve_offset_ref): Use is_dummy_object.
* typeck.c (build_x_function_call): Call build_dummy_object.
(unary_complex_lvalue): Call is_dummy_object.
* typeck.c (build_component_addr): Make sure field is a field.
* call.c (build_new_op): Delete obsolete code.
* pt.c (tsubst, TEMPLATE*PARM*): Abort if we don't have any args.
1998-10-18 Martin von Lwis <loewis@informatik.hu-berlin.de> 1998-10-18 Martin von Lwis <loewis@informatik.hu-berlin.de>
* decl2.c (validate_nonmember_using_decl): Fix using-directives of * decl2.c (validate_nonmember_using_decl): Fix using-directives of
......
...@@ -2513,73 +2513,10 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -2513,73 +2513,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
{ {
case NEW_EXPR: case NEW_EXPR:
case VEC_NEW_EXPR: case VEC_NEW_EXPR:
{
tree rval;
arglist = scratch_tree_cons (NULL_TREE, arg2, arg3);
if (flags & LOOKUP_GLOBAL)
return build_new_function_call
(lookup_function_nonclass (fnname, arglist), arglist);
/* FIXME */
rval = build_method_call
(build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node),
"new"),
fnname, arglist, NULL_TREE, flags);
if (rval == error_mark_node)
/* User might declare fancy operator new, but invoke it
like standard one. */
return rval;
TREE_TYPE (rval) = arg1;
return rval;
}
case VEC_DELETE_EXPR: case VEC_DELETE_EXPR:
case DELETE_EXPR: case DELETE_EXPR:
{ /* Use build_op_new_call and build_op_delete_call instead. */
tree rval; my_friendly_abort (981018);
if (flags & LOOKUP_GLOBAL)
{
arglist = build_scratch_list (NULL_TREE, arg1);
return build_new_function_call
(lookup_function_nonclass (fnname, arglist), arglist);
}
arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
arg1 = TREE_TYPE (arg1);
/* This handles the case where we're trying to delete
X (*a)[10];
a=new X[5][10];
delete[] a; */
if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
{
/* Strip off the pointer and the array. */
arg1 = TREE_TYPE (TREE_TYPE (arg1));
while (TREE_CODE (arg1) == ARRAY_TYPE)
arg1 = (TREE_TYPE (arg1));
arg1 = build_pointer_type (arg1);
}
/* FIXME */
rval = build_method_call
(build_indirect_ref (build1 (NOP_EXPR, arg1,
error_mark_node),
NULL_PTR),
fnname, arglist, NULL_TREE, flags);
#if 0
/* This can happen when operator delete is protected. */
my_friendly_assert (rval != error_mark_node, 250);
TREE_TYPE (rval) = void_type_node;
#endif
return rval;
}
case CALL_EXPR: case CALL_EXPR:
return build_object_call (arg1, arg2); return build_object_call (arg1, arg2);
...@@ -2898,10 +2835,8 @@ build_op_new_call (code, type, args, flags) ...@@ -2898,10 +2835,8 @@ build_op_new_call (code, type, args, flags)
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL) if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR)))) && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{ {
tree dummy = build1 (NOP_EXPR, build_pointer_type (type), return build_method_call (build_dummy_object (type),
error_mark_node); fnname, args, NULL_TREE, flags);
dummy = build_indirect_ref (dummy, "new");
return build_method_call (dummy, fnname, args, NULL_TREE, flags);
} }
else else
return build_new_function_call return build_new_function_call
...@@ -3716,8 +3651,7 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -3716,8 +3651,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
&& value_member (cand->fn, get_abstract_virtuals (basetype))) && value_member (cand->fn, get_abstract_virtuals (basetype)))
cp_error ("abstract virtual `%#D' called from constructor", cand->fn); cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
&& TREE_CODE (instance_ptr) == NOP_EXPR && is_dummy_object (instance_ptr))
&& TREE_OPERAND (instance_ptr, 0) == error_mark_node)
cp_error ("cannot call member function `%D' without object", cand->fn); cp_error ("cannot call member function `%D' without object", cand->fn);
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
......
...@@ -5045,17 +5045,11 @@ instantiate_type (lhstype, rhs, complain) ...@@ -5045,17 +5045,11 @@ instantiate_type (lhstype, rhs, complain)
if (function == error_mark_node) if (function == error_mark_node)
return error_mark_node; return error_mark_node;
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185); my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
if (DECL_VINDEX (function))
{ if (! DECL_STATIC_FUNCTION_P (function))
tree base = TREE_OPERAND (rhs, 0); cp_error ("reference to `%D' can only be used in a call",
tree base_ptr = build_unary_op (ADDR_EXPR, base, 0); function);
if (base_ptr == error_mark_node)
return error_mark_node;
base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr);
if (base_ptr == error_mark_node)
return error_mark_node;
return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
}
mark_used (function); mark_used (function);
return function; return function;
} }
...@@ -5293,49 +5287,11 @@ instantiate_type (lhstype, rhs, complain) ...@@ -5293,49 +5287,11 @@ instantiate_type (lhstype, rhs, complain)
elem = OVL_NEXT (elem); elem = OVL_NEXT (elem);
} }
/* No exact match found, look for a compatible method. */ name = rhs;
for (baselink = rhs; baselink; while (TREE_CODE (name) == TREE_LIST)
baselink = next_baselink (baselink)) name = TREE_VALUE (name);
{ name = DECL_NAME (OVL_CURRENT (name));
elem = TREE_VALUE (baselink);
for (; elem; elem = OVL_NEXT (elem))
if (comp_target_types (lhstype,
TREE_TYPE (OVL_CURRENT (elem)), 1) > 0)
break;
if (elem)
{
tree save_elem = OVL_CURRENT (elem);
for (elem = OVL_NEXT (elem); elem; elem = OVL_NEXT (elem))
if (comp_target_types (lhstype,
TREE_TYPE (OVL_CURRENT (elem)), 0) > 0)
break;
if (elem)
{
if (complain)
error ("ambiguous overload for overloaded method requested");
return error_mark_node;
}
mark_used (save_elem);
return save_elem;
}
name = rhs;
while (TREE_CODE (name) == TREE_LIST)
name = TREE_VALUE (name);
name = DECL_NAME (OVL_CURRENT (name));
#if 0
if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
{
/* Try to instantiate from non-member functions. */
rhs = lookup_name_nonclass (name);
if (rhs && TREE_CODE (rhs) == TREE_LIST)
{
/* This code seems to be missing a `return'. */
my_friendly_abort (4);
instantiate_type (lhstype, rhs, complain);
}
}
#endif
}
if (complain) if (complain)
cp_error ("no compatible member functions named `%D'", name); cp_error ("no compatible member functions named `%D'", name);
return error_mark_node; return error_mark_node;
......
...@@ -3084,6 +3084,9 @@ extern tree mapcar PROTO((tree, tree (*) (tree))); ...@@ -3084,6 +3084,9 @@ extern tree mapcar PROTO((tree, tree (*) (tree)));
extern tree no_linkage_check PROTO((tree)); extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree)); extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void)); extern void push_expression_obstack PROTO((void));
extern tree build_dummy_object PROTO((tree));
extern tree maybe_dummy_object PROTO((tree, tree *));
extern int is_dummy_object PROTO((tree));
#define scratchalloc expralloc #define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons #define scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list #define build_scratch_list build_expr_list
......
...@@ -107,21 +107,8 @@ cp_convert_to_pointer (type, expr) ...@@ -107,21 +107,8 @@ cp_convert_to_pointer (type, expr)
functions. */ functions. */
if (TYPE_PTRMEMFUNC_P (intype)) if (TYPE_PTRMEMFUNC_P (intype))
{ {
tree decl, basebinfo;
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype)); tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
tree t = TYPE_METHOD_BASETYPE (fntype); tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
if (current_class_type == 0
|| get_base_distance (t, current_class_type, 0, &basebinfo)
== -1)
{
decl = build1 (NOP_EXPR, t, error_mark_node);
}
else if (current_class_ptr == 0)
decl = build1 (NOP_EXPR, t, error_mark_node);
else
decl = current_class_ref;
expr = build (OFFSET_REF, fntype, decl, expr); expr = build (OFFSET_REF, fntype, decl, expr);
} }
......
...@@ -4539,9 +4539,13 @@ arg_assoc (k, n) ...@@ -4539,9 +4539,13 @@ arg_assoc (k, n)
if (TREE_CODE (n) == ADDR_EXPR) if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0); n = TREE_OPERAND (n, 0);
if (TREE_CODE (n) == COMPONENT_REF)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST) while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n); n = TREE_VALUE (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == TEMPLATE_ID_EXPR) if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
{ {
/* [basic.lookup.koenig] /* [basic.lookup.koenig]
...@@ -4604,7 +4608,7 @@ arg_assoc (k, n) ...@@ -4604,7 +4608,7 @@ arg_assoc (k, n)
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715); my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n)) for (; n; n = OVL_CHAIN (n))
if (arg_assoc (k, OVL_FUNCTION (n))) if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
return 1; return 1;
} }
......
...@@ -1577,8 +1577,7 @@ dump_expr (t, nop) ...@@ -1577,8 +1577,7 @@ dump_expr (t, nop)
case OFFSET_REF: case OFFSET_REF:
{ {
tree ob = TREE_OPERAND (t, 0); tree ob = TREE_OPERAND (t, 0);
if (TREE_CODE (ob) == NOP_EXPR if (is_dummy_object (ob))
&& TREE_OPERAND (ob, 0) == error_mark_node)
{ {
if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL) if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */ /* A::f */
......
...@@ -1359,7 +1359,6 @@ build_member_call (type, name, parmlist) ...@@ -1359,7 +1359,6 @@ build_member_call (type, name, parmlist)
tree t; tree t;
tree method_name; tree method_name;
int dtor = 0; int dtor = 0;
int dont_use_this = 0;
tree basetype_path, decl; tree basetype_path, decl;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR if (TREE_CODE (name) == TEMPLATE_ID_EXPR
...@@ -1415,23 +1414,11 @@ build_member_call (type, name, parmlist) ...@@ -1415,23 +1414,11 @@ build_member_call (type, name, parmlist)
return error_mark_node; return error_mark_node;
} }
/* No object? Then just fake one up, and let build_method_call decl = maybe_dummy_object (type, &basetype_path);
figure out what to do. */
if (current_class_type == 0
|| get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
dont_use_this = 1;
if (dont_use_this) /* Convert 'this' to the specified type to disambiguate conversion
{ to the function's context. */
basetype_path = TYPE_BINFO (type); if (decl == current_class_ref)
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
}
else if (current_class_ptr == 0)
{
dont_use_this = 1;
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
}
else
{ {
tree olddecl = current_class_ptr; tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl)); tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
...@@ -1440,13 +1427,10 @@ build_member_call (type, name, parmlist) ...@@ -1440,13 +1427,10 @@ build_member_call (type, name, parmlist)
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype), tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype)); TYPE_VOLATILE (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0); decl = convert_force (build_pointer_type (newtype), olddecl, 0);
decl = build_indirect_ref (decl, NULL_PTR);
} }
else
decl = olddecl;
} }
decl = build_indirect_ref (decl, NULL_PTR);
if (method_name == constructor_name (type) if (method_name == constructor_name (type)
|| method_name == constructor_name_full (type)) || method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist); return build_functional_cast (type, parmlist);
...@@ -1463,7 +1447,7 @@ build_member_call (type, name, parmlist) ...@@ -1463,7 +1447,7 @@ build_member_call (type, name, parmlist)
return error_mark_node; return error_mark_node;
if (TREE_CODE (t) == FIELD_DECL) if (TREE_CODE (t) == FIELD_DECL)
{ {
if (dont_use_this) if (is_dummy_object (decl))
{ {
cp_error ("invalid use of non-static field `%D'", t); cp_error ("invalid use of non-static field `%D'", t);
return error_mark_node; return error_mark_node;
...@@ -1569,16 +1553,7 @@ build_offset_ref (type, name) ...@@ -1569,16 +1553,7 @@ build_offset_ref (type, name)
return error_mark_node; return error_mark_node;
} }
if (current_class_type == 0 decl = maybe_dummy_object (type, &basebinfo);
|| get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
{
basebinfo = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, type, error_mark_node);
}
else if (current_class_ptr == 0)
decl = build1 (NOP_EXPR, type, error_mark_node);
else
decl = current_class_ref;
fnfields = lookup_fnfields (basebinfo, name, 1); fnfields = lookup_fnfields (basebinfo, name, 1);
fields = lookup_field (basebinfo, name, 0, 0); fields = lookup_field (basebinfo, name, 0, 0);
...@@ -1771,9 +1746,7 @@ resolve_offset_ref (exp) ...@@ -1771,9 +1746,7 @@ resolve_offset_ref (exp)
/* The first case is really just a reference to a member of `this'. */ /* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL if (TREE_CODE (member) == FIELD_DECL
&& (base == current_class_ref && (base == current_class_ref || is_dummy_object (base)))
|| (TREE_CODE (base) == NOP_EXPR
&& TREE_OPERAND (base, 0) == error_mark_node)))
{ {
tree basetype_path; tree basetype_path;
tree access; tree access;
...@@ -1815,8 +1788,7 @@ resolve_offset_ref (exp) ...@@ -1815,8 +1788,7 @@ resolve_offset_ref (exp)
} }
/* Ensure that we have an object. */ /* Ensure that we have an object. */
if (TREE_CODE (base) == NOP_EXPR if (is_dummy_object (base))
&& TREE_OPERAND (base, 0) == error_mark_node)
addr = error_mark_node; addr = error_mark_node;
else else
/* If this is a reference to a member function, then return the /* If this is a reference to a member function, then return the
......
...@@ -1866,6 +1866,17 @@ hack_identifier (value, name) ...@@ -1866,6 +1866,17 @@ hack_identifier (value, name)
TREE_USED (value) = 1; TREE_USED (value) = 1;
value = build_component_ref (current_class_ref, name, NULL_TREE, 1); value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
} }
else if (TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
{
tree decl;
if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value)))
return value;
decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0);
value = build_component_ref (decl, name, NULL_TREE, 1);
}
else if (really_overloaded_fn (value)) else if (really_overloaded_fn (value))
{ {
#if 0 #if 0
......
...@@ -5596,6 +5596,8 @@ tsubst (t, args, in_decl) ...@@ -5596,6 +5596,8 @@ tsubst (t, args, in_decl)
return arg; return arg;
} }
} }
else
my_friendly_abort (981018);
if (level == 1) if (level == 1)
/* This can happen during the attempted tsubst'ing in /* This can happen during the attempted tsubst'ing in
...@@ -5990,6 +5992,7 @@ tsubst_copy (t, args, in_decl) ...@@ -5990,6 +5992,7 @@ tsubst_copy (t, args, in_decl)
case CONST_CAST_EXPR: case CONST_CAST_EXPR:
case STATIC_CAST_EXPR: case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR: case DYNAMIC_CAST_EXPR:
case NOP_EXPR:
return build1 return build1
(code, tsubst (TREE_TYPE (t), args, in_decl), (code, tsubst (TREE_TYPE (t), args, in_decl),
tsubst_copy (TREE_OPERAND (t, 0), args, in_decl)); tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
......
...@@ -2629,3 +2629,56 @@ member_p (decl) ...@@ -2629,3 +2629,56 @@ member_p (decl)
tree ctx = DECL_CONTEXT (decl); tree ctx = DECL_CONTEXT (decl);
return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't'); return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
} }
/* Create a placeholder for member access where we don't actually have an
object that the access is against. */
tree
build_dummy_object (type)
tree type;
{
tree decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
return build_indirect_ref (decl, NULL_PTR);
}
/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
or a dummy object otherwise. If BINFOP is non-0, it is filled with the
binfo path from current_class_type to TYPE, or 0. */
tree
maybe_dummy_object (type, binfop)
tree type;
tree *binfop;
{
tree decl, context;
if (current_class_type
&& get_base_distance (type, current_class_type, 0, binfop) != -1)
context = current_class_type;
else
{
/* Reference from a nested class member function. */
context = type;
if (binfop)
*binfop = TYPE_BINFO (type);
}
if (current_class_ref && context == current_class_type)
decl = current_class_ref;
else
decl = build_dummy_object (context);
return decl;
}
/* Returns 1 if OB is a placeholder object, or a pointer to one. */
int
is_dummy_object (ob)
tree ob;
{
if (TREE_CODE (ob) == INDIRECT_REF)
ob = TREE_OPERAND (ob, 0);
return (TREE_CODE (ob) == NOP_EXPR
&& TREE_OPERAND (ob, 0) == error_mark_node);
}
...@@ -2078,57 +2078,27 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -2078,57 +2078,27 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node; return error_mark_node;
if (fndecls) if (fndecls)
{ {
/* If the function is unique and static, we can resolve it
now. Otherwise, we have to wait and see what context it is
used in; a component_ref involving a non-static member
function can only be used in a call (expr.ref). */
if (TREE_CHAIN (fndecls) == NULL_TREE if (TREE_CHAIN (fndecls) == NULL_TREE
&& TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD) && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
{ {
tree access, fndecl; tree fndecl;
/* Unique, so use this one now. */
basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls)); basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
fndecl = TREE_VALUE (fndecls); fndecl = TREE_VALUE (fndecls);
access = compute_access (TREE_PURPOSE (fndecls), fndecl); enforce_access (TREE_PURPOSE (fndecls), fndecl);
if (access == access_public_node) mark_used (fndecl);
{ return fndecl;
if (DECL_VINDEX (fndecl)
&& ! resolves_to_fixed_type_p (datum, 0))
{
tree addr = build_unary_op (ADDR_EXPR, datum, 0);
tree fntype = TREE_TYPE (fndecl);
addr = convert_pointer_to (DECL_CONTEXT (fndecl),
addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 310);
fndecl = build_vfn_ref (&addr, datum,
DECL_VINDEX (fndecl));
/* The type of fndecl is a function type,
not a pointer-to-function type, since
build_vfn_ref returns not the correct
vtable slot, but the indirection of the
correct vtable slot. */
TREE_TYPE (fndecl) = fntype;
}
else
mark_used (fndecl);
return build (OFFSET_REF, TREE_TYPE (fndecl),
datum, fndecl);
}
if (access == access_protected_node)
cp_error ("member function `%D' is protected", fndecl);
else
cp_error ("member function `%D' is private", fndecl);
return error_mark_node;
} }
else else
{ {
/* Just act like build_offset_ref, since the object does ref = build (COMPONENT_REF, unknown_type_node,
not matter unless we're actually calling the function. */ datum, fndecls);
tree t; return ref;
t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype,
unknown_type_node);
return t;
} }
} }
...@@ -2622,9 +2592,7 @@ build_x_function_call (function, params, decl) ...@@ -2622,9 +2592,7 @@ build_x_function_call (function, params, decl)
return error_mark_node; return error_mark_node;
} }
/* Yow: call from a static member function. */ /* Yow: call from a static member function. */
decl = build1 (NOP_EXPR, build_pointer_type (current_class_type), decl = build_dummy_object (current_class_type);
error_mark_node);
decl = build_indirect_ref (decl, NULL_PTR);
} }
/* Put back explicit template arguments, if any. */ /* Put back explicit template arguments, if any. */
...@@ -2636,12 +2604,10 @@ build_x_function_call (function, params, decl) ...@@ -2636,12 +2604,10 @@ build_x_function_call (function, params, decl)
else if (TREE_CODE (function) == COMPONENT_REF else if (TREE_CODE (function) == COMPONENT_REF
&& type == unknown_type_node) && type == unknown_type_node)
{ {
/* Should we undo what was done in build_component_ref? */ /* Undo what we did in build_component_ref. */
if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC) decl = TREE_OPERAND (function, 0);
/* Get the name that build_component_ref hid. */ function = TREE_OPERAND (function, 1);
function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1))); function = DECL_NAME (OVL_CURRENT (TREE_VALUE (function)));
else
function = TREE_PURPOSE (TREE_OPERAND (function, 1));
return build_method_call (decl, function, params, return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL); NULL_TREE, LOOKUP_NORMAL);
} }
...@@ -4248,6 +4214,8 @@ build_component_addr (arg, argtype, msg) ...@@ -4248,6 +4214,8 @@ build_component_addr (arg, argtype, msg)
tree basetype = decl_type_context (field); tree basetype = decl_type_context (field);
tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0); tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
if (DECL_C_BIT_FIELD (field)) if (DECL_C_BIT_FIELD (field))
{ {
error (msg, IDENTIFIER_POINTER (DECL_NAME (field))); error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
...@@ -4665,24 +4633,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4665,24 +4633,7 @@ build_unary_op (code, xarg, noconvert)
return build1 (ADDR_EXPR, unknown_type_node, arg); return build1 (ADDR_EXPR, unknown_type_node, arg);
} }
if (TREE_CODE (arg) == OVERLOAD if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
|| (TREE_CODE (arg) == OFFSET_REF
&& TREE_CODE (TREE_OPERAND (arg, 1)) == TEMPLATE_ID_EXPR))
return build1 (ADDR_EXPR, unknown_type_node, arg);
else if (TREE_CODE (arg) == TREE_LIST)
{
if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL)
/* Unique overloaded non-member function. */
return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
if (TREE_CHAIN (arg) == NULL_TREE
&& TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
&& TREE_CODE (TREE_VALUE (TREE_VALUE (arg))) != OVERLOAD)
/* Unique overloaded member function. */
return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
0);
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{ {
tree targs; tree targs;
tree fn; tree fn;
...@@ -4705,6 +4656,8 @@ build_unary_op (code, xarg, noconvert) ...@@ -4705,6 +4656,8 @@ build_unary_op (code, xarg, noconvert)
return build1 (ADDR_EXPR, unknown_type_node, arg); return build1 (ADDR_EXPR, unknown_type_node, arg);
} }
else if (type_unknown_p (arg))
return build1 (ADDR_EXPR, unknown_type_node, arg);
/* Handle complex lvalues (when permitted) /* Handle complex lvalues (when permitted)
by reduction to simpler cases. */ by reduction to simpler cases. */
...@@ -4890,9 +4843,7 @@ unary_complex_lvalue (code, arg) ...@@ -4890,9 +4843,7 @@ unary_complex_lvalue (code, arg)
tree type; tree type;
if (TREE_OPERAND (arg, 0) if (TREE_OPERAND (arg, 0)
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR && ! is_dummy_object (TREE_OPERAND (arg, 0))
|| (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
!= error_mark_node))
&& TREE_CODE (t) != FIELD_DECL) && TREE_CODE (t) != FIELD_DECL)
{ {
cp_error ("taking address of bound pointer-to-member expression"); cp_error ("taking address of bound pointer-to-member expression");
...@@ -5770,7 +5721,7 @@ build_c_cast (type, expr) ...@@ -5770,7 +5721,7 @@ build_c_cast (type, expr)
if (TREE_CODE (type) == VOID_TYPE) if (TREE_CODE (type) == VOID_TYPE)
value = build1 (CONVERT_EXPR, type, value); value = build1 (CONVERT_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE else if (TREE_TYPE (value) == NULL_TREE
|| type_unknown_p (value)) || type_unknown_p (value))
{ {
value = instantiate_type (type, value, 1); value = instantiate_type (type, value, 1);
/* Did we lose? */ /* Did we lose? */
......
...@@ -352,19 +352,14 @@ ack (s, v, v2) ...@@ -352,19 +352,14 @@ ack (s, v, v2)
59 is, so they can understand how to work around it, should they 59 is, so they can understand how to work around it, should they
ever run into it. ever run into it.
Note, there will be no more calls in the C++ front end to abort,
because the C++ front end is so unreliable still. The C front end
can get away with calling abort, because for most of the calls to
abort on most machines, it, I suspect, can be proven that it is
impossible to ever call abort. The same is not yet true for C++,
one day, maybe it will be.
We used to tell people to "fix the above error[s] and try recompiling We used to tell people to "fix the above error[s] and try recompiling
the program" via a call to fatal, but that message tended to look the program" via a call to fatal, but that message tended to look
silly. So instead, we just do the equivalent of a call to fatal in the silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */ same situation (call exit).
/* First used: 0 (reserved), Last used: 369. Free: */ We used to assign sequential numbers for the aborts; now we use an
encoding of the date the abort was added, since that has more meaning
when we only see the error message. */
static int abortcount = 0; static int abortcount = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment