Commit 4ac14744 by Mike Stump

86th Cygnus<->FSF quick merge

From-SVN: r11974
parent 62cb0901
...@@ -3,6 +3,82 @@ Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com> ...@@ -3,6 +3,82 @@ Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
* decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef. * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
(finish_file): Likewise. (finish_file): Likewise.
Wed May 15 14:46:14 1996 Mike Stump <mrs@cygnus.com>
* call.c (build_method_call): Allow implicit & on METHOD_TYPEs,
but pedwarn as the code is bogus.
* typeck.c (decay_conversion): Ditto.
(build_function_call_real): Use build_addr_func instead of
default_conversion. Don't allow pointer-to-method functions down
here.
(build_unary_op): Use real pointer-to-member functions instead of
fake ones.
(build_ptrmemfunc): Use build_addr_func instead of build_unary_op.
(convert_for_assignment): Removed some obsolete code.
* decl2.c (reparse_absdcl_as_expr): Pass current_class_ref to
build_x_function_call instead of current_class_ptr. Only call
digest_init once on an initializer, we do this just checking
TREE_TYPE.
(build_expr_from_tree): Pass current_class_ref to
build_x_function_call instead of current_class_ptr.
* init.c (build_member_call): Ditto.
* pase.y: Ditto.
* error.c (dump_expr): Handle OFFSET_REFs better.
* pt.c (unify): Handle pointer-to-member functions better.
* decl.c (finish_function): Clear out current_class_ref just like
we do for current_class_ptr.
* typeck.c (get_delta_difference): Handle virtual bases better.
Tue May 14 16:37:37 1996 Jason Merrill <jason@yorick.cygnus.com>
* sig.c (build_signature_table_constructor): Use the delta for
the original basetype for this virtual function with thunks.
(build_signature_method_call): We still need to adjust 'this'
with thunks.
Tue May 14 16:27:25 1996 Mike Stump <mrs@cygnus.com>
* call.c (build_addr_func): New routine. Used to get the `real'
address of a function or a method. Needed to avoid getting a
pointer-to-member function.
(build_call): New routine to build CALL_EXPRs.
(build_method_call): Use it.
* cvt.c (convert_to_aggr): Ditto.
* typeck.c (build_function_call_real): Ditto.
* sig.c (build_signature_table_constructor): Use build_addr_func.
* cp-tree.h (build_call, build_addr_func): Declare them.
Tue May 14 12:47:47 1996 Mike Stump <mrs@cygnus.com>
* cp-tree.h (LOOKUP_AGGR): Remove, unused.
* parse.y: Remove uses of LOOKUP_AGGR.
Tue May 14 12:07:51 1996 Mike Stump <mrs@cygnus.com>
* *.[chy]: Rename current_class_decl to current_class_ptr, and
C_C_D to current_class_ref.
Mon May 13 16:55:23 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (convert_harshness): Tighten up pointer conversions.
Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
* decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
(finish_file): Likewise.
Fri May 10 11:09:57 1996 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (convert_fn_ptr): We don't use thunks for pmfs.
* method.c (emit_thunk): Set flag_omit_frame_pointer in default
code.
Thu May 9 18:18:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c: Turn on thunks by default where supported.
Tue May 7 20:39:57 1996 Mike Stump <mrs@cygnus.com> Tue May 7 20:39:57 1996 Mike Stump <mrs@cygnus.com>
* cp-tree.h (build_overload_call_maybe): Removed. * cp-tree.h (build_overload_call_maybe): Removed.
......
...@@ -506,12 +506,6 @@ convert_harshness (type, parmtype, parm) ...@@ -506,12 +506,6 @@ convert_harshness (type, parmtype, parm)
if (TREE_CODE (ttl) != VOID_TYPE if (TREE_CODE (ttl) != VOID_TYPE
&& (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm))) && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
{ {
if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
{
ttl = unsigned_type (ttl);
ttr = unsigned_type (ttr);
penalty = 10;
}
if (comp_target_types (type, parmtype, 1) <= 0) if (comp_target_types (type, parmtype, 1) <= 0)
return EVIL_RETURN (h); return EVIL_RETURN (h);
} }
...@@ -526,22 +520,18 @@ convert_harshness (type, parmtype, parm) ...@@ -526,22 +520,18 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h); return EVIL_RETURN (h);
#endif #endif
if (penalty == 10 || ttr == ttl) if (ttr == ttl)
{ {
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype); tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
/* If one was unsigned but the other wasn't, then we need to h.code = 0;
do a standard conversion from T to unsigned T. */
if (penalty == 10)
h.code = PROMO_CODE; /* was STD_CODE */
else
h.code = 0;
/* Note conversion from `T*' to `const T*', /* Note conversion from `T*' to `const T*',
or `T*' to `volatile T*'. */ or `T*' to `volatile T*'. */
if (ttl == ttr if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
&& ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2)) || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
|| (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))) h.code = EVIL_CODE;
else if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
|| (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE; h.code |= QUAL_CODE;
h.distance = 0; h.distance = 0;
...@@ -580,8 +570,11 @@ convert_harshness (type, parmtype, parm) ...@@ -580,8 +570,11 @@ convert_harshness (type, parmtype, parm)
if (ttl != ttr) if (ttl != ttr)
{ {
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype); tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2)) if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
|| (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))) || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
h.code = EVIL_CODE;
else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
|| (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE; h.code |= QUAL_CODE;
} }
return h; return h;
...@@ -1192,7 +1185,7 @@ build_field_call (basetype_path, instance_ptr, name, parms) ...@@ -1192,7 +1185,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{ {
tree field, instance; tree field, instance;
if (instance_ptr == current_class_decl) if (instance_ptr == current_class_ptr)
{ {
/* Check to see if we really have a reference to an instance variable /* Check to see if we really have a reference to an instance variable
with `operator()()' overloaded. */ with `operator()()' overloaded. */
...@@ -1208,7 +1201,7 @@ build_field_call (basetype_path, instance_ptr, name, parms) ...@@ -1208,7 +1201,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{ {
/* If it's a field, try overloading operator (), /* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */ or calling if the field is a pointer-to-function. */
instance = build_component_ref_1 (C_C_D, field, 0); instance = build_component_ref_1 (current_class_ref, field, 0);
if (instance == error_mark_node) if (instance == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -1221,7 +1214,7 @@ build_field_call (basetype_path, instance_ptr, name, parms) ...@@ -1221,7 +1214,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
return build_function_call (instance, parms); return build_function_call (instance, parms);
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE) else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms)); return build_function_call (instance, tree_cons (NULL_TREE, current_class_ptr, parms));
} }
} }
return NULL_TREE; return NULL_TREE;
...@@ -1527,6 +1520,71 @@ print_n_candidates (candidates, n) ...@@ -1527,6 +1520,71 @@ print_n_candidates (candidates, n)
cp_error_at (" %D", candidates[i].function); cp_error_at (" %D", candidates[i].function);
} }
/* We want the address of a function or method. We avoid creating a
pointer-to-member function. */
tree
build_addr_func (function)
tree function;
{
tree type = TREE_TYPE (function);
/* We have to do these by hand to avoid real pointer to member
functions. */
if (TREE_CODE (type) == METHOD_TYPE)
{
tree addr;
type = build_pointer_type (type);
if (mark_addressable (function) == 0)
return error_mark_node;
addr = build1 (ADDR_EXPR, type, function);
/* Address of a static or external variable or function counts
as a constant */
if (staticp (function))
TREE_CONSTANT (addr) = 1;
function = addr;
}
else
function = default_conversion (function);
return function;
}
/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
POINTER_TYPE to those. Note, pointer to member function types
(TYPE_PTRMEMFUNC_P) must be handled by our callers. */
tree
build_call (function, result_type, parms)
tree function, result_type, parms;
{
int is_constructor = 0;
function = build_addr_func (function);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
sorry ("unable to call pointer to member function here");
return error_mark_node;
}
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
is_constructor = 1;
function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_TYPE (function) = result_type;
TREE_SIDE_EFFECTS (function) = 1;
return function;
}
/* Build something of the form ptr->method (args) /* Build something of the form ptr->method (args)
or object.method (args). This can also build or object.method (args). This can also build
calls to constructors, and find friends. calls to constructors, and find friends.
...@@ -1739,11 +1797,11 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1739,11 +1797,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
return error_mark_node; return error_mark_node;
} }
} }
else if (instance == C_C_D || instance == current_class_decl) else if (instance == current_class_ref || instance == current_class_ptr)
{ {
/* When doing initialization, we side-effect the TREE_TYPE of /* When doing initialization, we side-effect the TREE_TYPE of
C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */ current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
basetype = TREE_TYPE (C_C_D); basetype = TREE_TYPE (current_class_ref);
/* Anything manifestly `this' in constructors and destructors /* Anything manifestly `this' in constructors and destructors
has a known type, so virtual function tables are not needed. */ has a known type, so virtual function tables are not needed. */
...@@ -1765,8 +1823,8 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1765,8 +1823,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
} }
else else
{ {
instance = C_C_D; instance = current_class_ref;
instance_ptr = current_class_decl; instance_ptr = current_class_ptr;
basetype_path = TYPE_BINFO (current_class_type); basetype_path = TYPE_BINFO (current_class_type);
} }
result = build_field_call (basetype_path, instance_ptr, name, parms); result = build_field_call (basetype_path, instance_ptr, name, parms);
...@@ -1940,9 +1998,9 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1940,9 +1998,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm)); TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
t = TREE_TYPE (TREE_VALUE (parm)); t = TREE_TYPE (TREE_VALUE (parm));
} }
if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF if (TREE_CODE (t) == METHOD_TYPE)
&& TREE_CODE (t) == METHOD_TYPE)
{ {
cp_pedwarn ("assuming & on `%E'", TREE_VALUE (parm));
TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0); TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
} }
#if 0 #if 0
...@@ -2365,7 +2423,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2365,7 +2423,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
type (if it exists) is a pointer to. */ type (if it exists) is a pointer to. */
if (DECL_ABSTRACT_VIRTUAL_P (function) if (DECL_ABSTRACT_VIRTUAL_P (function)
&& instance == C_C_D && instance == current_class_ref
&& DECL_CONSTRUCTOR_P (current_function_decl) && DECL_CONSTRUCTOR_P (current_function_decl)
&& ! (flags & LOOKUP_NONVIRTUAL) && ! (flags & LOOKUP_NONVIRTUAL)
&& value_member (function, get_abstract_virtuals (basetype))) && value_member (function, get_abstract_virtuals (basetype)))
...@@ -2422,7 +2480,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2422,7 +2480,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
/* Let's be nasty to the user now, and give reasonable /* Let's be nasty to the user now, and give reasonable
error messages. */ error messages. */
instance_ptr = current_class_decl; instance_ptr = current_class_ptr;
if (instance_ptr) if (instance_ptr)
{ {
if (basetype != current_class_type) if (basetype != current_class_type)
...@@ -2540,21 +2598,9 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2540,21 +2598,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
GNU_xref_call (current_function_decl, GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function))); IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
{ result = build_call (function, value_type, parms);
int is_constructor result = convert_from_reference (result);
= TREE_CODE (function) == FUNCTION_DECL return result;
&& DECL_CONSTRUCTOR_P (function);
function = default_conversion (function);
result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
TREE_TYPE (result) = value_type;
TREE_SIDE_EFFECTS (result) = 1;
TREE_HAS_CONSTRUCTOR (result) = is_constructor;
result = convert_from_reference (result);
return result;
}
} }
/* Similar to `build_method_call', but for overloaded non-member functions. /* Similar to `build_method_call', but for overloaded non-member functions.
......
...@@ -72,7 +72,9 @@ struct class_level ...@@ -72,7 +72,9 @@ struct class_level
int unused; int unused;
}; };
tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */ /* The currect_class_ptr is the pointer to the current class.
current_class_ref is the actual current class. */
tree current_class_ptr, current_class_ref;
/* The following two can be derived from the previous one */ /* The following two can be derived from the previous one */
tree current_class_name; /* IDENTIFIER_NODE: name of current class */ tree current_class_name; /* IDENTIFIER_NODE: name of current class */
...@@ -434,7 +436,7 @@ build_vtbl_ref (instance, idx) ...@@ -434,7 +436,7 @@ build_vtbl_ref (instance, idx)
if (TREE_CODE (basetype) == REFERENCE_TYPE) if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype); basetype = TREE_TYPE (basetype);
if (instance == C_C_D) if (instance == current_class_ref)
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
NULL_PTR); NULL_PTR);
else else
...@@ -4494,7 +4496,7 @@ resolves_to_fixed_type_p (instance, nonnull) ...@@ -4494,7 +4496,7 @@ resolves_to_fixed_type_p (instance, nonnull)
} }
else if (nonnull) else if (nonnull)
{ {
if (instance == current_class_decl if (instance == current_class_ptr
&& flag_this_is_variable <= 0) && flag_this_is_variable <= 0)
{ {
/* Some people still use `this = 0' inside destructors. */ /* Some people still use `this = 0' inside destructors. */
...@@ -4941,12 +4943,6 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4941,12 +4943,6 @@ instantiate_type (lhstype, rhs, complain)
tree elem, baselink, name; tree elem, baselink, name;
int globals = overloaded_globals_p (rhs); int globals = overloaded_globals_p (rhs);
#if 0 /* obsolete */
/* If there's only one function we know about, return that. */
if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE)
return TREE_VALUE (rhs);
#endif
/* First look for an exact match. Search either overloaded /* First look for an exact match. Search either overloaded
functions or member functions. May have to undo what functions or member functions. May have to undo what
`default_conversion' might do to lhstype. */ `default_conversion' might do to lhstype. */
......
...@@ -1002,7 +1002,7 @@ struct lang_decl ...@@ -1002,7 +1002,7 @@ struct lang_decl
/* Nonzero for FUNCTION_DECL means that this constructor is known to /* Nonzero for FUNCTION_DECL means that this constructor is known to
not make any assignment to `this', and therefore can be trusted not make any assignment to `this', and therefore can be trusted
to return it unchanged. Otherwise, we must re-assign `current_class_decl' to return it unchanged. Otherwise, we must re-assign `current_class_ptr'
after performing base initializations. */ after performing base initializations. */
#define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg) #define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
...@@ -1551,7 +1551,8 @@ extern tree current_lang_name, lang_name_cplusplus, lang_name_c; ...@@ -1551,7 +1551,8 @@ extern tree current_lang_name, lang_name_cplusplus, lang_name_c;
of CURRENT_FUNCTION_DECL due to overloading */ of CURRENT_FUNCTION_DECL due to overloading */
extern tree original_function_name; extern tree original_function_name;
extern tree current_class_name, current_class_type, current_class_decl, C_C_D; extern tree current_class_name, current_class_type;
extern tree current_class_ptr, current_class_ref;
/* in init.c */ /* in init.c */
extern tree global_base_init_list; extern tree global_base_init_list;
...@@ -1820,8 +1821,6 @@ extern int at_eof; ...@@ -1820,8 +1821,6 @@ extern int at_eof;
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG }; enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
/* The following two can be derived from the previous one */ /* The following two can be derived from the previous one */
extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
extern tree current_class_type; /* _TYPE: the type of the current class */ extern tree current_class_type; /* _TYPE: the type of the current class */
...@@ -1838,7 +1837,6 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1838,7 +1837,6 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
LOOKUP_COMPLAIN mean complain if no suitable member function LOOKUP_COMPLAIN mean complain if no suitable member function
matching the arguments is found. matching the arguments is found.
LOOKUP_NORMAL is just a combination of these two. LOOKUP_NORMAL is just a combination of these two.
LOOKUP_AGGR requires the instance to be of aggregate type.
LOOKUP_NONVIRTUAL means make a direct call to the member function found LOOKUP_NONVIRTUAL means make a direct call to the member function found
LOOKUP_GLOBAL means search through the space of overloaded functions, LOOKUP_GLOBAL means search through the space of overloaded functions,
as well as the space of member functions. as well as the space of member functions.
...@@ -1858,7 +1856,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1858,7 +1856,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define LOOKUP_PROTECT (1) #define LOOKUP_PROTECT (1)
#define LOOKUP_COMPLAIN (2) #define LOOKUP_COMPLAIN (2)
#define LOOKUP_NORMAL (3) #define LOOKUP_NORMAL (3)
#define LOOKUP_AGGR (4) /* #define LOOKUP_UNUSED (4) */
#define LOOKUP_NONVIRTUAL (8) #define LOOKUP_NONVIRTUAL (8)
#define LOOKUP_GLOBAL (16) #define LOOKUP_GLOBAL (16)
#define LOOKUP_HAS_IN_CHARGE (32) #define LOOKUP_HAS_IN_CHARGE (32)
...@@ -1941,6 +1939,8 @@ extern int get_arglist_len_in_bytes PROTO((tree)); ...@@ -1941,6 +1939,8 @@ extern int get_arglist_len_in_bytes PROTO((tree));
extern tree build_vfield_ref PROTO((tree, tree)); extern tree build_vfield_ref PROTO((tree, tree));
extern tree find_scoped_type PROTO((tree, tree, tree)); extern tree find_scoped_type PROTO((tree, tree, tree));
extern tree resolve_scope_to_name PROTO((tree, tree)); extern tree resolve_scope_to_name PROTO((tree, tree));
extern tree build_call PROTO((tree, tree, tree));
extern tree build_addr_func PROTO((tree));
extern tree build_scoped_method_call PROTO((tree, tree, tree, tree)); extern tree build_scoped_method_call PROTO((tree, tree, tree, tree));
extern tree build_method_call PROTO((tree, tree, tree, tree, int)); extern tree build_method_call PROTO((tree, tree, tree, tree, int));
extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int)); extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int));
......
...@@ -82,6 +82,7 @@ static tree ...@@ -82,6 +82,7 @@ static tree
convert_fn_ptr (type, expr) convert_fn_ptr (type, expr)
tree type, expr; tree type, expr;
{ {
#if 0 /* We don't use thunks for pmfs. */
if (flag_vtable_thunks) if (flag_vtable_thunks)
{ {
tree intype = TREE_TYPE (expr); tree intype = TREE_TYPE (expr);
...@@ -104,6 +105,7 @@ convert_fn_ptr (type, expr) ...@@ -104,6 +105,7 @@ convert_fn_ptr (type, expr)
return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr)); return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
} }
else else
#endif
return build_ptrmemfunc (type, expr, 1); return build_ptrmemfunc (type, expr, 1);
} }
...@@ -477,7 +479,7 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -477,7 +479,7 @@ build_up_reference (type, arg, flags, checkconst)
case PARM_DECL: case PARM_DECL:
#if 0 #if 0
if (targ == current_class_decl) if (targ == current_class_ptr)
{ {
error ("address of `this' not available"); error ("address of `this' not available");
/* #if 0 */ /* #if 0 */
...@@ -1056,14 +1058,11 @@ convert_to_aggr (type, expr, msgp, protect) ...@@ -1056,14 +1058,11 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE; return NULL_TREE;
fntype = TREE_TYPE (function); fntype = TREE_TYPE (function);
function = default_conversion (function);
parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
result = build_nt (CALL_EXPR, function, parmlist, NULL_TREE, LOOKUP_NORMAL);
convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
parmlist, NULL_TREE, LOOKUP_NORMAL), result = build_call (function, TREE_TYPE (fntype), parmlist);
NULL_TREE);
TREE_TYPE (result) = TREE_TYPE (fntype);
TREE_SIDE_EFFECTS (result) = 1;
return result; return result;
} }
...@@ -1809,3 +1808,166 @@ type_promotes_to (type) ...@@ -1809,3 +1808,166 @@ type_promotes_to (type)
return cp_build_type_variant (type, constp, volatilep); return cp_build_type_variant (type, constp, volatilep);
} }
#if 0
/* Work in progress. Ask jason before removing. */
int
null_ptr_cst (t)
tree t;
{
return (INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t));
}
tree
standard_conversion (to, from, expr)
tree to, from, expr;
{
enum tree_code fcode = TREE_CODE (from);
enum tree_code tcode = TREE_CODE (to);
tree conv;
if (from == to)
return from;
conv = from;
if (fcode == FUNCTION_TYPE)
{
from = build_pointer_type (from);
fcode = TREE_CODE (from);
conv = build1 (LVALUE_CONV, from, conv);
}
else if (fcode == ARRAY_TYPE)
{
from = build_pointer_type (TREE_TYPE (from));
fcode = TREE_CODE (from);
conv = build1 (LVALUE_CONV, from, conv);
}
if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
&& expr && null_ptr_cst (expr))
{
conv = build1 (CONV_CONV, to, conv);
}
else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
{
enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))), 1))
/* OK for now */;
else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
&& ufcode != FUNCTION_TYPE)
{
from = cp_build_type_variant (void_type_node,
TYPE_READONLY (TREE_TYPE (from)),
TYPE_VOLATILE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
{
tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
if (DERIVED_FROM_P (tbase, fbase)
&& (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))),
1)))
{
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
}
else
return 0;
}
else if (IS_AGGR_TYPE (TREE_TYPE (from))
&& IS_AGGR_TYPE (TREE_TYPE (to)))
{
if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
{
from = cp_build_type_variant (TREE_TYPE (to),
TYPE_READONLY (TREE_TYPE (from)),
TYPE_VOLATILE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
}
else
return 0;
}
else
return 0;
if (! comptypes (from, to, 1) && comp_ptr_ttypes (to, from))
{
from = to;
conv = build1 (QUAL_CONV, from, conv);
}
}
else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
{
tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from));
tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to));
tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
if (! DERIVED_FROM_P (tbase, fbase)
|| ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1)
|| ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1)
|| TYPE_READONLY (fbase) != TYPE_READONLY (tbase)
|| TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase))
return 0;
from = cp_build_type_variant (tbase, TYPE_READONLY (fbase),
TYPE_VOLATILE (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
conv = build1 (CONV_CONV, from, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
if (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
|| fcode == POINTER_TYPE)
return build1 (CONV_CONV, to, conv);
else
return 0;
}
else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
else if (to == type_promotes_to (from))
conv = build1 (PROMO_CONV, to, conv);
else
conv = build1 (CONV_CONV, to, conv);
}
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from))
{
conv = build1 (CONV_CONV, to, conv);
}
else
return 0;
return conv;
}
tree
implicit_conversion (to, from, expr, flags)
tree to, from, expr;
int flags;
{
tree conv = standard_conversion (to, from, expr);
if (conv || (flags & LOOKUP_NO_CONVERSION))
return conv;
flags |= LOOKUP_NO_CONVERSION;
/* try constructors */;
/* try conversion ops */;
return conv;
}
#endif
...@@ -3275,7 +3275,7 @@ pushdecl (x) ...@@ -3275,7 +3275,7 @@ pushdecl (x)
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter"; warnstring = "declaration of `%s' shadows a parameter";
else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
&& current_class_decl && current_class_ptr
&& !TREE_STATIC (name)) && !TREE_STATIC (name))
warnstring = "declaration of `%s' shadows a member of `this'"; warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE) else if (oldlocal != NULL_TREE)
...@@ -11075,14 +11075,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) ...@@ -11075,14 +11075,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
push_nested_class (ctype, 1); push_nested_class (ctype, 1);
/* If we're compiling a friend function, neither of the variables /* If we're compiling a friend function, neither of the variables
current_class_decl nor current_class_type will have values. */ current_class_ptr nor current_class_type will have values. */
if (! doing_friend) if (! doing_friend)
{ {
/* We know that this was set up by `grokclassfn'. /* We know that this was set up by `grokclassfn'.
We do not wait until `store_parm_decls', since evil We do not wait until `store_parm_decls', since evil
parse errors may never get us to that point. Here parse errors may never get us to that point. Here
we keep the consistency between `current_class_type' we keep the consistency between `current_class_type'
and `current_class_decl'. */ and `current_class_ptr'. */
tree t = current_function_parms; tree t = current_function_parms;
my_friendly_assert (t != NULL_TREE my_friendly_assert (t != NULL_TREE
...@@ -11093,14 +11093,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) ...@@ -11093,14 +11093,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
int i = suspend_momentary (); int i = suspend_momentary ();
/* Fool build_indirect_ref. */ /* Fool build_indirect_ref. */
current_class_decl = NULL_TREE; current_class_ptr = NULL_TREE;
C_C_D = build_indirect_ref (t, NULL_PTR); current_class_ref = build_indirect_ref (t, NULL_PTR);
current_class_decl = t; current_class_ptr = t;
resume_momentary (i); resume_momentary (i);
} }
else else
/* We're having a signature pointer here. */ /* We're having a signature pointer here. */
C_C_D = current_class_decl = t; current_class_ref = current_class_ptr = t;
} }
} }
...@@ -11110,7 +11110,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) ...@@ -11110,7 +11110,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
push_nested_class (DECL_CONTEXT (decl1), 2); push_nested_class (DECL_CONTEXT (decl1), 2);
else else
push_memoized_context (0, 1); push_memoized_context (0, 1);
current_class_decl = C_C_D = NULL_TREE; current_class_ptr = current_class_ref = NULL_TREE;
} }
pushlevel (0); pushlevel (0);
...@@ -11502,7 +11502,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11502,7 +11502,7 @@ finish_function (lineno, call_poplevel, nested)
if (current_function_assigns_this) if (current_function_assigns_this)
cond = build (NE_EXPR, boolean_type_node, cond = build (NE_EXPR, boolean_type_node,
current_class_decl, integer_zero_node); current_class_ptr, integer_zero_node);
else else
{ {
int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
...@@ -11541,10 +11541,10 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11541,10 +11541,10 @@ finish_function (lineno, call_poplevel, nested)
/* These are two cases where we cannot delegate deletion. */ /* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
|| TYPE_GETS_REG_DELETE (current_class_type)) || TYPE_GETS_REG_DELETE (current_class_type))
exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node, exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
else else
exprstmt = build_delete (current_class_type, C_C_D, in_charge_node, exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
/* If we did not assign to this, then `this' is non-zero at /* If we did not assign to this, then `this' is non-zero at
...@@ -11576,7 +11576,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11576,7 +11576,7 @@ finish_function (lineno, call_poplevel, nested)
{ {
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
{ {
tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl); tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_ptr);
expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)), expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
ptr, integer_zero_node, ptr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0)); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
...@@ -11605,11 +11605,11 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11605,11 +11605,11 @@ finish_function (lineno, call_poplevel, nested)
error_mark_node), error_mark_node),
NULL_PTR), NULL_PTR),
ansi_opname[(int) DELETE_EXPR], ansi_opname[(int) DELETE_EXPR],
tree_cons (NULL_TREE, current_class_decl, tree_cons (NULL_TREE, current_class_ptr,
build_tree_list (NULL_TREE, virtual_size)), build_tree_list (NULL_TREE, virtual_size)),
NULL_TREE, LOOKUP_NORMAL); NULL_TREE, LOOKUP_NORMAL);
else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0, exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0,
virtual_size); virtual_size);
else else
exprstmt = NULL_TREE; exprstmt = NULL_TREE;
...@@ -11646,16 +11646,16 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11646,16 +11646,16 @@ finish_function (lineno, call_poplevel, nested)
/* Make all virtual function table pointers in non-virtual base /* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function classes point to CURRENT_CLASS_TYPE's virtual function
tables. */ tables. */
expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl); expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl); expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr);
} }
if (! ok_to_optimize_dtor) if (! ok_to_optimize_dtor)
{ {
cond = build_binary_op (NE_EXPR, cond = build_binary_op (NE_EXPR,
current_class_decl, integer_zero_node, 1); current_class_ptr, integer_zero_node, 1);
expand_start_cond (cond, 0); expand_start_cond (cond, 0);
} }
...@@ -11691,7 +11691,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11691,7 +11691,7 @@ finish_function (lineno, call_poplevel, nested)
expand_end_bindings (decls, decls != NULL_TREE, 0); expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0); poplevel (decls != NULL_TREE, 0, 0);
} }
c_expand_return (current_class_decl); c_expand_return (current_class_ptr);
} }
else if (TYPE_MAIN_VARIANT (TREE_TYPE ( else if (TYPE_MAIN_VARIANT (TREE_TYPE (
DECL_RESULT (current_function_decl))) != void_type_node DECL_RESULT (current_function_decl))) != void_type_node
...@@ -11715,8 +11715,8 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11715,8 +11715,8 @@ finish_function (lineno, call_poplevel, nested)
if (flag_this_is_variable > 0) if (flag_this_is_variable > 0)
{ {
cond = build_binary_op (EQ_EXPR, cond = build_binary_op (EQ_EXPR,
current_class_decl, integer_zero_node, 1); current_class_ptr, integer_zero_node, 1);
thenclause = build_modify_expr (current_class_decl, NOP_EXPR, thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0)); build_new (NULL_TREE, current_class_type, void_type_node, 0));
} }
...@@ -11769,7 +11769,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11769,7 +11769,7 @@ finish_function (lineno, call_poplevel, nested)
poplevel (decls != NULL_TREE, 1, 0); poplevel (decls != NULL_TREE, 1, 0);
} }
c_expand_return (current_class_decl); c_expand_return (current_class_ptr);
current_function_assigns_this = 0; current_function_assigns_this = 0;
current_function_just_assigned_this = 0; current_function_just_assigned_this = 0;
...@@ -11974,7 +11974,8 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11974,7 +11974,8 @@ finish_function (lineno, call_poplevel, nested)
} }
named_label_uses = NULL_TREE; named_label_uses = NULL_TREE;
current_class_decl = NULL_TREE; current_class_ptr = NULL_TREE;
current_class_ref = NULL_TREE;
} }
/* Create the FUNCTION_DECL for a function definition. /* Create the FUNCTION_DECL for a function definition.
...@@ -12412,8 +12413,8 @@ struct cp_function ...@@ -12412,8 +12413,8 @@ struct cp_function
tree base_init_list; tree base_init_list;
tree member_init_list; tree member_init_list;
tree base_init_expr; tree base_init_expr;
tree class_decl; tree current_class_ptr;
tree C_C_D; tree current_class_ref;
rtx result_rtx; rtx result_rtx;
struct cp_function *next; struct cp_function *next;
struct binding_level *binding_level; struct binding_level *binding_level;
...@@ -12459,8 +12460,8 @@ push_cp_function_context (context) ...@@ -12459,8 +12460,8 @@ push_cp_function_context (context)
p->temp_name_counter = temp_name_counter; p->temp_name_counter = temp_name_counter;
p->base_init_list = current_base_init_list; p->base_init_list = current_base_init_list;
p->member_init_list = current_member_init_list; p->member_init_list = current_member_init_list;
p->class_decl = current_class_decl; p->current_class_ptr = current_class_ptr;
p->C_C_D = C_C_D; p->current_class_ref = current_class_ref;
p->eh_context = push_eh_context (); p->eh_context = push_eh_context ();
} }
...@@ -12502,8 +12503,8 @@ pop_cp_function_context (context) ...@@ -12502,8 +12503,8 @@ pop_cp_function_context (context)
temp_name_counter = p->temp_name_counter; temp_name_counter = p->temp_name_counter;
current_base_init_list = p->base_init_list; current_base_init_list = p->base_init_list;
current_member_init_list = p->member_init_list; current_member_init_list = p->member_init_list;
current_class_decl = p->class_decl; current_class_ptr = p->current_class_ptr;
C_C_D = p->C_C_D; current_class_ref = p->current_class_ref;
pop_eh_context (p->eh_context); pop_eh_context (p->eh_context);
......
...@@ -155,9 +155,13 @@ int warn_implicit = 1; ...@@ -155,9 +155,13 @@ int warn_implicit = 1;
int warn_ctor_dtor_privacy = 1; int warn_ctor_dtor_privacy = 1;
/* True if we want to implement vtables using "thunks". /* True if we want to implement vtables using "thunks".
The default is off now, but will be on later. */ The default is off by default, on if explicitly supported. */
#ifdef ASM_OUTPUT_MI_THUNK
int flag_vtable_thunks = 1;
#else
int flag_vtable_thunks; int flag_vtable_thunks;
#endif
/* True if we want to deal with repository information. */ /* True if we want to deal with repository information. */
...@@ -3336,7 +3340,7 @@ reparse_absdcl_as_expr (type, decl) ...@@ -3336,7 +3340,7 @@ reparse_absdcl_as_expr (type, decl)
/* recurse */ /* recurse */
decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0)); decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_decl); decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node) if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
decl = require_complete_type (decl); decl = require_complete_type (decl);
...@@ -3357,7 +3361,8 @@ reparse_absdcl_as_casts (decl, expr) ...@@ -3357,7 +3361,8 @@ reparse_absdcl_as_casts (decl, expr)
{ {
tree type; tree type;
if (TREE_CODE (expr) == CONSTRUCTOR) if (TREE_CODE (expr) == CONSTRUCTOR
&& TREE_TYPE (expr) == 0)
{ {
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0); decl = TREE_OPERAND (decl, 0);
...@@ -3556,7 +3561,7 @@ build_expr_from_tree (t) ...@@ -3556,7 +3561,7 @@ build_expr_from_tree (t)
name = build_expr_from_tree (name); name = build_expr_from_tree (name);
return build_x_function_call return build_x_function_call
(name, build_expr_from_tree (TREE_OPERAND (t, 1)), (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
current_class_decl); current_class_ref);
} }
case COND_EXPR: case COND_EXPR:
......
...@@ -1259,8 +1259,9 @@ dump_expr (t, nop) ...@@ -1259,8 +1259,9 @@ dump_expr (t, nop)
dump_expr (TREE_OPERAND (t, 1), 0); dump_expr (TREE_OPERAND (t, 1), 0);
else else
{ {
sorry ("operand of OFFSET_REF not understood"); dump_expr (TREE_OPERAND (t, 0), 0);
goto error; OB_PUTS (" .* ");
dump_expr (TREE_OPERAND (t, 1), 0);
} }
break; break;
} }
......
...@@ -174,7 +174,7 @@ perform_member_init (member, name, init, explicit, protect_list) ...@@ -174,7 +174,7 @@ perform_member_init (member, name, init, explicit, protect_list)
if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST) if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
init = build_tree_list (NULL_TREE, init); init = build_tree_list (NULL_TREE, init);
decl = build_component_ref (C_C_D, name, NULL_TREE, explicit); decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
if (explicit if (explicit
&& TREE_CODE (type) == ARRAY_TYPE && TREE_CODE (type) == ARRAY_TYPE
...@@ -220,7 +220,7 @@ perform_member_init (member, name, init, explicit, protect_list) ...@@ -220,7 +220,7 @@ perform_member_init (member, name, init, explicit, protect_list)
current_member_init_list. */ current_member_init_list. */
if (init || explicit) if (init || explicit)
{ {
decl = build_component_ref (C_C_D, name, NULL_TREE, explicit); decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
} }
...@@ -237,7 +237,7 @@ perform_member_init (member, name, init, explicit, protect_list) ...@@ -237,7 +237,7 @@ perform_member_init (member, name, init, explicit, protect_list)
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
{ {
tree expr = build_component_ref (C_C_D, name, NULL_TREE, explicit); tree expr = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
expr = build_delete (type, expr, integer_zero_node, expr = build_delete (type, expr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
...@@ -487,7 +487,7 @@ build_partial_cleanup_for (binfo) ...@@ -487,7 +487,7 @@ build_partial_cleanup_for (binfo)
tree binfo; tree binfo;
{ {
tree expr = convert_pointer_to_real (binfo, tree expr = convert_pointer_to_real (binfo,
build_unary_op (ADDR_EXPR, C_C_D, 0)); build_unary_op (ADDR_EXPR, current_class_ref, 0));
return build_delete (TREE_TYPE (expr), return build_delete (TREE_TYPE (expr),
expr, expr,
...@@ -561,7 +561,7 @@ emit_base_init (t, immediately) ...@@ -561,7 +561,7 @@ emit_base_init (t, immediately)
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
expand_start_cond (first_arg, 0); expand_start_cond (first_arg, 0);
expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl, expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
vbase_init_list); vbase_init_list);
expand_end_cond (); expand_end_cond ();
} }
...@@ -596,7 +596,7 @@ emit_base_init (t, immediately) ...@@ -596,7 +596,7 @@ emit_base_init (t, immediately)
push_temp_slots (); push_temp_slots ();
target_temp_slot_level = temp_slot_level; target_temp_slot_level = temp_slot_level;
member = convert_pointer_to_real (base_binfo, current_class_decl); member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE, expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL); BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
...@@ -626,11 +626,11 @@ emit_base_init (t, immediately) ...@@ -626,11 +626,11 @@ emit_base_init (t, immediately)
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do come from virtual base classes. */ do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl); expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do not come from virtual base classes. */ do not come from virtual base classes. */
expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl); expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
{ {
...@@ -863,7 +863,7 @@ do_member_init (s_id, name, init) ...@@ -863,7 +863,7 @@ do_member_init (s_id, name, init)
return; return;
} }
base = convert_pointer_to (binfo, current_class_decl); base = convert_pointer_to (binfo, current_class_ptr);
expand_member_init (build_indirect_ref (base, NULL_PTR), name, init); expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
} }
...@@ -1139,8 +1139,9 @@ expand_member_init (exp, name, init) ...@@ -1139,8 +1139,9 @@ expand_member_init (exp, name, init)
explaining that such initializations are invalid. explaining that such initializations are invalid.
ALIAS_THIS is nonzero iff we are initializing something which is ALIAS_THIS is nonzero iff we are initializing something which is
essentially an alias for C_C_D. In this case, the base constructor essentially an alias for current_class_ref. In this case, the base
may move it on us, and we must keep track of such deviations. constructor may move it on us, and we must keep track of such
deviations.
If INIT resolves to a CALL_EXPR which happens to return If INIT resolves to a CALL_EXPR which happens to return
something of the type we are looking for, then we know something of the type we are looking for, then we know
...@@ -1160,8 +1161,7 @@ expand_member_init (exp, name, init) ...@@ -1160,8 +1161,7 @@ expand_member_init (exp, name, init)
initialization. initialization.
A constructor or a conversion operator may have to be used to A constructor or a conversion operator may have to be used to
perform the initialization, but not both, as it would be ambiguous. perform the initialization, but not both, as it would be ambiguous. */
*/
void void
expand_aggr_init (exp, init, alias_this, flags) expand_aggr_init (exp, init, alias_this, flags)
...@@ -1318,8 +1318,8 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags) ...@@ -1318,8 +1318,8 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
value is used in the derived class. */ value is used in the derived class. */
if ((flag_this_is_variable & 1) && alias_this) if ((flag_this_is_variable & 1) && alias_this)
{ {
TREE_TYPE (rval) = TREE_TYPE (current_class_decl); TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
expand_assignment (current_class_decl, rval, 0, 0); expand_assignment (current_class_ptr, rval, 0, 0);
} }
else else
expand_expr_stmt (rval); expand_expr_stmt (rval);
...@@ -1676,7 +1676,7 @@ build_member_call (type, name, parmlist) ...@@ -1676,7 +1676,7 @@ build_member_call (type, name, parmlist)
tree ns = lookup_name (type, 0); tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL) if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
{ {
return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_decl); return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
} }
} }
...@@ -1705,14 +1705,14 @@ build_member_call (type, name, parmlist) ...@@ -1705,14 +1705,14 @@ build_member_call (type, name, parmlist)
basetype_path = TYPE_BINFO (type); basetype_path = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node); decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
} }
else if (current_class_decl == 0) else if (current_class_ptr == 0)
{ {
dont_use_this = 1; dont_use_this = 1;
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node); decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
} }
else else
{ {
tree olddecl = current_class_decl; tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl)); tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type) if (oldtype != type)
{ {
...@@ -1846,10 +1846,10 @@ build_offset_ref (type, name) ...@@ -1846,10 +1846,10 @@ build_offset_ref (type, name)
basebinfo = TYPE_BINFO (type); basebinfo = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, type, error_mark_node); decl = build1 (NOP_EXPR, type, error_mark_node);
} }
else if (current_class_decl == 0) else if (current_class_ptr == 0)
decl = build1 (NOP_EXPR, type, error_mark_node); decl = build1 (NOP_EXPR, type, error_mark_node);
else else
decl = C_C_D; decl = current_class_ref;
if (constructor_name (BINFO_TYPE (basebinfo)) == name) if (constructor_name (BINFO_TYPE (basebinfo)) == name)
if (dtor) if (dtor)
...@@ -1978,7 +1978,12 @@ resolve_offset_ref (exp) ...@@ -1978,7 +1978,12 @@ resolve_offset_ref (exp)
if (TREE_CODE (exp) == TREE_LIST) if (TREE_CODE (exp) == TREE_LIST)
return build_unary_op (ADDR_EXPR, exp, 0); return build_unary_op (ADDR_EXPR, exp, 0);
if (TREE_CODE (exp) != OFFSET_REF) if (TREE_CODE (exp) == OFFSET_REF)
{
member = TREE_OPERAND (exp, 1);
base = TREE_OPERAND (exp, 0);
}
else
{ {
my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214); my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214);
if (TYPE_OFFSET_BASETYPE (type) != current_class_type) if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
...@@ -1988,12 +1993,7 @@ resolve_offset_ref (exp) ...@@ -1988,12 +1993,7 @@ resolve_offset_ref (exp)
} }
member = exp; member = exp;
type = TREE_TYPE (type); type = TREE_TYPE (type);
base = C_C_D; base = current_class_ref;
}
else
{
member = TREE_OPERAND (exp, 1);
base = TREE_OPERAND (exp, 0);
} }
if ((TREE_CODE (member) == VAR_DECL if ((TREE_CODE (member) == VAR_DECL
...@@ -2008,7 +2008,7 @@ resolve_offset_ref (exp) ...@@ -2008,7 +2008,7 @@ resolve_offset_ref (exp)
/* Syntax error can cause a member which should /* Syntax error can cause a member which should
have been seen as static to be grok'd as non-static. */ have been seen as static to be grok'd as non-static. */
if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE) if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
{ {
if (TREE_ADDRESSABLE (member) == 0) if (TREE_ADDRESSABLE (member) == 0)
{ {
...@@ -2022,7 +2022,7 @@ resolve_offset_ref (exp) ...@@ -2022,7 +2022,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 == C_C_D && (base == current_class_ref
|| (TREE_CODE (base) == NOP_EXPR || (TREE_CODE (base) == NOP_EXPR
&& TREE_OPERAND (base, 0) == error_mark_node))) && TREE_OPERAND (base, 0) == error_mark_node)))
{ {
...@@ -2033,7 +2033,7 @@ resolve_offset_ref (exp) ...@@ -2033,7 +2033,7 @@ resolve_offset_ref (exp)
else else
basetype = DECL_CONTEXT (member); basetype = DECL_CONTEXT (member);
base = current_class_decl; base = current_class_ptr;
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0) if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
{ {
...@@ -3555,8 +3555,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3555,8 +3555,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
addr = convert_force (build_pointer_type (type), addr, 0); addr = convert_force (build_pointer_type (type), addr, 0);
if (TREE_CODE (addr) == NOP_EXPR if (TREE_CODE (addr) == NOP_EXPR
&& TREE_OPERAND (addr, 0) == current_class_decl) && TREE_OPERAND (addr, 0) == current_class_ptr)
ref = C_C_D; ref = current_class_ref;
else else
ref = build_indirect_ref (addr, NULL_PTR); ref = build_indirect_ref (addr, NULL_PTR);
ptr = 0; ptr = 0;
......
...@@ -1549,19 +1549,19 @@ hack_identifier (value, name) ...@@ -1549,19 +1549,19 @@ hack_identifier (value, name)
type = TREE_TYPE (value); type = TREE_TYPE (value);
if (TREE_CODE (value) == FIELD_DECL) if (TREE_CODE (value) == FIELD_DECL)
{ {
if (current_class_decl == NULL_TREE) if (current_class_ptr == NULL_TREE)
{ {
error ("request for member `%s' in static member function", error ("request for member `%s' in static member function",
IDENTIFIER_POINTER (DECL_NAME (value))); IDENTIFIER_POINTER (DECL_NAME (value)));
return error_mark_node; return error_mark_node;
} }
TREE_USED (current_class_decl) = 1; TREE_USED (current_class_ptr) = 1;
/* Mark so that if we are in a constructor, and then find that /* Mark so that if we are in a constructor, and then find that
this field was initialized by a base initializer, this field was initialized by a base initializer,
we can emit an error message. */ we can emit an error message. */
TREE_USED (value) = 1; TREE_USED (value) = 1;
value = build_component_ref (C_C_D, name, NULL_TREE, 1); value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
} }
else if (really_overloaded_fn (value)) else if (really_overloaded_fn (value))
{ {
...@@ -1653,141 +1653,6 @@ hack_identifier (value, name) ...@@ -1653,141 +1653,6 @@ hack_identifier (value, name)
} }
#if 0
/* Given an object OF, and a type conversion operator COMPONENT
build a call to the conversion operator, if a call is requested,
or return the address (as a pointer to member function) if one is not.
OF can be a TYPE_DECL or any kind of datum that would normally
be passed to `build_component_ref'. It may also be NULL_TREE,
in which case `current_class_type' and `current_class_decl'
provide default values.
BASETYPE_PATH, if non-null, is the path of basetypes
to go through before we get the the instance of interest.
PROTECT says whether we apply C++ scoping rules or not. */
tree
build_component_type_expr (of, component, basetype_path, protect)
tree of, component, basetype_path;
int protect;
{
tree cname = NULL_TREE;
tree tmp, last;
tree name;
int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;
if (of)
my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);
my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);
tmp = TREE_OPERAND (component, 0);
last = NULL_TREE;
while (tmp)
{
switch (TREE_CODE (tmp))
{
case CALL_EXPR:
if (last)
TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
else
TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);
last = groktypename (build_tree_list (TREE_TYPE (component),
TREE_OPERAND (component, 0)));
name = build_typename_overload (last);
TREE_TYPE (name) = last;
if (TREE_OPERAND (tmp, 0)
&& TREE_OPERAND (tmp, 0) != void_list_node)
{
cp_error ("`operator %T' requires empty parameter list", last);
TREE_OPERAND (tmp, 0) = NULL_TREE;
}
if (of && TREE_CODE (of) != TYPE_DECL)
return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
else if (of)
{
tree this_this;
if (current_class_decl == NULL_TREE)
{
cp_error ("object required for `operator %T' call",
TREE_TYPE (name));
return error_mark_node;
}
this_this = convert_pointer_to (TREE_TYPE (of),
current_class_decl);
this_this = build_indirect_ref (this_this, NULL_PTR);
return build_method_call (this_this, name, NULL_TREE,
NULL_TREE, flags | LOOKUP_NONVIRTUAL);
}
else if (current_class_decl)
return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);
cp_error ("object required for `operator %T' call",
TREE_TYPE (name));
return error_mark_node;
case INDIRECT_REF:
case ADDR_EXPR:
case ARRAY_REF:
break;
case SCOPE_REF:
my_friendly_assert (cname == 0, 255);
cname = TREE_OPERAND (tmp, 0);
tmp = TREE_OPERAND (tmp, 1);
break;
default:
my_friendly_abort (77);
}
last = tmp;
tmp = TREE_OPERAND (tmp, 0);
}
last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0)));
name = build_typename_overload (last);
TREE_TYPE (name) = last;
if (of && TREE_CODE (of) == TYPE_DECL)
{
if (cname == NULL_TREE)
{
cname = DECL_NAME (of);
of = NULL_TREE;
}
else my_friendly_assert (cname == DECL_NAME (of), 256);
}
if (of)
{
tree this_this;
if (current_class_decl == NULL_TREE)
{
cp_error ("object required for `operator %T' call",
TREE_TYPE (name));
return error_mark_node;
}
this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
return build_component_ref (this_this, name, NULL_TREE, protect);
}
else if (cname)
return build_offset_ref (cname, name);
else if (current_class_name)
return build_offset_ref (current_class_name, name);
cp_error ("object required for `operator %T' member reference",
TREE_TYPE (name));
return error_mark_node;
}
#endif
static char * static char *
thunk_printable_name (decl) thunk_printable_name (decl)
tree decl; tree decl;
...@@ -1863,6 +1728,7 @@ emit_thunk (thunk_fndecl) ...@@ -1863,6 +1728,7 @@ emit_thunk (thunk_fndecl)
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
int tem; int tem;
int failure = 0; int failure = 0;
int save_ofp;
/* Used to remember which regs we need to emit a USE rtx for. */ /* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER]; rtx need_use[FIRST_PSEUDO_REGISTER];
...@@ -1892,6 +1758,8 @@ emit_thunk (thunk_fndecl) ...@@ -1892,6 +1758,8 @@ emit_thunk (thunk_fndecl)
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname); assemble_end_function (thunk_fndecl, fnname);
#else #else
save_ofp = flag_omit_frame_pointer;
flag_omit_frame_pointer = 1;
init_function_start (thunk_fndecl, input_filename, lineno); init_function_start (thunk_fndecl, input_filename, lineno);
pushlevel (0); pushlevel (0);
expand_start_bindings (1); expand_start_bindings (1);
...@@ -2063,13 +1931,12 @@ emit_thunk (thunk_fndecl) ...@@ -2063,13 +1931,12 @@ emit_thunk (thunk_fndecl)
final (insns, asm_out_file, optimize, 0); final (insns, asm_out_file, optimize, 0);
assemble_end_function (thunk_fndecl, fnname); assemble_end_function (thunk_fndecl, fnname);
exit_rest_of_compilation:
reload_completed = 0; reload_completed = 0;
/* Cancel the effect of rtl_in_current_obstack. */ /* Cancel the effect of rtl_in_current_obstack. */
permanent_allocation (1); permanent_allocation (1);
flag_omit_frame_pointer = save_ofp;
#endif /* ASM_OUTPUT_MI_THUNK */ #endif /* ASM_OUTPUT_MI_THUNK */
decl_printable_name = save_decl_printable_name; decl_printable_name = save_decl_printable_name;
...@@ -2112,7 +1979,7 @@ do_build_copy_constructor (fndecl) ...@@ -2112,7 +1979,7 @@ do_build_copy_constructor (fndecl)
if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
{ {
t = build (INIT_EXPR, void_type_node, C_C_D, parm); t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t); cplus_expand_expr_stmt (t);
} }
...@@ -2202,7 +2069,7 @@ do_build_assign_ref (fndecl) ...@@ -2202,7 +2069,7 @@ do_build_assign_ref (fndecl)
if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
{ {
tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm); tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t); cplus_expand_expr_stmt (t);
} }
...@@ -2253,13 +2120,13 @@ do_build_assign_ref (fndecl) ...@@ -2253,13 +2120,13 @@ do_build_assign_ref (fndecl)
else else
continue; continue;
comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field); comp = build (COMPONENT_REF, TREE_TYPE (field), current_class_ref, field);
init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); init = build (COMPONENT_REF, TREE_TYPE (field), parm, field);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
} }
} }
c_expand_return (C_C_D); c_expand_return (current_class_ref);
pop_momentary (); pop_momentary ();
} }
......
...@@ -782,22 +782,22 @@ member_init: '(' nonnull_exprlist ')' ...@@ -782,22 +782,22 @@ member_init: '(' nonnull_exprlist ')'
{ {
if (current_class_name && !flag_traditional) if (current_class_name && !flag_traditional)
pedwarn ("anachronistic old style base class initializer"); pedwarn ("anachronistic old style base class initializer");
expand_member_init (C_C_D, NULL_TREE, $2); expand_member_init (current_class_ref, NULL_TREE, $2);
} }
| LEFT_RIGHT | LEFT_RIGHT
{ {
if (current_class_name && !flag_traditional) if (current_class_name && !flag_traditional)
pedwarn ("anachronistic old style base class initializer"); pedwarn ("anachronistic old style base class initializer");
expand_member_init (C_C_D, NULL_TREE, void_type_node); expand_member_init (current_class_ref, NULL_TREE, void_type_node);
} }
| notype_identifier '(' nonnull_exprlist ')' | notype_identifier '(' nonnull_exprlist ')'
{ expand_member_init (C_C_D, $1, $3); } { expand_member_init (current_class_ref, $1, $3); }
| notype_identifier LEFT_RIGHT | notype_identifier LEFT_RIGHT
{ expand_member_init (C_C_D, $1, void_type_node); } { expand_member_init (current_class_ref, $1, void_type_node); }
| complete_type_name '(' nonnull_exprlist ')' | complete_type_name '(' nonnull_exprlist ')'
{ expand_member_init (C_C_D, $1, $3); } { expand_member_init (current_class_ref, $1, $3); }
| complete_type_name LEFT_RIGHT | complete_type_name LEFT_RIGHT
{ expand_member_init (C_C_D, $1, void_type_node); } { expand_member_init (current_class_ref, $1, void_type_node); }
/* GNU extension */ /* GNU extension */
| notype_qualified_id '(' nonnull_exprlist ')' | notype_qualified_id '(' nonnull_exprlist ')'
{ {
...@@ -1046,12 +1046,7 @@ nonnull_exprlist: ...@@ -1046,12 +1046,7 @@ nonnull_exprlist:
unary_expr: unary_expr:
primary %prec UNARY primary %prec UNARY
{ { $$ = $1; }
#if 0
if (TREE_CODE ($$) == TYPE_EXPR)
$$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);
#endif
}
/* __extension__ turns off -pedantic for following primary. */ /* __extension__ turns off -pedantic for following primary. */
| EXTENSION | EXTENSION
{ $<itype>1 = pedantic; { $<itype>1 = pedantic;
...@@ -1362,14 +1357,14 @@ primary: ...@@ -1362,14 +1357,14 @@ primary:
} }
| primary '(' nonnull_exprlist ')' | primary '(' nonnull_exprlist ')'
{ {
$$ = build_x_function_call ($1, $3, current_class_decl); $$ = build_x_function_call ($1, $3, current_class_ref);
if (TREE_CODE ($$) == CALL_EXPR if (TREE_CODE ($$) == CALL_EXPR
&& TREE_TYPE ($$) != void_type_node) && TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$); $$ = require_complete_type ($$);
} }
| primary LEFT_RIGHT | primary LEFT_RIGHT
{ {
$$ = build_x_function_call ($$, NULL_TREE, current_class_decl); $$ = build_x_function_call ($$, NULL_TREE, current_class_ref);
if (TREE_CODE ($$) == CALL_EXPR if (TREE_CODE ($$) == CALL_EXPR
&& TREE_TYPE ($$) != void_type_node) && TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$); $$ = require_complete_type ($$);
...@@ -1391,12 +1386,12 @@ primary: ...@@ -1391,12 +1386,12 @@ primary:
$$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
/* C++ extensions */ /* C++ extensions */
| THIS | THIS
{ if (current_class_decl) { if (current_class_ptr)
{ {
#ifdef WARNING_ABOUT_CCD #ifdef WARNING_ABOUT_CCD
TREE_USED (current_class_decl) = 1; TREE_USED (current_class_ptr) = 1;
#endif #endif
$$ = current_class_decl; $$ = current_class_ptr;
} }
else if (current_function_decl else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl)) && DECL_STATIC_FUNCTION_P (current_function_decl))
...@@ -1516,13 +1511,13 @@ primary: ...@@ -1516,13 +1511,13 @@ primary:
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done build_x_function_call cannot always undo what is done
in build_component_ref entirely yet, we cannot do this. */ in build_component_ref entirely yet, we cannot do this. */
$$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, $$); $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, current_class_ref);
if (TREE_CODE ($$) == CALL_EXPR if (TREE_CODE ($$) == CALL_EXPR
&& TREE_TYPE ($$) != void_type_node) && TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$); $$ = require_complete_type ($$);
#else #else
$$ = build_method_call ($$, $2, $4, NULL_TREE, $$ = build_method_call ($$, $2, $4, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR)); LOOKUP_NORMAL);
#endif #endif
} }
| object unqualified_id LEFT_RIGHT | object unqualified_id LEFT_RIGHT
...@@ -1531,13 +1526,13 @@ primary: ...@@ -1531,13 +1526,13 @@ primary:
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done build_x_function_call cannot always undo what is done
in build_component_ref entirely yet, we cannot do this. */ in build_component_ref entirely yet, we cannot do this. */
$$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, $$); $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, current_class_ref);
if (TREE_CODE ($$) == CALL_EXPR if (TREE_CODE ($$) == CALL_EXPR
&& TREE_TYPE ($$) != void_type_node) && TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$); $$ = require_complete_type ($$);
#else #else
$$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE, $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR)); LOOKUP_NORMAL);
#endif #endif
} }
| object overqualified_id '(' nonnull_exprlist ')' | object overqualified_id '(' nonnull_exprlist ')'
...@@ -1546,7 +1541,7 @@ primary: ...@@ -1546,7 +1541,7 @@ primary:
{ {
warning ("signature name in scope resolution ignored"); warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE, $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR)); LOOKUP_NORMAL);
} }
else else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4); $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
...@@ -1557,7 +1552,7 @@ primary: ...@@ -1557,7 +1552,7 @@ primary:
{ {
warning ("signature name in scope resolution ignored"); warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE, $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR)); LOOKUP_NORMAL);
} }
else else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE); $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
...@@ -1605,9 +1600,9 @@ primary_no_id: ...@@ -1605,9 +1600,9 @@ primary_no_id:
pedwarn ("ANSI C++ forbids braced-groups within expressions"); pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); } $$ = expand_end_stmt_expr ($<ttype>2); }
| primary_no_id '(' nonnull_exprlist ')' | primary_no_id '(' nonnull_exprlist ')'
{ $$ = build_x_function_call ($$, $3, current_class_decl); } { $$ = build_x_function_call ($$, $3, current_class_ref); }
| primary_no_id LEFT_RIGHT | primary_no_id LEFT_RIGHT
{ $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); } { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); }
| primary_no_id '[' expr ']' | primary_no_id '[' expr ']'
{ goto do_array; } { goto do_array; }
| primary_no_id PLUSPLUS | primary_no_id PLUSPLUS
......
...@@ -2581,6 +2581,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2581,6 +2581,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 0; return 0;
case POINTER_TYPE: case POINTER_TYPE:
if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
return unify (tparms, targs, ntparms, parm,
TYPE_PTRMEMFUNC_FN_TYPE (arg), nsubsts);
if (TREE_CODE (arg) != POINTER_TYPE) if (TREE_CODE (arg) != POINTER_TYPE)
return 1; return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
......
...@@ -769,7 +769,7 @@ lookup_field_1 (type, name) ...@@ -769,7 +769,7 @@ lookup_field_1 (type, name)
itself inside a class, we need decls to go into the fn's decls (our itself inside a class, we need decls to go into the fn's decls (our
second case below). But if we're in a class and the class itself is second case below). But if we're in a class and the class itself is
inside a function, we need decls to go into the decls for the class. To inside a function, we need decls to go into the decls for the class. To
achieve this last goal, we must see if, when both current_class_decl and achieve this last goal, we must see if, when both current_class_ptr and
current_function_decl are set, the class was declared inside that current_function_decl are set, the class was declared inside that
function. If so, we know to put the decls into the class's scope. */ function. If so, we know to put the decls into the class's scope. */
......
...@@ -573,7 +573,7 @@ build_signature_table_constructor (sig_ty, rhs) ...@@ -573,7 +573,7 @@ build_signature_table_constructor (sig_ty, rhs)
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = integer_zero_node; delta = integer_zero_node;
index = integer_zero_node; index = integer_zero_node;
pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); pfn = build_addr_func (rhs_method);
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1; TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node; TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1; TREE_ADDRESSABLE (rhs_method) = 1;
...@@ -584,8 +584,12 @@ build_signature_table_constructor (sig_ty, rhs) ...@@ -584,8 +584,12 @@ build_signature_table_constructor (sig_ty, rhs)
/* virtual member function */ /* virtual member function */
tag = integer_one_node; tag = integer_one_node;
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), if (flag_vtable_thunks)
rhstype, 1)); delta = BINFO_OFFSET
(get_binfo (DECL_CONTEXT (rhs_method), rhstype, 1));
else
delta = BINFO_OFFSET
(get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1));
index = DECL_VINDEX (rhs_method); index = DECL_VINDEX (rhs_method);
vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method), vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
rhstype, 0)); rhstype, 0));
...@@ -598,7 +602,7 @@ build_signature_table_constructor (sig_ty, rhs) ...@@ -598,7 +602,7 @@ build_signature_table_constructor (sig_ty, rhs)
delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
rhstype, 1)); rhstype, 1));
index = integer_zero_node; index = integer_zero_node;
pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); pfn = build_addr_func (rhs_method);
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1; TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node; TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1; TREE_ADDRESSABLE (rhs_method) = 1;
...@@ -985,10 +989,7 @@ build_signature_method_call (basetype, instance, function, parms) ...@@ -985,10 +989,7 @@ build_signature_method_call (basetype, instance, function, parms)
TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
if (flag_vtable_thunks) virtual_call = build_function_call (vfn, new_parms);
virtual_call = build_function_call (vfn, parms);
else
virtual_call = build_function_call (vfn, new_parms);
} }
/* Undo the cast, make `this' a signature pointer again. */ /* Undo the cast, make `this' a signature pointer again. */
......
...@@ -48,7 +48,7 @@ real_lvalue_p (ref) ...@@ -48,7 +48,7 @@ real_lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1; return 1;
if (ref == current_class_decl && flag_this_is_variable <= 0) if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0; return 0;
switch (TREE_CODE (ref)) switch (TREE_CODE (ref))
...@@ -118,7 +118,7 @@ lvalue_p (ref) ...@@ -118,7 +118,7 @@ lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1; return 1;
if (ref == current_class_decl && flag_this_is_variable <= 0) if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0; return 0;
switch (TREE_CODE (ref)) switch (TREE_CODE (ref))
......
...@@ -1341,7 +1341,7 @@ build_m_component_ref (datum, component) ...@@ -1341,7 +1341,7 @@ build_m_component_ref (datum, component)
{ {
component = build_indirect_ref (component, NULL_PTR); component = build_indirect_ref (component, NULL_PTR);
type = TREE_TYPE (component); type = TREE_TYPE (component);
rettype = TREE_TYPE (TREE_TYPE (component)); rettype = TREE_TYPE (type);
} }
if (datum == error_mark_node || component == error_mark_node) if (datum == error_mark_node || component == error_mark_node)
......
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