aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMike Stump <mrs@gcc.gnu.org>1996-05-16 18:43:00 +0000
committerMike Stump <mrs@gcc.gnu.org>1996-05-16 18:43:00 +0000
commit4ac14744830df0e672c6b0fbf57823f3b95c0be4 (patch)
tree1fd63b75624ee907f78b23f718f4b44ac276eec5 /gcc
parent62cb090122381c4e7a3058c88a5a5ef192c08e7c (diff)
downloadgcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.zip
gcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.tar.gz
gcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.tar.bz2
86th Cygnus<->FSF quick merge
From-SVN: r11974
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog76
-rw-r--r--gcc/cp/call.c138
-rw-r--r--gcc/cp/class.c14
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/cvt.c180
-rw-r--r--gcc/cp/decl.c57
-rw-r--r--gcc/cp/decl2.c13
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/init.c64
-rw-r--r--gcc/cp/method.c155
-rw-r--r--gcc/cp/parse.y45
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/cp/search.c2
-rw-r--r--gcc/cp/sig.c17
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/cp/typeck.c159
-rw-r--r--gcc/cp/typeck2.c2
17 files changed, 535 insertions, 412 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ee57c7e..4b4c2b8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
(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>
* cp-tree.h (build_overload_call_maybe): Removed.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a50c588..f51d09b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -506,12 +506,6 @@ convert_harshness (type, parmtype, parm)
if (TREE_CODE (ttl) != VOID_TYPE
&& (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)
return EVIL_RETURN (h);
}
@@ -526,22 +520,18 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h);
#endif
- if (penalty == 10 || ttr == ttl)
+ if (ttr == ttl)
{
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- /* If one was unsigned but the other wasn't, then we need to
- do a standard conversion from T to unsigned T. */
- if (penalty == 10)
- h.code = PROMO_CODE; /* was STD_CODE */
- else
- h.code = 0;
-
+ h.code = 0;
/* Note conversion from `T*' to `const T*',
or `T*' to `volatile T*'. */
- if (ttl == ttr
- && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (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.distance = 0;
@@ -580,8 +570,11 @@ convert_harshness (type, parmtype, parm)
if (ttl != ttr)
{
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (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;
}
return h;
@@ -1192,7 +1185,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{
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
with `operator()()' overloaded. */
@@ -1208,7 +1201,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{
/* If it's a field, try overloading operator (),
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)
return error_mark_node;
@@ -1221,7 +1214,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
return build_function_call (instance, parms);
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;
@@ -1527,6 +1520,71 @@ print_n_candidates (candidates, n)
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)
or object.method (args). This can also build
calls to constructors, and find friends.
@@ -1739,11 +1797,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
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
- C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
- basetype = TREE_TYPE (C_C_D);
+ current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
+ basetype = TREE_TYPE (current_class_ref);
/* Anything manifestly `this' in constructors and destructors
has a known type, so virtual function tables are not needed. */
@@ -1765,8 +1823,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
else
{
- instance = C_C_D;
- instance_ptr = current_class_decl;
+ instance = current_class_ref;
+ instance_ptr = current_class_ptr;
basetype_path = TYPE_BINFO (current_class_type);
}
result = build_field_call (basetype_path, instance_ptr, name, parms);
@@ -1940,9 +1998,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
t = TREE_TYPE (TREE_VALUE (parm));
}
- if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
- && TREE_CODE (t) == METHOD_TYPE)
+ if (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);
}
#if 0
@@ -2365,7 +2423,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
type (if it exists) is a pointer to. */
if (DECL_ABSTRACT_VIRTUAL_P (function)
- && instance == C_C_D
+ && instance == current_class_ref
&& DECL_CONSTRUCTOR_P (current_function_decl)
&& ! (flags & LOOKUP_NONVIRTUAL)
&& value_member (function, get_abstract_virtuals (basetype)))
@@ -2422,7 +2480,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
/* Let's be nasty to the user now, and give reasonable
error messages. */
- instance_ptr = current_class_decl;
+ instance_ptr = current_class_ptr;
if (instance_ptr)
{
if (basetype != current_class_type)
@@ -2540,21 +2598,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
- {
- int is_constructor
- = TREE_CODE (function) == FUNCTION_DECL
- && 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;
- }
+ result = build_call (function, value_type, parms);
+ result = convert_from_reference (result);
+ return result;
}
/* Similar to `build_method_call', but for overloaded non-member functions.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4f1f23a..4c6cf3e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -72,7 +72,9 @@ struct class_level
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 */
tree current_class_name; /* IDENTIFIER_NODE: name of current class */
@@ -434,7 +436,7 @@ build_vtbl_ref (instance, idx)
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (instance == C_C_D)
+ if (instance == current_class_ref)
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
NULL_PTR);
else
@@ -4494,7 +4496,7 @@ resolves_to_fixed_type_p (instance, nonnull)
}
else if (nonnull)
{
- if (instance == current_class_decl
+ if (instance == current_class_ptr
&& flag_this_is_variable <= 0)
{
/* Some people still use `this = 0' inside destructors. */
@@ -4941,12 +4943,6 @@ instantiate_type (lhstype, rhs, complain)
tree elem, baselink, name;
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
functions or member functions. May have to undo what
`default_conversion' might do to lhstype. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d6db7a0..cb850e0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1002,7 +1002,7 @@ struct lang_decl
/* Nonzero for FUNCTION_DECL means that this constructor is known to
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. */
#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;
of CURRENT_FUNCTION_DECL due to overloading */
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 */
extern tree global_base_init_list;
@@ -1820,8 +1821,6 @@ extern int at_eof;
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 */
extern tree current_class_name; /* IDENTIFIER_NODE: name of 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 */
LOOKUP_COMPLAIN mean complain if no suitable member function
matching the arguments is found.
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_GLOBAL means search through the space of overloaded 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 */
#define LOOKUP_PROTECT (1)
#define LOOKUP_COMPLAIN (2)
#define LOOKUP_NORMAL (3)
-#define LOOKUP_AGGR (4)
+/* #define LOOKUP_UNUSED (4) */
#define LOOKUP_NONVIRTUAL (8)
#define LOOKUP_GLOBAL (16)
#define LOOKUP_HAS_IN_CHARGE (32)
@@ -1941,6 +1939,8 @@ extern int get_arglist_len_in_bytes PROTO((tree));
extern tree build_vfield_ref PROTO((tree, tree));
extern tree find_scoped_type PROTO((tree, 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_method_call PROTO((tree, tree, tree, tree, int));
extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int));
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 5c09175..972939e 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -82,6 +82,7 @@ static tree
convert_fn_ptr (type, expr)
tree type, expr;
{
+#if 0 /* We don't use thunks for pmfs. */
if (flag_vtable_thunks)
{
tree intype = TREE_TYPE (expr);
@@ -104,6 +105,7 @@ convert_fn_ptr (type, expr)
return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
}
else
+#endif
return build_ptrmemfunc (type, expr, 1);
}
@@ -477,7 +479,7 @@ build_up_reference (type, arg, flags, checkconst)
case PARM_DECL:
#if 0
- if (targ == current_class_decl)
+ if (targ == current_class_ptr)
{
error ("address of `this' not available");
/* #if 0 */
@@ -1056,14 +1058,11 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE;
fntype = TREE_TYPE (function);
- function = default_conversion (function);
-
- result = build_nt (CALL_EXPR, function,
- convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- parmlist, NULL_TREE, LOOKUP_NORMAL),
- NULL_TREE);
- TREE_TYPE (result) = TREE_TYPE (fntype);
- TREE_SIDE_EFFECTS (result) = 1;
+
+ parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ parmlist, NULL_TREE, LOOKUP_NORMAL);
+
+ result = build_call (function, TREE_TYPE (fntype), parmlist);
return result;
}
@@ -1809,3 +1808,166 @@ type_promotes_to (type)
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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 83ed195..73b5709 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3275,7 +3275,7 @@ pushdecl (x)
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
- && current_class_decl
+ && current_class_ptr
&& !TREE_STATIC (name))
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
@@ -11075,14 +11075,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
push_nested_class (ctype, 1);
/* 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)
{
/* We know that this was set up by `grokclassfn'.
We do not wait until `store_parm_decls', since evil
parse errors may never get us to that point. Here
we keep the consistency between `current_class_type'
- and `current_class_decl'. */
+ and `current_class_ptr'. */
tree t = current_function_parms;
my_friendly_assert (t != NULL_TREE
@@ -11093,14 +11093,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
int i = suspend_momentary ();
/* Fool build_indirect_ref. */
- current_class_decl = NULL_TREE;
- C_C_D = build_indirect_ref (t, NULL_PTR);
- current_class_decl = t;
+ current_class_ptr = NULL_TREE;
+ current_class_ref = build_indirect_ref (t, NULL_PTR);
+ current_class_ptr = t;
resume_momentary (i);
}
else
/* 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)
push_nested_class (DECL_CONTEXT (decl1), 2);
else
push_memoized_context (0, 1);
- current_class_decl = C_C_D = NULL_TREE;
+ current_class_ptr = current_class_ref = NULL_TREE;
}
pushlevel (0);
@@ -11502,7 +11502,7 @@ finish_function (lineno, call_poplevel, nested)
if (current_function_assigns_this)
cond = build (NE_EXPR, boolean_type_node,
- current_class_decl, integer_zero_node);
+ current_class_ptr, integer_zero_node);
else
{
int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
@@ -11541,10 +11541,10 @@ finish_function (lineno, call_poplevel, nested)
/* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (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);
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);
/* If we did not assign to this, then `this' is non-zero at
@@ -11576,7 +11576,7 @@ finish_function (lineno, call_poplevel, nested)
{
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)),
ptr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
@@ -11605,11 +11605,11 @@ finish_function (lineno, call_poplevel, nested)
error_mark_node),
NULL_PTR),
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)),
NULL_TREE, LOOKUP_NORMAL);
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);
else
exprstmt = NULL_TREE;
@@ -11646,16 +11646,16 @@ finish_function (lineno, call_poplevel, nested)
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
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))
- 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)
{
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);
}
@@ -11691,7 +11691,7 @@ finish_function (lineno, call_poplevel, nested)
expand_end_bindings (decls, decls != NULL_TREE, 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 (
DECL_RESULT (current_function_decl))) != void_type_node
@@ -11715,8 +11715,8 @@ finish_function (lineno, call_poplevel, nested)
if (flag_this_is_variable > 0)
{
cond = build_binary_op (EQ_EXPR,
- current_class_decl, integer_zero_node, 1);
- thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
+ current_class_ptr, integer_zero_node, 1);
+ thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
}
@@ -11769,7 +11769,7 @@ finish_function (lineno, call_poplevel, nested)
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_just_assigned_this = 0;
@@ -11974,7 +11974,8 @@ finish_function (lineno, call_poplevel, nested)
}
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.
@@ -12412,8 +12413,8 @@ struct cp_function
tree base_init_list;
tree member_init_list;
tree base_init_expr;
- tree class_decl;
- tree C_C_D;
+ tree current_class_ptr;
+ tree current_class_ref;
rtx result_rtx;
struct cp_function *next;
struct binding_level *binding_level;
@@ -12459,8 +12460,8 @@ push_cp_function_context (context)
p->temp_name_counter = temp_name_counter;
p->base_init_list = current_base_init_list;
p->member_init_list = current_member_init_list;
- p->class_decl = current_class_decl;
- p->C_C_D = C_C_D;
+ p->current_class_ptr = current_class_ptr;
+ p->current_class_ref = current_class_ref;
p->eh_context = push_eh_context ();
}
@@ -12502,8 +12503,8 @@ pop_cp_function_context (context)
temp_name_counter = p->temp_name_counter;
current_base_init_list = p->base_init_list;
current_member_init_list = p->member_init_list;
- current_class_decl = p->class_decl;
- C_C_D = p->C_C_D;
+ current_class_ptr = p->current_class_ptr;
+ current_class_ref = p->current_class_ref;
pop_eh_context (p->eh_context);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2ca80b5..18fb1af 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -155,9 +155,13 @@ int warn_implicit = 1;
int warn_ctor_dtor_privacy = 1;
/* 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;
+#endif
/* True if we want to deal with repository information. */
@@ -3336,7 +3340,7 @@ reparse_absdcl_as_expr (type, decl)
/* recurse */
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)
decl = require_complete_type (decl);
@@ -3357,7 +3361,8 @@ reparse_absdcl_as_casts (decl, expr)
{
tree type;
- if (TREE_CODE (expr) == CONSTRUCTOR)
+ if (TREE_CODE (expr) == CONSTRUCTOR
+ && TREE_TYPE (expr) == 0)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
@@ -3556,7 +3561,7 @@ build_expr_from_tree (t)
name = build_expr_from_tree (name);
return build_x_function_call
(name, build_expr_from_tree (TREE_OPERAND (t, 1)),
- current_class_decl);
+ current_class_ref);
}
case COND_EXPR:
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 652ed3f..1f66155 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1259,8 +1259,9 @@ dump_expr (t, nop)
dump_expr (TREE_OPERAND (t, 1), 0);
else
{
- sorry ("operand of OFFSET_REF not understood");
- goto error;
+ dump_expr (TREE_OPERAND (t, 0), 0);
+ OB_PUTS (" .* ");
+ dump_expr (TREE_OPERAND (t, 1), 0);
}
break;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 45dc9c2..5695c98 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -174,7 +174,7 @@ perform_member_init (member, name, init, explicit, protect_list)
if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
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
&& TREE_CODE (type) == ARRAY_TYPE
@@ -220,7 +220,7 @@ perform_member_init (member, name, init, explicit, protect_list)
current_member_init_list. */
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));
}
}
@@ -237,7 +237,7 @@ perform_member_init (member, name, init, explicit, protect_list)
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,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
@@ -487,7 +487,7 @@ build_partial_cleanup_for (binfo)
tree 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),
expr,
@@ -561,7 +561,7 @@ emit_base_init (t, immediately)
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
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);
expand_end_cond ();
}
@@ -596,7 +596,7 @@ emit_base_init (t, immediately)
push_temp_slots ();
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,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
@@ -626,11 +626,11 @@ emit_base_init (t, immediately)
/* Initialize all the virtual function table fields that
do come from virtual base classes. */
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
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))
{
@@ -863,7 +863,7 @@ do_member_init (s_id, name, init)
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);
}
@@ -1139,8 +1139,9 @@ expand_member_init (exp, name, init)
explaining that such initializations are invalid.
ALIAS_THIS is nonzero iff we are initializing something which is
- essentially an alias for C_C_D. In this case, the base constructor
- may move it on us, and we must keep track of such deviations.
+ essentially an alias for current_class_ref. In this case, the base
+ 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
something of the type we are looking for, then we know
@@ -1160,8 +1161,7 @@ expand_member_init (exp, name, init)
initialization.
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
expand_aggr_init (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. */
if ((flag_this_is_variable & 1) && alias_this)
{
- TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
- expand_assignment (current_class_decl, rval, 0, 0);
+ TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
+ expand_assignment (current_class_ptr, rval, 0, 0);
}
else
expand_expr_stmt (rval);
@@ -1676,7 +1676,7 @@ build_member_call (type, name, parmlist)
tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
{
- return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_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)
basetype_path = TYPE_BINFO (type);
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;
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
}
else
{
- tree olddecl = current_class_decl;
+ tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
{
@@ -1846,10 +1846,10 @@ build_offset_ref (type, name)
basebinfo = TYPE_BINFO (type);
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);
else
- decl = C_C_D;
+ decl = current_class_ref;
if (constructor_name (BINFO_TYPE (basebinfo)) == name)
if (dtor)
@@ -1978,7 +1978,12 @@ resolve_offset_ref (exp)
if (TREE_CODE (exp) == TREE_LIST)
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);
if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
@@ -1988,12 +1993,7 @@ resolve_offset_ref (exp)
}
member = exp;
type = TREE_TYPE (type);
- base = C_C_D;
- }
- else
- {
- member = TREE_OPERAND (exp, 1);
- base = TREE_OPERAND (exp, 0);
+ base = current_class_ref;
}
if ((TREE_CODE (member) == VAR_DECL
@@ -2008,7 +2008,7 @@ resolve_offset_ref (exp)
/* Syntax error can cause a member which should
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)
{
@@ -2022,7 +2022,7 @@ resolve_offset_ref (exp)
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
- && (base == C_C_D
+ && (base == current_class_ref
|| (TREE_CODE (base) == NOP_EXPR
&& TREE_OPERAND (base, 0) == error_mark_node)))
{
@@ -2033,7 +2033,7 @@ resolve_offset_ref (exp)
else
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)
{
@@ -3555,8 +3555,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
addr = convert_force (build_pointer_type (type), addr, 0);
if (TREE_CODE (addr) == NOP_EXPR
- && TREE_OPERAND (addr, 0) == current_class_decl)
- ref = C_C_D;
+ && TREE_OPERAND (addr, 0) == current_class_ptr)
+ ref = current_class_ref;
else
ref = build_indirect_ref (addr, NULL_PTR);
ptr = 0;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 5d16db6..79761e9 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1549,19 +1549,19 @@ hack_identifier (value, name)
type = TREE_TYPE (value);
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",
IDENTIFIER_POINTER (DECL_NAME (value)));
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
this field was initialized by a base initializer,
we can emit an error message. */
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))
{
@@ -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 *
thunk_printable_name (decl)
tree decl;
@@ -1863,6 +1728,7 @@ emit_thunk (thunk_fndecl)
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
int tem;
int failure = 0;
+ int save_ofp;
/* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER];
@@ -1892,6 +1758,8 @@ emit_thunk (thunk_fndecl)
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname);
#else
+ save_ofp = flag_omit_frame_pointer;
+ flag_omit_frame_pointer = 1;
init_function_start (thunk_fndecl, input_filename, lineno);
pushlevel (0);
expand_start_bindings (1);
@@ -2063,13 +1931,12 @@ emit_thunk (thunk_fndecl)
final (insns, asm_out_file, optimize, 0);
assemble_end_function (thunk_fndecl, fnname);
- exit_rest_of_compilation:
-
reload_completed = 0;
/* Cancel the effect of rtl_in_current_obstack. */
permanent_allocation (1);
+ flag_omit_frame_pointer = save_ofp;
#endif /* ASM_OUTPUT_MI_THUNK */
decl_printable_name = save_decl_printable_name;
@@ -2112,7 +1979,7 @@ do_build_copy_constructor (fndecl)
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;
cplus_expand_expr_stmt (t);
}
@@ -2202,7 +2069,7 @@ do_build_assign_ref (fndecl)
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;
cplus_expand_expr_stmt (t);
}
@@ -2253,13 +2120,13 @@ do_build_assign_ref (fndecl)
else
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);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
}
}
- c_expand_return (C_C_D);
+ c_expand_return (current_class_ref);
pop_momentary ();
}
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index bd44fd4..adda622 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -782,22 +782,22 @@ member_init: '(' nonnull_exprlist ')'
{
if (current_class_name && !flag_traditional)
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
{
if (current_class_name && !flag_traditional)
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 ')'
- { expand_member_init (C_C_D, $1, $3); }
+ { expand_member_init (current_class_ref, $1, $3); }
| 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 ')'
- { expand_member_init (C_C_D, $1, $3); }
+ { expand_member_init (current_class_ref, $1, $3); }
| 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 */
| notype_qualified_id '(' nonnull_exprlist ')'
{
@@ -1046,12 +1046,7 @@ nonnull_exprlist:
unary_expr:
primary %prec UNARY
- {
-#if 0
- if (TREE_CODE ($$) == TYPE_EXPR)
- $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);
-#endif
- }
+ { $$ = $1; }
/* __extension__ turns off -pedantic for following primary. */
| EXTENSION
{ $<itype>1 = pedantic;
@@ -1362,14 +1357,14 @@ primary:
}
| 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
&& TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$);
}
| 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
&& TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$);
@@ -1391,12 +1386,12 @@ primary:
$$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
/* C++ extensions */
| THIS
- { if (current_class_decl)
+ { if (current_class_ptr)
{
#ifdef WARNING_ABOUT_CCD
- TREE_USED (current_class_decl) = 1;
+ TREE_USED (current_class_ptr) = 1;
#endif
- $$ = current_class_decl;
+ $$ = current_class_ptr;
}
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
@@ -1516,13 +1511,13 @@ primary:
/* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done
in build_component_ref entirely yet, we cannot do this. */
- $$ = 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
&& TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$);
#else
$$ = build_method_call ($$, $2, $4, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
#endif
}
| object unqualified_id LEFT_RIGHT
@@ -1531,13 +1526,13 @@ primary:
/* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done
in build_component_ref entirely yet, we cannot do this. */
- $$ = 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
&& TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$);
#else
$$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
#endif
}
| object overqualified_id '(' nonnull_exprlist ')'
@@ -1546,7 +1541,7 @@ primary:
{
warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
}
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
@@ -1557,7 +1552,7 @@ primary:
{
warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
}
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
@@ -1605,9 +1600,9 @@ primary_no_id:
pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); }
| 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
- { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); }
+ { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); }
| primary_no_id '[' expr ']'
{ goto do_array; }
| primary_no_id PLUSPLUS
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 47a37c8..0addffd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2581,6 +2581,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 0;
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)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index d7db46b..2a852cd 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -769,7 +769,7 @@ lookup_field_1 (type, name)
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
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
function. If so, we know to put the decls into the class's scope. */
diff --git a/gcc/cp/sig.c b/gcc/cp/sig.c
index 00f257e..701b3be 100644
--- a/gcc/cp/sig.c
+++ b/gcc/cp/sig.c
@@ -573,7 +573,7 @@ build_signature_table_constructor (sig_ty, rhs)
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = 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_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
@@ -584,8 +584,12 @@ build_signature_table_constructor (sig_ty, rhs)
/* virtual member function */
tag = integer_one_node;
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
- delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
- rhstype, 1));
+ if (flag_vtable_thunks)
+ 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);
vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
rhstype, 0));
@@ -598,7 +602,7 @@ build_signature_table_constructor (sig_ty, rhs)
delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
rhstype, 1));
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_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
@@ -985,10 +989,7 @@ build_signature_method_call (basetype, instance, function, parms)
TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
- if (flag_vtable_thunks)
- virtual_call = build_function_call (vfn, parms);
- else
- virtual_call = build_function_call (vfn, new_parms);
+ virtual_call = build_function_call (vfn, new_parms);
}
/* Undo the cast, make `this' a signature pointer again. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7a8ef46..3684a2a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -48,7 +48,7 @@ real_lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
@@ -118,7 +118,7 @@ lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 88ce4db..507150c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -100,13 +100,13 @@ require_complete_type (value)
not been laid out. Try to avoid an error by interpreting
it as this->X::Y, if reasonable. */
if (TREE_CODE (value) == OFFSET_REF
- && C_C_D != 0
- && TREE_OPERAND (value, 0) == C_C_D)
+ && current_class_ref != 0
+ && TREE_OPERAND (value, 0) == current_class_ref)
{
tree base, member = TREE_OPERAND (value, 1);
tree basetype = TYPE_OFFSET_BASETYPE (type);
my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
- base = convert_pointer_to (basetype, current_class_decl);
+ base = convert_pointer_to (basetype, current_class_ptr);
value = build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (base, NULL_PTR), member);
return require_complete_type (value);
@@ -1470,14 +1470,7 @@ decay_conversion (exp)
}
if (code == METHOD_TYPE)
{
- if (TREE_CODE (exp) == OFFSET_REF)
- {
- /* FIXME: We should emit an error here about using a ptrmemfunc
- for something other than a function call. */
- my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL,
- 308);
- return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- }
+ cp_pedwarn ("assuming & on `%E'", exp);
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
@@ -1628,7 +1621,7 @@ build_object_ref (datum, basetype, field)
}
/* Like `build_component_ref, but uses an already found field.
- Must compute access for C_C_D. Otherwise, ok. */
+ Must compute access for current_class_ref. Otherwise, ok. */
tree
build_component_ref_1 (datum, field, protect)
tree datum, field;
@@ -1667,7 +1660,7 @@ build_component_ref_1 (datum, field, protect)
if (TREE_STATIC (field))
return field;
- if (datum == C_C_D)
+ if (datum == current_class_ref)
{
tree access = compute_access (TYPE_BINFO (current_class_type), field);
@@ -2020,8 +2013,8 @@ build_indirect_ref (ptr, errorstring)
ptr : default_conversion (ptr));
register tree type = TREE_TYPE (pointer);
- if (ptr == current_class_decl)
- return C_C_D;
+ if (ptr == current_class_ptr)
+ return current_class_ref;
if (IS_AGGR_TYPE (type))
{
@@ -2226,8 +2219,9 @@ build_array_ref (array, idx)
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
- TREE_VALUE of each node is a parameter-expression.
- FUNCTION's data type may be a function type or a pointer-to-function.
+ TREE_VALUE of each node is a parameter-expression. The PARAMS do
+ not include any object pointer that may be required. FUNCTION's
+ data type may be a function type or a pointer-to-function.
For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
is the list of possible methods that FUNCTION could conceivably
@@ -2242,7 +2236,7 @@ build_array_ref (array, idx)
In the second case, TREE_PURPOSE (function) is the function's
name directly.
- DECL is the class instance variable, usually CURRENT_CLASS_DECL.
+ DECL is the class instance variable, usually CURRENT_CLASS_REF.
When calling a TEMPLATE_DECL, we don't require a complete return
type. */
@@ -2392,7 +2386,7 @@ build_x_function_call (function, params, decl)
if (TREE_OPERAND (function, 0))
decl = TREE_OPERAND (function, 0);
else
- decl = C_C_D;
+ decl = current_class_ref;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
function = get_member_function_from_ptrfunc (&decl_addr,
@@ -2594,25 +2588,25 @@ build_function_call_real (function, params, require_complete, flags)
function = inline_conversion (function);
}
else
- function = default_conversion (function);
+ function = build_addr_func (function);
}
else
{
fndecl = NULL_TREE;
- /* Convert anything with function type to a pointer-to-function. */
- if (function == error_mark_node)
- return error_mark_node;
- function = default_conversion (function);
+ function = build_addr_func (function);
}
+ if (function == error_mark_node)
+ return error_mark_node;
+
fntype = TREE_TYPE (function);
if (TYPE_PTRMEMFUNC_P (fntype))
{
- tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
- function = get_member_function_from_ptrfunc (&instance_ptr, function);
+ cp_error ("must use .* or ->* to call pointer-to-member function in `%E (...)'",
+ function);
+ return error_mark_node;
}
is_method = (TREE_CODE (fntype) == POINTER_TYPE
@@ -2670,17 +2664,15 @@ build_function_call_real (function, params, require_complete, flags)
/* C++ */
value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
{
- register tree result =
- build (CALL_EXPR, value_type,
- function, coerced_params, NULL_TREE);
-
- TREE_SIDE_EFFECTS (result) = 1;
+ register tree result
+ = build_call (function, value_type, coerced_params);
- if (! require_complete)
- return convert_from_reference (result);
- if (value_type == void_type_node)
- return result;
- result = require_complete_type (result);
+ if (require_complete)
+ {
+ if (value_type == void_type_node)
+ return result;
+ result = require_complete_type (result);
+ }
return convert_from_reference (result);
}
}
@@ -4282,10 +4274,10 @@ build_unary_op (code, xarg, noconvert)
/* Let &* cancel out to simplify resulting code. */
if (TREE_CODE (arg) == INDIRECT_REF)
{
- /* We don't need to have `current_class_decl' wrapped in a
+ /* We don't need to have `current_class_ptr' wrapped in a
NON_LVALUE_EXPR node. */
- if (arg == C_C_D)
- return current_class_decl;
+ if (arg == current_class_ref)
+ return current_class_ptr;
/* Keep `default_conversion' from converting if
ARG is of REFERENCE_TYPE. */
@@ -4402,6 +4394,14 @@ build_unary_op (code, xarg, noconvert)
function counts as a constant */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
+
+ if (TREE_CODE (argtype) == POINTER_TYPE &&
+ TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+ {
+ build_ptrmemfunc_type (argtype);
+ addr = build_ptrmemfunc (argtype, addr, 0);
+ }
+
return addr;
}
}
@@ -4542,31 +4542,6 @@ unary_complex_lvalue (code, arg)
}
-#if 0
- /* This seems to be obsolete now (and posssibly wrong, compare with
- resolve_offset_ref). */
- if (TREE_CODE (arg) == OFFSET_REF)
- {
- tree left = TREE_OPERAND (arg, 0), left_addr;
- tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0);
-
- if (left == 0)
- if (current_class_decl)
- left_addr = current_class_decl;
- else
- {
- error ("no `this' for pointer to member");
- return error_mark_node;
- }
- else
- left_addr = build_unary_op (ADDR_EXPR, left, 0);
-
- return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)),
- build1 (NOP_EXPR, integer_type_node, left_addr),
- build1 (NOP_EXPR, integer_type_node, right_addr));
- }
-#endif
-
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
{
@@ -4597,7 +4572,7 @@ unary_complex_lvalue (code, arg)
address of it; it should not be allocated in a register.
Value is 1 if successful.
- C++: we do not allow `current_class_decl' to be addressable. */
+ C++: we do not allow `current_class_ptr' to be addressable. */
int
mark_addressable (exp)
@@ -4618,7 +4593,7 @@ mark_addressable (exp)
break;
case PARM_DECL:
- if (x == current_class_decl)
+ if (x == current_class_ptr)
{
error ("address of `this' not available");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
@@ -5702,7 +5677,7 @@ build_modify_expr (lhs, modifycode, rhs)
}
/* check to see if there is an assignment to `this' */
- if (lhs == current_class_decl)
+ if (lhs == current_class_ptr)
{
if (flag_this_is_variable > 0
&& DECL_NAME (current_function_decl) != NULL_TREE
@@ -5976,11 +5951,16 @@ get_delta_difference (from, to, force)
}
if (TREE_VIA_VIRTUAL (binfo))
{
+ binfo = binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (from));
warning ("pointer to member conversion to virtual base class will only work if you are very careful");
}
+ delta = BINFO_OFFSET (binfo);
+ delta = convert (ptrdiff_type_node, delta);
+
return build_binary_op (MINUS_EXPR,
integer_zero_node,
- BINFO_OFFSET (binfo), 1);
+ delta, 1);
}
if (TREE_VIA_VIRTUAL (binfo))
{
@@ -6099,8 +6079,7 @@ build_ptrmemfunc (type, pfn, force)
pfn = instantiate_type (type, pfn, 1);
if (pfn == error_mark_node)
return error_mark_node;
- if (TREE_CODE (pfn) != ADDR_EXPR)
- pfn = build_unary_op (ADDR_EXPR, pfn, 0);
+ pfn = build_addr_func (pfn);
}
/* Allow pointer to member conversions here. */
@@ -6109,6 +6088,14 @@ build_ptrmemfunc (type, pfn, force)
force);
delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
+#if 0
+ /* We need to check the argument types to see if they are compatible
+ (any const or volatile violations. */
+ something like this:
+ comptype (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (type))),
+ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))), ?);
+#endif
+
if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
warning ("assuming pointer to member function is non-virtual");
@@ -6414,12 +6401,12 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
some type instantiation if that resolves the
ambiguity of (X Y::*) and (X *). */
- if (current_class_decl)
+ if (current_class_ptr)
{
if (TREE_CODE (rhs) == INTEGER_CST)
{
rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
- current_class_decl, rhs);
+ current_class_ptr, rhs);
return convert_for_assignment (type, rhs,
errtype, fndecl, parmnum);
}
@@ -6522,24 +6509,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
cp_warning ("\t`%T' != `%T'", type, rhstype);
}
}
- else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (119);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
- else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (120);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
else
{
if (fndecl)
@@ -6931,7 +6900,7 @@ c_expand_return (retval)
}
if (DECL_CONSTRUCTOR_P (current_function_decl))
- retval = current_class_decl;
+ retval = current_class_ptr;
else if (DECL_NAME (result) != NULL_TREE
&& TREE_CODE (valtype) != VOID_TYPE)
retval = result;
@@ -6956,10 +6925,10 @@ c_expand_return (retval)
}
}
else if (DECL_CONSTRUCTOR_P (current_function_decl)
- && retval != current_class_decl)
+ && retval != current_class_ptr)
{
error ("return from a constructor: use `this = ...' instead");
- retval = current_class_decl;
+ retval = current_class_ptr;
}
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
@@ -7164,7 +7133,7 @@ c_expand_return (retval)
}
else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
{
- /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */
+ /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */
expand_goto (ctor_label);
}
else if (retval)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 602a092..14802dc 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1341,7 +1341,7 @@ build_m_component_ref (datum, component)
{
component = build_indirect_ref (component, NULL_PTR);
type = TREE_TYPE (component);
- rettype = TREE_TYPE (TREE_TYPE (component));
+ rettype = TREE_TYPE (type);
}
if (datum == error_mark_node || component == error_mark_node)