This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) patch to overhaul method reference handling
- To: egcs-patches at cygnus dot com
- Subject: (C++) patch to overhaul method reference handling
- From: Jason Merrill <jason at cygnus dot com>
- Date: Mon, 19 Oct 1998 20:12:43 -0700
Applied. In push_class_decls, we store one function out of however many
there are with the same name in the IDENTIFIER_CLASS_VALUE for that name.
Previously, we would sometimes use that function directly instead of doing
overload resolution; this patch causes us to build up a COMPONENT_REF
immediately, and fixes the code for doing that.
Fixes g++.bugs/900213_03.C, g++.other/pmf2.C, g++.robertl/eb131.C.
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.
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.113
diff -c -p -r1.113 call.c
*** call.c 1998/10/09 00:10:54 1.113
--- call.c 1998/10/20 03:02:56
*************** build_new_op (code, flags, arg1, arg2, a
*** 2513,2585 ****
{
case 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 DELETE_EXPR:
! {
! tree rval;
!
! 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:
return build_object_call (arg1, arg2);
--- 2513,2522 ----
{
case NEW_EXPR:
case VEC_NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
! /* Use build_op_new_call and build_op_delete_call instead. */
! my_friendly_abort (981018);
case CALL_EXPR:
return build_object_call (arg1, arg2);
*************** build_op_new_call (code, type, args, fla
*** 2898,2907 ****
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{
! tree dummy = build1 (NOP_EXPR, build_pointer_type (type),
! error_mark_node);
! dummy = build_indirect_ref (dummy, "new");
! return build_method_call (dummy, fnname, args, NULL_TREE, flags);
}
else
return build_new_function_call
--- 2835,2842 ----
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{
! return build_method_call (build_dummy_object (type),
! fnname, args, NULL_TREE, flags);
}
else
return build_new_function_call
*************** build_new_method_call (instance, name, a
*** 3716,3723 ****
&& value_member (cand->fn, get_abstract_virtuals (basetype)))
cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
! && TREE_CODE (instance_ptr) == NOP_EXPR
! && TREE_OPERAND (instance_ptr, 0) == error_mark_node)
cp_error ("cannot call member function `%D' without object", cand->fn);
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
--- 3651,3657 ----
&& value_member (cand->fn, get_abstract_virtuals (basetype)))
cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
! && is_dummy_object (instance_ptr))
cp_error ("cannot call member function `%D' without object", cand->fn);
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.96
diff -c -p -r1.96 class.c
*** class.c 1998/10/17 20:33:40 1.96
--- class.c 1998/10/20 03:02:56
*************** instantiate_type (lhstype, rhs, complain
*** 5045,5061 ****
if (function == error_mark_node)
return error_mark_node;
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
! if (DECL_VINDEX (function))
! {
! tree base = TREE_OPERAND (rhs, 0);
! tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
! 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);
return function;
}
--- 5045,5055 ----
if (function == error_mark_node)
return error_mark_node;
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
!
! if (! DECL_STATIC_FUNCTION_P (function))
! cp_error ("reference to `%D' can only be used in a call",
! function);
!
mark_used (function);
return function;
}
*************** instantiate_type (lhstype, rhs, complain
*** 5293,5341 ****
elem = OVL_NEXT (elem);
}
! /* No exact match found, look for a compatible method. */
! for (baselink = rhs; baselink;
! baselink = next_baselink (baselink))
! {
! 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)
cp_error ("no compatible member functions named `%D'", name);
return error_mark_node;
--- 5287,5297 ----
elem = OVL_NEXT (elem);
}
! name = rhs;
! while (TREE_CODE (name) == TREE_LIST)
! name = TREE_VALUE (name);
! name = DECL_NAME (OVL_CURRENT (name));
!
if (complain)
cp_error ("no compatible member functions named `%D'", name);
return error_mark_node;
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.155
diff -c -p -r1.155 cp-tree.h
*** cp-tree.h 1998/10/16 03:37:36 1.155
--- cp-tree.h 1998/10/20 03:02:56
*************** cp-tree.h PROTO((tree, tree
*** 3084,3089 ****
--- 3084,3092 ----
extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
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 scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list
Index: cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.36
diff -c -p -r1.36 cvt.c
*** cvt.c 1998/10/16 03:37:37 1.36
--- cvt.c 1998/10/20 03:02:56
*************** cp_convert_to_pointer (type, expr)
*** 107,127 ****
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
- tree decl, basebinfo;
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
! tree t = TYPE_METHOD_BASETYPE (fntype);
!
! 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);
}
--- 107,114 ----
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
! tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
expr = build (OFFSET_REF, fntype, decl, expr);
}
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.146
diff -c -p -r1.146 decl2.c
*** decl2.c 1998/10/18 09:21:17 1.146
--- decl2.c 1998/10/20 03:02:57
*************** arg_assoc (k, n)
*** 4539,4547 ****
--- 4539,4551 ----
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
+ if (TREE_CODE (n) == COMPONENT_REF)
+ n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
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)
{
/* [basic.lookup.koenig]
*************** arg_assoc (k, n)
*** 4604,4610 ****
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n))
! if (arg_assoc (k, OVL_FUNCTION (n)))
return 1;
}
--- 4608,4614 ----
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n))
! if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
return 1;
}
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.55
diff -c -p -r1.55 error.c
*** error.c 1998/10/06 14:19:54 1.55
--- error.c 1998/10/20 03:02:57
*************** dump_expr (t, nop)
*** 1577,1584 ****
case OFFSET_REF:
{
tree ob = TREE_OPERAND (t, 0);
! if (TREE_CODE (ob) == NOP_EXPR
! && TREE_OPERAND (ob, 0) == error_mark_node)
{
if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */
--- 1577,1583 ----
case OFFSET_REF:
{
tree ob = TREE_OPERAND (t, 0);
! if (is_dummy_object (ob))
{
if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.69
diff -c -p -r1.69 init.c
*** init.c 1998/10/16 03:37:40 1.69
--- init.c 1998/10/20 03:02:57
*************** build_member_call (type, name, parmlist)
*** 1359,1365 ****
tree t;
tree method_name;
int dtor = 0;
- int dont_use_this = 0;
tree basetype_path, decl;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR
--- 1359,1364 ----
*************** build_member_call (type, name, parmlist)
*** 1415,1438 ****
return error_mark_node;
}
! /* No object? Then just fake one up, and let build_method_call
! 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)
{
- basetype_path = TYPE_BINFO (type);
- 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 oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
--- 1414,1425 ----
return error_mark_node;
}
! decl = maybe_dummy_object (type, &basetype_path);
! /* Convert 'this' to the specified type to disambiguate conversion
! to the function's context. */
! if (decl == current_class_ref)
{
tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
*************** build_member_call (type, name, parmlist)
*** 1440,1452 ****
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
}
- else
- decl = olddecl;
}
- decl = build_indirect_ref (decl, NULL_PTR);
-
if (method_name == constructor_name (type)
|| method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist);
--- 1427,1436 ----
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
+ decl = build_indirect_ref (decl, NULL_PTR);
}
}
if (method_name == constructor_name (type)
|| method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist);
*************** build_member_call (type, name, parmlist)
*** 1463,1469 ****
return error_mark_node;
if (TREE_CODE (t) == FIELD_DECL)
{
! if (dont_use_this)
{
cp_error ("invalid use of non-static field `%D'", t);
return error_mark_node;
--- 1447,1453 ----
return error_mark_node;
if (TREE_CODE (t) == FIELD_DECL)
{
! if (is_dummy_object (decl))
{
cp_error ("invalid use of non-static field `%D'", t);
return error_mark_node;
*************** build_offset_ref (type, name)
*** 1569,1584 ****
return error_mark_node;
}
! if (current_class_type == 0
! || 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);
fields = lookup_field (basebinfo, name, 0, 0);
--- 1553,1559 ----
return error_mark_node;
}
! decl = maybe_dummy_object (type, &basebinfo);
fnfields = lookup_fnfields (basebinfo, name, 1);
fields = lookup_field (basebinfo, name, 0, 0);
*************** resolve_offset_ref (exp)
*** 1771,1779 ****
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
! && (base == current_class_ref
! || (TREE_CODE (base) == NOP_EXPR
! && TREE_OPERAND (base, 0) == error_mark_node)))
{
tree basetype_path;
tree access;
--- 1746,1752 ----
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
! && (base == current_class_ref || is_dummy_object (base)))
{
tree basetype_path;
tree access;
*************** resolve_offset_ref (exp)
*** 1815,1822 ****
}
/* Ensure that we have an object. */
! if (TREE_CODE (base) == NOP_EXPR
! && TREE_OPERAND (base, 0) == error_mark_node)
addr = error_mark_node;
else
/* If this is a reference to a member function, then return the
--- 1788,1794 ----
}
/* Ensure that we have an object. */
! if (is_dummy_object (base))
addr = error_mark_node;
else
/* If this is a reference to a member function, then return the
Index: method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.79
diff -c -p -r1.79 method.c
*** method.c 1998/10/16 12:07:58 1.79
--- method.c 1998/10/20 03:02:57
*************** hack_identifier (value, name)
*** 1866,1871 ****
--- 1866,1882 ----
TREE_USED (value) = 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))
{
#if 0
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.217
diff -c -p -r1.217 pt.c
*** pt.c 1998/10/17 20:33:43 1.217
--- pt.c 1998/10/20 03:02:57
*************** tsubst_copy (t, args, in_decl)
*** 5990,5995 ****
--- 5992,5998 ----
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case NOP_EXPR:
return build1
(code, tsubst (TREE_TYPE (t), args, in_decl),
tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.71
diff -c -p -r1.71 tree.c
*** tree.c 1998/10/17 20:33:45 1.71
--- tree.c 1998/10/20 03:02:58
*************** member_p (decl)
*** 2629,2631 ****
--- 2629,2684 ----
tree ctx = DECL_CONTEXT (decl);
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);
+ }
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.116
diff -c -p -r1.116 typeck.c
*** typeck.c 1998/10/16 03:37:41 1.116
--- typeck.c 1998/10/20 03:02:58
*************** build_component_ref (datum, component, b
*** 2078,2134 ****
return error_mark_node;
if (fndecls)
{
if (TREE_CHAIN (fndecls) == NULL_TREE
! && TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD)
{
! tree access, fndecl;
- /* Unique, so use this one now. */
basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
fndecl = TREE_VALUE (fndecls);
! access = compute_access (TREE_PURPOSE (fndecls), fndecl);
! if (access == access_public_node)
! {
! 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
{
! /* Just act like build_offset_ref, since the object does
! not matter unless we're actually calling the function. */
! tree t;
!
! t = build_tree_list (error_mark_node, fndecls);
! TREE_TYPE (t) = build_offset_type (basetype,
! unknown_type_node);
! return t;
}
}
--- 2078,2104 ----
return error_mark_node;
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
! && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL
! && DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
{
! tree fndecl;
basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
fndecl = TREE_VALUE (fndecls);
! enforce_access (TREE_PURPOSE (fndecls), fndecl);
! mark_used (fndecl);
! return fndecl;
}
else
{
! ref = build (COMPONENT_REF, unknown_type_node,
! datum, fndecls);
! return ref;
}
}
*************** build_x_function_call (function, params,
*** 2622,2630 ****
return error_mark_node;
}
/* Yow: call from a static member function. */
! decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
! error_mark_node);
! decl = build_indirect_ref (decl, NULL_PTR);
}
/* Put back explicit template arguments, if any. */
--- 2592,2598 ----
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. */
*************** build_x_function_call (function, params,
*** 2636,2647 ****
else if (TREE_CODE (function) == COMPONENT_REF
&& type == unknown_type_node)
{
! /* Should we undo what was done in build_component_ref? */
! if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)
! /* Get the name that build_component_ref hid. */
! function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
! else
! function = TREE_PURPOSE (TREE_OPERAND (function, 1));
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
--- 2604,2613 ----
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);
! function = DECL_NAME (OVL_CURRENT (TREE_VALUE (function)));
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
*************** build_component_addr (arg, argtype, msg)
*** 4248,4253 ****
--- 4214,4221 ----
tree basetype = decl_type_context (field);
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))
{
error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
*************** build_unary_op (code, xarg, noconvert)
*** 4665,4689 ****
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
! if (TREE_CODE (arg) == OVERLOAD
! || (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 fn;
--- 4633,4640 ----
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
! if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
tree targs;
tree fn;
*************** build_unary_op (code, xarg, noconvert)
*** 4705,4710 ****
--- 4656,4663 ----
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)
by reduction to simpler cases. */
*************** unary_complex_lvalue (code, arg)
*** 4890,4898 ****
tree type;
if (TREE_OPERAND (arg, 0)
! && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
! || (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
! != error_mark_node))
&& TREE_CODE (t) != FIELD_DECL)
{
cp_error ("taking address of bound pointer-to-member expression");
--- 4843,4849 ----
tree type;
if (TREE_OPERAND (arg, 0)
! && ! is_dummy_object (TREE_OPERAND (arg, 0))
&& TREE_CODE (t) != FIELD_DECL)
{
cp_error ("taking address of bound pointer-to-member expression");