diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-05-16 18:43:00 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-05-16 18:43:00 +0000 |
commit | 4ac14744830df0e672c6b0fbf57823f3b95c0be4 (patch) | |
tree | 1fd63b75624ee907f78b23f718f4b44ac276eec5 | |
parent | 62cb090122381c4e7a3058c88a5a5ef192c08e7c (diff) | |
download | gcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.zip gcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.tar.gz gcc-4ac14744830df0e672c6b0fbf57823f3b95c0be4.tar.bz2 |
86th Cygnus<->FSF quick merge
From-SVN: r11974
-rw-r--r-- | gcc/cp/ChangeLog | 76 | ||||
-rw-r--r-- | gcc/cp/call.c | 138 | ||||
-rw-r--r-- | gcc/cp/class.c | 14 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 12 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 180 | ||||
-rw-r--r-- | gcc/cp/decl.c | 57 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 13 | ||||
-rw-r--r-- | gcc/cp/error.c | 5 | ||||
-rw-r--r-- | gcc/cp/init.c | 64 | ||||
-rw-r--r-- | gcc/cp/method.c | 155 | ||||
-rw-r--r-- | gcc/cp/parse.y | 45 | ||||
-rw-r--r-- | gcc/cp/pt.c | 4 | ||||
-rw-r--r-- | gcc/cp/search.c | 2 | ||||
-rw-r--r-- | gcc/cp/sig.c | 17 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 159 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
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) |