From 28cbf42c14d84ef906619aa7c180a72c6acea2fb Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 23 Mar 1995 00:44:31 +0000 Subject: [PATCH] 59th Cygnus<->FSF merge From-SVN: r9225 --- gcc/cp/ChangeLog | 185 +++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/Makefile.in | 1 + gcc/cp/call.c | 2 +- gcc/cp/class.c | 56 ++++---------- gcc/cp/cp-tree.h | 2 +- gcc/cp/cvt.c | 12 +++ gcc/cp/decl.c | 115 +++++++++++++++++++--------- gcc/cp/decl2.c | 119 ++++++++++++++++++----------- gcc/cp/error.c | 7 ++ gcc/cp/expr.c | 83 +++++++++++++++++++- gcc/cp/init.c | 6 +- gcc/cp/lex.c | 10 ++- gcc/cp/method.c | 17 ++++- gcc/cp/parse.y | 8 +- gcc/cp/pt.c | 26 ++++++- gcc/cp/tree.c | 2 + gcc/cp/typeck.c | 159 ++++++++++++++++++++++++-------------- 17 files changed, 619 insertions(+), 191 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index aa13e96d206..331e139e1fe 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,188 @@ +Wed Mar 22 15:10:34 1995 Mike Stump + + * decl2.c (finish_prevtable_vardecl, finish_vtable_vardecl): Revert + Brendan's last change and fix latent problem that causes TD entries + to not come out when the things that need them has yet to be + expanded. + +Wed Mar 22 15:12:00 1995 Jason Merrill + + * typeck.c (build_binary_op_nodefault, comparison ops): Update type0 + and type1, since we might have changed op0 or op1. + +Wed Mar 22 13:33:45 1995 Jason Merrill + + * typeck.c (common_type): Don't mess up templates. + +Wed Mar 22 04:56:00 1995 Jason Merrill + + * typeck.c (common_type): Handle ptms properly. Also handle + T* -> void*. + (build_binary_op_nodefault): New variable build_type controls what + type is given to the expression when it is created. Set this to + boolean_type_node for comparison ops instead of using result_type. + (comp_target_types): Allow T * -> void *. + + * cvt.c (cp_convert_to_pointer): Do access control when converting + ptms, too. + +Tue Mar 21 17:25:06 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * parse.y (extern_lang_string): Catch use of linkage specs that + aren't all naming the same language. + + * class.c (finish_struct): Delete accidental duplicate code. + +Tue Mar 21 14:00:57 1995 Jason Merrill + + * typeck.c (build_binary_op_nodefault): Disable pedwarns about + comparing functions and incomplete types. + + * decl.c (finish_function): Only unset current_function_decl if + !nested. + (duplicate_decls): Last change went too far; we only want to stop + checking for value/reference ambiguity. + +Tue Mar 21 01:26:39 1995 Mike Stump + + * gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it + out fresh, as the new type may be larger. + +Mon Mar 20 19:01:10 1995 Jason Merrill + + * expr.c (extract_init): Try to expand the RTL for the + initialization and figure out what it will look like so we can avoid + run-time initialization. Disabled for now. + (extract_scalar_init): Helper for scalar initialization. + (extract_aggr_init): Helper for aggregate initialization. + + * decl.c (duplicate_decls): Don't complain about ambiguous + declarations. + (obscure_complex_init): Now returns a tree. Call extract_init if + we're optimizing and this is a toplevel decl. + (finish_decl): Update accordingly. + + * lex.c (check_newline): If we're just changing files (not pushing + or popping), update input_file_stack->name. + +Mon Mar 20 17:55:04 1995 Mike Stump + + * pt.c (type_unification): Only TEMPLATE_DECLs are handled right now + in the transitive unification code. + +Mon Mar 20 16:07:50 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * decl.c (shadow_tag): Don't allow inline, virtual, or explicit on + non-functions. + (grokdeclarator): Don't allow friends to be defined in local classes. + +Sat Mar 18 04:03:33 1995 Jason Merrill + + * decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC + rather than DECL_SAVED_INSNS to decide whether or not this method + was declared inline. + + * method.c (synthesize_method): Turn off DECL_INLINE if + function_cannot_inline_p thinks we're too large. + + * typeck.c (build_indirect_ref): Use build_expr_type_conversion. + +Fri Mar 17 17:47:36 1995 Jason Merrill + + * class.c (instantiate_type): Handle pmfs. + + * typeck.c (convert_for_assignment): Check types when assigning one + pmf to another. + + * decl.c (define_label): Fix logic for printing out the name of the + label in an error message. + + * error.c (dump_expr): Support ARRAY_REF. + +Fri Mar 17 17:43:02 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * decl2.c (finish_vtable_vardecl): Call build_t_desc here. + (finish_prevtable_vardecl): Instead of here. + +Fri Mar 17 14:40:45 1995 Jason Merrill + + * decl.c (expand_static_init): Also use expand_aggr_init if the + initializer is a TREE_LIST. + (grokdeclarator): Only pedwarn about extra qualification if -pedantic. + + * pt.c (unify): Fix unification of return type. + + * expr.c (fixup_result_decl): Use store_expr, rather than + emit_move_insn, to move the return value into the place where + callers will expect it. + +Thu Mar 16 22:05:25 1995 Jason Merrill + + * init.c (build_offset_ref): Call assmble_external on functions. + * typeck.c (build_component_ref): Ditto. + +Thu Mar 16 20:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * decl.c (struct saved_scope): Add members base_init_list and + member_init_list. + (push_to_top_level): Save current_base_init_list and + current_member_init_list to them. + (pop_from_top_level): Put it back. + +Thu Mar 16 19:21:14 1995 Jason Merrill + + * pt.c (instantiate_template): Call assemble_external. + +Thu Mar 16 18:07:54 1995 Brendan Kehoe (brendan@phydeaux.cygnus.com) + + * class.c: Include rtl.h, to get NULL_RTX. + (finish_struct): Also zero out DECL_SAVED_INSNS, to avoid problems + on hosts with different sizes for each part of the union. + * tree.c: Also include rtl.h. + (layout_basetypes): Same change for DECL_SAVED_INSNS. + +Thu Mar 16 13:57:36 1995 Jason Merrill + + * pt.c (unify): Fix array domain unification for 64-bit targets. + + * decl2.c (finish_file): Push bizarre type decl before walking the + vtables the first time. + (walk_vtables): OK, don't set prev to vars if the vardecl_fn messed + with TREE_CHAIN (prev). + + * init.c (emit_base_init): Use convert_pointer_to_real instead of + convert_pointer_to when converting to a direct base. + +Wed Mar 15 20:26:29 1995 Mike Stump + + * pt.c (type_unification): Handle transitive unification better. + +Wed Mar 15 13:56:16 1995 Jason Merrill + + * decl2.c (walk_vtables): Always set prev to vars. + (mark_vtable_entries): Call assemble_external on the vtable entries. + + * class.c (finish_struct): Set the vtable's size to NULL_TREE before + calling layout_decl, so that it gets updated properly. + + Finally re-enable dynamic synthesis. This time it works. + * method.c (synthesize_method): Pass decl_function_context (fndecl) + to {push,pop}_cp_function_context. + * decl.c (push_cp_function_context): Now takes a tree argument. + (pop_cp_function_context): Ditto. + * call.c (build_method_call): Enable synthesis. + * lex.c (cons_up_default_function): Ditto. + +Tue Mar 14 19:14:19 1995 Doug Evans + + * parse.y (setattrs): Chain onto prefix_attributes rather than + setting it. + +Wed Mar 15 13:00:00 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * decl.c (pushdecl): Check if the type of the VAR_DECL is an + error_mark_node before trying to read TYPE_LANG_SPECIFIC. + Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com) * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold, diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index dd267f37841..6007f00d042 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -167,6 +167,7 @@ OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o compiler: ../cc1plus ../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS) + rm -f $@ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1plus \ $(CXX_OBJS) $(OBJS) $(LIBS) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3079d147734..9ba6d1894e7 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2379,7 +2379,7 @@ build_method_call (instance, name, parms, basetype_path, flags) /* Declare external function if necessary. */ assemble_external (function); -#if 0 +#if 1 /* Is it a synthesized method that needs to be synthesized? */ if (DECL_ARTIFICIAL (function) && ! flag_no_inline && DECL_SAVED_INSNS (function) == 0 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f296dc9b421..d6e23156dc6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "cp-tree.h" #include "flags.h" +#include "rtl.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -2963,6 +2964,11 @@ finish_struct (t, list_of_fieldlists, warn_anon) DECL_CLASS_CONTEXT (x) = t; + /* Do both of these, even though they're in the same union; + if the insn `r' member and the size `i' member are + different sizes, as on the alpha, the larger of the two + will end up with garbage in it. */ + DECL_SAVED_INSNS (x) = NULL_RTX; DECL_FIELD_SIZE (x) = 0; /* The name of the field is the original field name @@ -3027,6 +3033,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) fields = x; last_x = x; + DECL_SAVED_INSNS (x) = NULL_RTX; DECL_FIELD_SIZE (x) = 0; /* When this goes into scope, it will be a non-local reference. */ @@ -3505,6 +3512,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) DECL_FIELD_CONTEXT (vfield) = t; DECL_CLASS_CONTEXT (vfield) = t; DECL_FCONTEXT (vfield) = t; + DECL_SAVED_INSNS (vfield) = NULL_RTX; DECL_FIELD_SIZE (vfield) = 0; DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); if (CLASSTYPE_RTTI (t)) @@ -3576,47 +3584,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_ALIGN (t) = round_up_size; /* Pass layout information about base classes to layout_type, if any. */ - - { - tree field; - for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) - { - if (TREE_STATIC (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL) - continue; - - /* If this field is an anonymous union, - give each union-member the same position as the union has. - - ??? This is a real kludge because it makes the structure - of the types look strange. This feature is only used by - C++, which should have build_component_ref build two - COMPONENT_REF operations, one for the union and one for - the inner field. We set the offset of this field to zero - so that either the old or the correct method will work. - Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are - moved into the type of this field, but nothing seems to break - by doing this. */ - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree uelt = TYPE_FIELDS (TREE_TYPE (field)); - for (; uelt; uelt = TREE_CHAIN (uelt)) - { - if (TREE_CODE (uelt) != FIELD_DECL) - continue; - - DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); - DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); - } - - DECL_FIELD_BITPOS (field) = integer_zero_node; - } - } - } - if (n_baseclasses) { tree pseudo_basetype = TREE_TYPE (base_layout_decl); @@ -3911,6 +3878,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype) { TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype; + DECL_SIZE (TYPE_BINFO_VTABLE (t)) = 0; layout_decl (TYPE_BINFO_VTABLE (t), 0); /* At one time the vtable info was grabbed 2 words at a time. This fails on sparc unless you have 8-byte alignment. (tiemann) */ @@ -4726,6 +4694,9 @@ instantiate_type (lhstype, rhs, complain) functions or member functions. May have to undo what `default_conversion' might do to lhstype. */ + if (TYPE_PTRMEMFUNC_P (lhstype)) + lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype); + if (TREE_CODE (lhstype) == POINTER_TYPE) if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) @@ -4884,8 +4855,7 @@ instantiate_type (lhstype, rhs, complain) #endif } if (complain) - error ("no compatible member functions named `%s'", - IDENTIFIER_POINTER (name)); + cp_error ("no compatible member functions named `%D'", name); return error_mark_node; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 528c23a03d6..98ea89f09f1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1,5 +1,5 @@ /* Definitions for C++ parsing and type checking. - Copyright (C) 1987, 1993, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index e87b168a233..7e880b44b99 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -155,6 +155,18 @@ cp_convert_to_pointer (type, expr) && TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE) return convert_fn_ptr (type, expr); + if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE + && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE) + { + tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); + tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); + tree binfo = get_binfo (b1, b2, 1); + if (binfo == NULL_TREE) + binfo = get_binfo (b2, b1, 1); + if (binfo == error_mark_node) + return error_mark_node; + } + return build1 (NOP_EXPR, type, expr); } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1ef0ebd8f19..c9865e30de7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1443,6 +1443,7 @@ struct saved_scope { tree old_bindings; struct saved_scope *prev; tree class_name, class_type, class_decl, function_decl; + tree base_init_list, member_init_list; struct binding_level *class_bindings; tree previous_class_type; tree *lang_base, *lang_stack, lang_name; @@ -1519,6 +1520,8 @@ push_to_top_level () s->class_type = current_class_type; s->class_decl = current_class_decl; s->function_decl = current_function_decl; + s->base_init_list = current_base_init_list; + s->member_init_list = current_member_init_list; s->class_bindings = class_binding_level; s->previous_class_type = previous_class_type; s->lang_stack = current_lang_stack; @@ -1571,6 +1574,8 @@ pop_from_top_level () C_C_D = CLASSTYPE_INST_VAR (current_class_type); else C_C_D = NULL_TREE; + current_base_init_list = s->base_init_list; + current_member_init_list = s->member_init_list; current_function_decl = s->function_decl; class_binding_level = s->class_bindings; previous_class_type = s->previous_class_type; @@ -2230,7 +2235,7 @@ duplicate_decls (newdecl, olddecl) cp_error_at ("previous declaration `%#D' here", olddecl); } else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), - TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2)) + TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3)) { cp_error ("new declaration `%#D'", newdecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl); @@ -3061,6 +3066,7 @@ pushdecl (x) /* Keep count of variables in this level with incomplete type. */ /* RTTI TD entries are created while defining the type_info. */ if (TREE_CODE (x) == VAR_DECL + && TREE_TYPE (x) != error_mark_node && TYPE_LANG_SPECIFIC (TREE_TYPE (x)) && TYPE_BEING_DEFINED (TREE_TYPE (x))) { @@ -3606,6 +3612,7 @@ define_label (filename, line, name) else { tree uses, prev; + int identified = 0; /* Mark label as having been defined. */ DECL_INITIAL (decl) = error_mark_node; @@ -3636,10 +3643,11 @@ define_label (filename, line, name) && DECL_INITIAL (new_decls) != error_mark_node) || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))) { - if (IDENTIFIER_ERROR_LOCUS (decl) == NULL_TREE) - cp_error ("invalid jump to label `%D'", decl); - SET_IDENTIFIER_ERROR_LOCUS (decl, current_function_decl); - cp_error ("crosses initialization of `%D'", new_decls); + if (! identified) + cp_error ("jump to label `%D'", decl); + identified = 1; + cp_error_at (" crosses initialization of `%#D'", + new_decls); } new_decls = TREE_CHAIN (new_decls); } @@ -5259,7 +5267,10 @@ shadow_tag (declspecs) else if (value == ridpointers[(int) RID_STATIC] || value == ridpointers[(int) RID_EXTERN] || value == ridpointers[(int) RID_AUTO] - || value == ridpointers[(int) RID_REGISTER]) + || value == ridpointers[(int) RID_REGISTER] + || value == ridpointers[(int) RID_INLINE] + || value == ridpointers[(int) RID_VIRTUAL] + || value == ridpointers[(int) RID_EXPLICIT]) ob_modifier = value; } @@ -5290,9 +5301,19 @@ shadow_tag (declspecs) { /* Anonymous unions are objects, that's why we only check for inappropriate specifiers in this branch. */ + if (ob_modifier) - cp_error ("`%D' can only be specified for objects and functions", - ob_modifier); + { + if (ob_modifier == ridpointers[(int) RID_INLINE] + || ob_modifier == ridpointers[(int) RID_VIRTUAL]) + cp_error ("`%D' can only be specified for functions", ob_modifier); + else if (ob_modifier == ridpointers[(int) RID_EXPLICIT]) + cp_error ("`%D' can only be specified for constructors", + ob_modifier); + else + cp_error ("`%D' can only be specified for objects and functions", + ob_modifier); + } if (found_tag == 0) pedwarn ("abstract declarator used as declaration"); @@ -5837,16 +5858,24 @@ grok_reference_init (decl, type, init, cleanupp) it in with a dummy CONSTRUCTOR to force the variable into .data; otherwise we can use error_mark_node. */ -static void -obscure_complex_init (decl) - tree decl; +static tree +obscure_complex_init (decl, init) + tree decl, init; { + if (! flag_no_inline && TREE_STATIC (decl)) + { + if (extract_init (decl, init)) + return NULL_TREE; + } + if (current_binding_level == global_binding_level && ! DECL_COMMON (decl)) DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, NULL_TREE); else DECL_INITIAL (decl) = error_mark_node; + + return init; } /* Finish processing of a declaration; @@ -6078,22 +6107,18 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags) } } #endif - - /* We must hide the initializer so that expand_decl - won't try to do something it does not understand. */ - obscure_complex_init (decl); } else { dont_use_constructor: if (TREE_CODE (init) != TREE_VEC) init = store_init_value (decl, init); - - /* Don't let anyone try to initialize this variable - until we are ready to do so. */ - if (init) - obscure_complex_init (decl); } + + if (init) + /* We must hide the initializer so that expand_decl + won't try to do something it does not understand. */ + init = obscure_complex_init (decl, init); } else if (DECL_EXTERNAL (decl)) ; @@ -6120,7 +6145,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags) if (TYPE_SIZE (type) != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (type)) - obscure_complex_init (decl); + init = obscure_complex_init (decl, NULL_TREE); } else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (type) != REFERENCE_TYPE @@ -6589,7 +6614,8 @@ expand_static_init (decl, init) integer_zero_node, 1), 0); old_cleanups = cleanups_this_call; expand_assignment (temp, integer_one_node, 0, 0); - if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) + || TREE_CODE (init) == TREE_LIST) { expand_aggr_init (decl, init, 0, 0); do_pending_stack_adjust (); @@ -8372,11 +8398,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) RIDBIT_RESET (RID_FRIEND, specbits); friendp = 0; } + if (decl_context == NORMAL) + error ("friend declaration not in class definition"); + if (current_function_decl && funcdef_flag) + cp_error ("can't define friend function `%s' in a local class definition", + name); } - if (decl_context == NORMAL && friendp) - error ("friend declaration not in class definition"); - /* Traditionally, declaring return type float means double. */ if (flag_traditional @@ -8598,8 +8626,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) basetype :: member . */ if (ctype == current_class_type) - cp_pedwarn ("extra qualification `%T::' on member `%s' ignored", - ctype, name); + { + /* class A { + void A::f (); + }; + + Is this ill-formed? */ + + if (pedantic) + cp_pedwarn ("extra qualification `%T::' on member `%s' ignored", + ctype, name); + } else if (TREE_CODE (type) == FUNCTION_TYPE) { if (current_class_type == NULL_TREE @@ -11307,7 +11344,7 @@ finish_function (lineno, call_poplevel, nested) int ok_to_optimize_dtor = 0; if (current_function_assigns_this) - cond = build (NE_EXPR, integer_type_node, + cond = build (NE_EXPR, boolean_type_node, current_class_decl, integer_zero_node); else { @@ -11756,8 +11793,14 @@ finish_function (lineno, call_poplevel, nested) if (DECL_STATIC_DESTRUCTOR (fndecl)) static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors); - /* Let the error reporting routines know that we're outside a function. */ - current_function_decl = NULL_TREE; + if (! nested) + { + /* Let the error reporting routines know that we're outside a + function. For a nested function, this value is used in + pop_cp_function_context and then reset via pop_function_context. */ + current_function_decl = NULL_TREE; + } + named_label_uses = NULL_TREE; } @@ -12190,13 +12233,13 @@ struct cp_function *cp_function_chain; used during compilation of a C++ function. */ void -push_cp_function_context (toplev) - int toplev; +push_cp_function_context (context) + tree context; { struct cp_function *p = (struct cp_function *) xmalloc (sizeof (struct cp_function)); - push_function_context_to (toplev); + push_function_context_to (context); p->next = cp_function_chain; cp_function_chain = p; @@ -12221,8 +12264,8 @@ push_cp_function_context (toplev) /* Restore the variables used during compilation of a C++ function. */ void -pop_cp_function_context (toplev) - int toplev; +pop_cp_function_context (context) + tree context; { struct cp_function *p = cp_function_chain; tree link; @@ -12244,7 +12287,7 @@ pop_cp_function_context (toplev) } #endif - pop_function_context_from (toplev); + pop_function_context_from (context); cp_function_chain = p->next; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 6cc04204cd9..633fc8b7e21 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1932,7 +1932,8 @@ build_push_scope (cname, name) return rval; } -void cplus_decl_attributes (decl, attributes, prefix_attributes) +void +cplus_decl_attributes (decl, attributes, prefix_attributes) tree decl, attributes, prefix_attributes; { if (decl && decl != void_type_node) @@ -2463,7 +2464,14 @@ mark_vtable_entries (decl) extern tree abort_fndecl; if (flag_vtable_thunks) fnaddr = TREE_VALUE (entries); - TREE_OPERAND (fnaddr, 0) = abort_fndecl; + TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl; + } + if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn)) + { + int save_extern = DECL_EXTERNAL (fn); + DECL_EXTERNAL (fn) = 1; + assemble_external (fn); + DECL_EXTERNAL (fn) = save_extern; } } } @@ -2561,7 +2569,8 @@ finish_prevtable_vardecl (prev, vars) for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; method = DECL_NEXT_METHOD (method)) { - if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method) + if (DECL_VINDEX (method) != NULL_TREE + && !DECL_DECLARED_STATIC (method) && !DECL_ABSTRACT_VIRTUAL_P (method)) { SET_CLASSTYPE_INTERFACE_KNOWN (ctype); @@ -2574,10 +2583,17 @@ finish_prevtable_vardecl (prev, vars) import_export_vtable (vars, ctype, 1); + /* We cannot use TREE_USED here, as it may be set by the expanding of a + ctor that is used to build a global object. The long term plan is to + make the TD entries statically initialized and move this to + finish_vtable_vardecl time. */ if (flag_rtti && write_virtuals >= 0 - && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) + && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars))) { - /* Kick out the type descriptor before writing out the vtable. */ + /* Kick out the type descriptor before we dump out global + initializers, as they are initialized at run time and + we have to find them when we scan for things that need initialized + at the top level. */ build_t_desc (ctype, 1); } } @@ -2589,6 +2605,15 @@ finish_vtable_vardecl (prev, vars) if (write_virtuals >= 0 && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) { +#if 0 + /* The long term plan it to make the TD entries statically initialized, + have the entries built and emitted here. When that happens, this + can be enabled, and the other call to build_t_desc removed. */ + /* Kick out the type descriptor before writing out the vtable. */ + if (flag_rtti) + build_t_desc (DECL_CONTEXT (vars), 1); +#endif + /* Write it out. */ mark_vtable_entries (vars); if (TREE_TYPE (DECL_INITIAL (vars)) == 0) @@ -2651,19 +2676,22 @@ walk_vtables (typedecl_fn, vardecl_fn) { register tree type = TREE_TYPE (vars); - if (TREE_CODE (vars) == TYPE_DECL - && type != error_mark_node - && TYPE_LANG_SPECIFIC (type) - && CLASSTYPE_VSIZE (type)) + if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) + { + if (vardecl_fn) (*vardecl_fn) (prev, vars); + + if (prev && TREE_CHAIN (prev) != vars) + continue; + } + else if (TREE_CODE (vars) == TYPE_DECL + && type != error_mark_node + && TYPE_LANG_SPECIFIC (type) + && CLASSTYPE_VSIZE (type)) { if (typedecl_fn) (*typedecl_fn) (prev, vars); } - else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) - { - if (vardecl_fn) (*vardecl_fn) (prev, vars); - } - else - prev = vars; + + prev = vars; } } @@ -2805,6 +2833,31 @@ finish_file () interface_unknown = 1; interface_only = 0; +#if 1 + /* The reason for pushing garbage onto the global_binding_level is to + ensure that we can slice out _DECLs which pertain to virtual function + tables. If the last thing pushed onto the global_binding_level was a + virtual function table, then slicing it out would slice away all the + decls (i.e., we lose the head of the chain). + + There are several ways of getting the same effect, from changing the + way that iterators over the chain treat the elements that pertain to + virtual function tables, moving the implementation of this code to + decl.c (where we can manipulate global_binding_level directly), + popping the garbage after pushing it and slicing away the vtable + stuff, or just leaving it alone. */ + + /* Make last thing in global scope not be a virtual function table. */ +#if 0 /* not yet, should get fixed properly later */ + vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node); +#else + vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node); +#endif + DECL_IGNORED_P (vars) = 1; + SET_DECL_ARTIFICIAL (vars); + pushdecl (vars); +#endif + /* Walk to mark the inline functions we need, then output them so that we can pick up any other tdecls that those routines need. */ walk_vtables ((void (*)())0, finish_prevtable_vardecl); @@ -3023,37 +3076,12 @@ finish_file () start_time = get_run_time (); - /* Now delete from the chain of variables all virtual function tables. - We output them all ourselves, because each will be treated specially. */ - -#if 1 - /* The reason for pushing garbage onto the global_binding_level is to - ensure that we can slice out _DECLs which pertain to virtual function - tables. If the last thing pushed onto the global_binding_level was a - virtual function table, then slicing it out would slice away all the - decls (i.e., we lose the head of the chain). - - There are several ways of getting the same effect, from changing the - way that iterators over the chain treat the elements that pertain to - virtual function tables, moving the implementation of this code to - decl.c (where we can manipulate global_binding_level directly), - popping the garbage after pushing it and slicing away the vtable - stuff, or just leaving it alone. */ - - /* Make last thing in global scope not be a virtual function table. */ -#if 0 /* not yet, should get fixed properly later */ - vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node); -#else - vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node); -#endif - DECL_IGNORED_P (vars) = 1; - SET_DECL_ARTIFICIAL (vars); - pushdecl (vars); -#endif - if (flag_handle_signatures) walk_sigtables ((void (*)())0, finish_sigtable_vardecl); + for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname)) + import_export_inline (TREE_VALUE (fnname)); + /* Now write out inline functions which had their addresses taken and which were not declared virtual and which were not declared `extern inline'. */ @@ -3089,7 +3117,7 @@ finish_file () TREE_CHAIN (last) = TREE_CHAIN (place); continue; } - import_export_inline (decl); + if (TREE_PUBLIC (decl) || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) || flag_keep_inline_functions) @@ -3112,6 +3140,9 @@ finish_file () } } + /* Now delete from the chain of variables all virtual function tables. + We output them all ourselves, because each will be treated specially. */ + walk_vtables ((void (*)())0, prune_vtable_vardecl); for (vars = getdecls (); vars; vars = TREE_CHAIN (vars)) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 215dd179240..d7bbff8d284 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1142,6 +1142,13 @@ dump_expr (t, nop) } break; + case ARRAY_REF: + dump_expr (TREE_OPERAND (t, 0), 0); + OB_PUTC ('['); + dump_expr (TREE_OPERAND (t, 1), 0); + OB_PUTC (']'); + break; + case CONVERT_EXPR: dump_unary_op ("+", t, nop); break; diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index a7dc3d8051a..338065b00a9 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -264,7 +264,7 @@ fixup_result_decl (decl, result) REG_FUNCTION_VALUE_P (real_decl_result) = 1; result = real_decl_result; } - emit_move_insn (result, DECL_RTL (decl)); + store_expr (decl, result, 0); emit_insn (gen_rtx (USE, VOIDmode, result)); } } @@ -274,9 +274,90 @@ fixup_result_decl (decl, result) in some cases. We cannot use `memory_operand' as a test here because on most RISC machines, a variable's address is not, by itself, a legitimate address. */ + int decl_in_memory_p (decl) tree decl; { return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM; } + +/* Expand this initialization inline and see if it's simple enough that + it can be done at compile-time. */ + +static tree +extract_aggr_init (decl, init) + tree decl, init; +{ + return 0; +} + +static tree +extract_scalar_init (decl, init) + tree decl, init; +{ + rtx value, insns, insn; + extern struct obstack temporary_obstack; + tree t = NULL_TREE; + + push_obstacks (&temporary_obstack, &temporary_obstack); + start_sequence (); + value = expand_expr (init, NULL_RTX, VOIDmode, 0); + insns = get_insns (); + end_sequence (); + reg_scan (insns, max_reg_num (), 0); + jump_optimize (insns, 0, 0, 1); + pop_obstacks (); + + for (insn = insns; insn; insn = NEXT_INSN (insn)) + { + rtx r, to; + + if (GET_CODE (insn) == NOTE) + continue; + else if (GET_CODE (insn) != INSN) + return 0; + + r = PATTERN (insn); + if (GET_CODE (r) != SET) + return 0; + + to = XEXP (r, 0); + + if (! (to == value || + (GET_CODE (to) == SUBREG && XEXP (to, 0) == value))) + return 0; + + r = XEXP (r, 1); + + switch (GET_CODE (r)) + { + case CONST_INT: + t = build_int_2 (XEXP (r, 0), 0); + break; + default: + return 0; + } + } + + return t; +} + +int +extract_init (decl, init) + tree decl, init; +{ + return 0; + + if (IS_AGGR_TYPE (TREE_TYPE (decl)) + || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) + init = extract_aggr_init (decl, init); + else + init = extract_scalar_init (decl, init); + + if (init == NULL_TREE) + return 0; + + DECL_INITIAL (decl) = init; + return 1; +} diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 01c5bcb896a..37376131d8c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -571,7 +571,7 @@ emit_base_init (t, immediately) if (init != void_list_node) { - member = convert_pointer_to (base_binfo, current_class_decl); + member = convert_pointer_to_real (base_binfo, current_class_decl); expand_aggr_init_1 (base_binfo, 0, build_indirect_ref (member, NULL_PTR), init, BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL); @@ -1980,6 +1980,10 @@ build_offset_ref (cname, name) && ((flag_save_memoized_contexts && global_bindings_p ()) || ! allocation_temporary_p ())) fnfields = copy_list (fnfields); + + for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t)) + assemble_external (t); + t = build_tree_list (error_mark_node, fnfields); TREE_TYPE (t) = build_offset_type (type, unknown_type_node); return t; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 6cbc00671b2..895f2694e87 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1796,8 +1796,10 @@ cons_up_default_function (type, full_name, kind) /* When on-the-fly synthesis works properly, remove the second and third conditions here. */ if (flag_keep_inline_functions +#if 0 || ! flag_no_inline || complex +#endif || ! DECL_EXTERNAL (fn)) { struct pending_inline *t; @@ -2812,7 +2814,13 @@ linenum: extract_interface_info (); c = get_last_nonwhite_on_line (); - if (c != EOF) + if (c == EOF) + { + /* Update the name in the top element of input_file_stack. */ + if (input_file_stack) + input_file_stack->name = input_filename; + } + else { put_back (c); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 29b64e69e3d..adbb97e0e50 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2209,12 +2209,12 @@ synthesize_method (fndecl) tree fndecl; { int nested = (current_function_decl != NULL_TREE); - int toplev = (decl_function_context (fndecl) == NULL_TREE); + tree context = decl_function_context (fndecl); char *f = input_filename; tree base = DECL_CLASS_CONTEXT (fndecl); if (nested) - push_cp_function_context (toplev); + push_cp_function_context (context); input_filename = DECL_SOURCE_FILE (fndecl); interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base); @@ -2238,8 +2238,19 @@ synthesize_method (fndecl) } finish_function (lineno, 0, nested); + + /* Do we really *want* to inline this function? */ + if (DECL_INLINE (fndecl)) + { + /* Turn off DECL_INLINE for the moment so function_cannot_inline_p + will check our size. */ + DECL_INLINE (fndecl) = 0; + if (function_cannot_inline_p (fndecl) == 0) + DECL_INLINE (fndecl) = 1; + } + input_filename = f; extract_interface_info (); if (nested) - pop_cp_function_context (toplev); + pop_cp_function_context (context); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d9430eca6cb..d8d7eb8ef2e 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -402,8 +402,12 @@ any_id: ; extern_lang_string: - EXTERN_LANG_STRING + EXTERN_LANG_STRING { push_lang_context ($1); } + | extern_lang_string EXTERN_LANG_STRING + { if (current_lang_name != $2) + cp_error ("use of linkage spec `%D' is different from previous spec `%D'", $2, current_lang_name); + pop_lang_context (); push_lang_context ($2); } ; template_header: @@ -1725,7 +1729,7 @@ object: primary '.' ; setattrs: /* empty */ - { prefix_attributes = $0; } + { prefix_attributes = chainon (prefix_attributes, $0); } ; decl: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5ac3b633b3f..e05265a0785 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1712,6 +1712,8 @@ instantiate_template (tmpl, targ_ptr) if (fndecl == error_mark_node) goto exit; + assemble_external (fndecl); + /* If it's a static member fn in the template, we need to change it into a FUNCTION_TYPE and chop off its this pointer. */ if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE @@ -2059,6 +2061,23 @@ type_unification (tparms, targs, parms, args, nsubsts, subr) if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't') { my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293); + if (TREE_CODE (arg) == TREE_LIST + && TREE_TYPE (arg) == unknown_type_node + && TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL) + { + int nsubsts, ntparms; + tree *targs; + + /* Have to back unify here */ + arg = TREE_VALUE (arg); + nsubsts = 0; + ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg)); + targs = (tree *) alloca (sizeof (tree) * ntparms); + parm = tree_cons (NULL_TREE, parm, NULL_TREE); + return type_unification (DECL_TEMPLATE_PARMS (arg), targs, + TYPE_ARG_TYPES (TREE_TYPE (arg)), + parm, &nsubsts, 0); + } arg = TREE_TYPE (arg); } #endif @@ -2200,6 +2219,8 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) nsubsts); case REFERENCE_TYPE: + if (TREE_CODE (arg) == REFERENCE_TYPE) + arg = TREE_TYPE (arg); return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts); case ARRAY_TYPE: @@ -2242,8 +2263,6 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) tree t1, t2; t1 = TREE_OPERAND (parm, 0); t2 = TREE_OPERAND (parm, 1); - if (TREE_CODE (t1) != TEMPLATE_CONST_PARM) - return 1; return unify (tparms, targs, ntparms, t1, fold (build (PLUS_EXPR, integer_type_node, arg, t2)), nsubsts); @@ -2299,6 +2318,9 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) if (TREE_CODE (arg) != FUNCTION_TYPE) return 1; check_args: + if (unify (tparms, targs, ntparms, TREE_TYPE (parm), + TREE_TYPE (arg), nsubsts)) + return 1; return type_unification (tparms, targs, TYPE_ARG_TYPES (parm), TYPE_ARG_TYPES (arg), nsubsts, 1); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 763d768148c..712a76f7923 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -24,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "tree.h" #include "cp-tree.h" #include "flags.h" +#include "rtl.h" #define CEIL(x,y) (((x) + (y) - 1) / (y)) @@ -826,6 +827,7 @@ layout_basetypes (rec, binfos) DECL_FIELD_CONTEXT (decl) = rec; DECL_CLASS_CONTEXT (decl) = rec; DECL_FCONTEXT (decl) = basetype; + DECL_SAVED_INSNS (decl) = NULL_RTX; DECL_FIELD_SIZE (decl) = 0; DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node); TREE_CHAIN (decl) = vbase_decls; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b7f51d2a3fd..2467882061b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -369,12 +369,24 @@ common_type (t1, t2) But ANSI C++ specifies doing this with the qualifiers. So I turned it on again. */ { - tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), - TYPE_MAIN_VARIANT (TREE_TYPE (t2))); + tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1)); + tree tt2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2)); int constp = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2)); int volatilep = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2)); + tree target; + + if (tt1 == tt2) + target = tt1; + else if ((IS_AGGR_TYPE_CODE (TREE_CODE (tt1)) + || TREE_CODE (tt1) == OFFSET_TYPE + || TREE_CODE (tt1) == METHOD_TYPE) + && TREE_CODE (tt2) == TREE_CODE (tt1)) + target = common_type (tt1, tt2); + else + target = void_type_node; + target = cp_build_type_variant (target, constp, volatilep); if (code1 == POINTER_TYPE) t1 = build_pointer_type (target); @@ -480,17 +492,18 @@ common_type (t1, t2) return build_type_attribute_variant (t1, attributes); case OFFSET_TYPE: - if (TYPE_OFFSET_BASETYPE (t1) == TYPE_OFFSET_BASETYPE (t2) - && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) + if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) { - tree basetype = TYPE_OFFSET_BASETYPE (t1); - t1 = build_offset_type (basetype, - common_type (TREE_TYPE (t1), TREE_TYPE (t2))); - } - else - compiler_error ("common_type called with uncommon member types"); + tree b1 = TYPE_OFFSET_BASETYPE (t1); + tree b2 = TYPE_OFFSET_BASETYPE (t2); + tree base; - /* ... falls through ... */ + if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)) + return build_type_attribute_variant (t1, attributes); + else if (binfo_or_else (b2, b1)) + return build_type_attribute_variant (t2, attributes); + } + compiler_error ("common_type called with uncommon member types"); default: return build_type_attribute_variant (t1, attributes); @@ -762,6 +775,17 @@ comp_target_types (ttl, ttr, nptrs) if (ttl == ttr) return 1; + if (TREE_CODE (ttl) == VOID_TYPE + && TREE_CODE (ttr) != FUNCTION_TYPE + && TREE_CODE (ttr) != METHOD_TYPE + && TREE_CODE (ttr) != OFFSET_TYPE) + return 1; + if (TREE_CODE (ttr) == VOID_TYPE + && TREE_CODE (ttl) != FUNCTION_TYPE + && TREE_CODE (ttl) != METHOD_TYPE + && TREE_CODE (ttl) != OFFSET_TYPE) + return -1; + if (TREE_CODE (ttr) != TREE_CODE (ttl)) return 0; @@ -1680,6 +1704,7 @@ build_component_ref (datum, component, basetype_path, protect) my_friendly_assert (datum != error_mark_node, 310); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); } + assemble_external (fndecl); return fndecl; } if (access == access_protected) @@ -1692,7 +1717,12 @@ build_component_ref (datum, component, basetype_path, protect) { /* Just act like build_offset_ref, since the object does not matter unless we're actually calling the function. */ - tree t = build_tree_list (error_mark_node, fndecls); + tree t; + + for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t)) + assemble_external (t); + + t = build_tree_list (error_mark_node, fndecls); TREE_TYPE (t) = build_offset_type (basetype, unknown_type_node); return t; @@ -1779,6 +1809,13 @@ build_indirect_ref (ptr, errorstring) if (ptr == current_class_decl) return C_C_D; + ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1); + if (ptr) + { + pointer = ptr; + type = TREE_TYPE (pointer); + } + if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE) { if (TREE_CODE (pointer) == ADDR_EXPR @@ -2821,6 +2858,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) Zero means they need to be converted to RESULT_TYPE. */ int converted = 0; + /* Nonzero means create the expression with this type, rather than + RESULT_TYPE. */ + tree build_type = 0; + /* Nonzero means after finally constructing the expression give it this type. Otherwise, give it type RESULT_TYPE. */ tree final_type = 0; @@ -3064,8 +3105,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case EQ_EXPR: case NE_EXPR: - result_type = boolean_type_node; - converted = 1; + build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) short_compare = 1; @@ -3073,33 +3113,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) { register tree tt0 = TYPE_MAIN_VARIANT (TREE_TYPE (type0)); register tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (type1)); - /* Anything compares with void *. void * compares with anything. - Otherwise, the targets must be the same. */ - if (tt0 != tt1 && TREE_CODE (tt0) == RECORD_TYPE - && TREE_CODE (tt1) == RECORD_TYPE) - { - tree base = common_base_type (tt0, tt1); - if (base == NULL_TREE) - cp_pedwarn ("comparison of distinct object pointer types `%T' and `%T'", type0, type1); - else if (base == error_mark_node) - { - cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1); - return error_mark_node; - } - else - { - if (integer_zerop (op0)) - op0 = null_pointer_node; - else - op0 = convert_pointer_to (base, op0); - if (integer_zerop (op1)) - op1 = null_pointer_node; - else - op1 = convert_pointer_to (base, op1); - } - } - else if (comp_target_types (type0, type1, 1)) - ; + + if (comp_target_types (type0, type1, 1)) + result_type = common_type (type0, type1); else if (tt0 == void_type_node) { if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE @@ -3225,10 +3241,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) { return build_binary_op (code, op1, op0, 1); } - else - /* If args are not valid, clear out RESULT_TYPE - to cause an error message later. */ - result_type = 0; + + type0 = TREE_TYPE (op0); + type1 = TREE_TYPE (op1); + if (result_type == NULL_TREE) + result_type = type0; break; case MAX_EXPR: @@ -3239,8 +3256,12 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { if (! comp_target_types (type0, type1, 1)) - cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", - type0, type1); + { + cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", + type0, type1); + result_type = ptr_type_node; + } +#if 0 else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) cp_pedwarn ("comparison of %scomplete and %scomplete pointers", @@ -3250,15 +3271,20 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (pedantic && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); - result_type = common_type (type0, type1); +#endif + else + result_type = common_type (type0, type1); } + + if (result_type == NULL_TREE) + result_type = type0; break; case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR: - result_type = boolean_type_node; + build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) short_compare = 1; @@ -3267,6 +3293,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if (! comp_target_types (type0, type1, 1)) cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", type0, type1); +#if 0 else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) cp_pedwarn ("comparison of %scomplete and %scomplete pointers", @@ -3276,6 +3303,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (pedantic && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); +#endif + else + result_type = common_type (type0, type1); } else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) @@ -3299,9 +3329,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) warning ("comparison between pointer and integer"); op0 = convert (TREE_TYPE (op1), op0); } - else - result_type = 0; - converted = 1; + + type0 = TREE_TYPE (op0); + type1 = TREE_TYPE (op1); + if (result_type == NULL_TREE) + result_type = type0; break; } @@ -3437,7 +3469,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) return convert (boolean_type_node, val); - op0 = xop0, op1 = xop1, result_type = boolean_type_node; + op0 = xop0, op1 = xop1; + converted = 1; resultcode = xresultcode; } @@ -3544,8 +3577,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) op1 = convert (result_type, op1); } + if (build_type == NULL_TREE) + build_type = result_type; + { - register tree result = build (resultcode, result_type, op0, op1); + register tree result = build (resultcode, build_type, op0, op1); register tree folded; folded = fold (result); @@ -6731,11 +6767,22 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) && TREE_CODE (rhstype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (rhstype)) == METHOD_TYPE) || integer_zerop (rhs) - || TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs))) + || TYPE_PTRMEMFUNC_P (rhstype)) && TYPE_PTRMEMFUNC_P (type)) { + tree ttl = TYPE_PTRMEMFUNC_FN_TYPE (type); + tree ttr = (TREE_CODE (rhstype) == POINTER_TYPE ? rhstype + : TYPE_PTRMEMFUNC_FN_TYPE (type)); + int ctt = comp_target_types (ttl, ttr, 1); + + if (ctt < 0) + cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", + ttr, ttl); + else if (ctt == 0) + cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr); + /* compatible pointer to member functions. */ - return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0); + return build_ptrmemfunc (ttl, rhs, 0); } else if (codel == ERROR_MARK || coder == ERROR_MARK) return error_mark_node;