diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 686b5b54635..5b2a422836d 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -44,10 +44,9 @@ X_CPPFLAGS = T_CPPFLAGS = CC = cc -# CYGNUS LOCAL: we use byacc instead of bison, DO NOT SEND TO RMS -BISON = `if [ -f ../../byacc/byacc ] ; then echo ../../byacc/byacc ; else echo byacc ; fi` +BISON = bison BISONFLAGS = -LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi` +LEX = flex LEXFLAGS= AR = ar OLDAR_FLAGS = qc @@ -204,7 +203,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h `echo $(srcdir)/parse.c | sed 's,^\./,,'` $(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y - @echo expect 28 shift/reduce conflicts, 14 reduce/reduce conflicts. + @echo expect 24 reduce/reduce conflicts. cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 02fc964e3ae..663b727aa95 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -39,7 +39,7 @@ extern int inhibit_warnings; extern int flag_assume_nonnull_objects; extern tree ctor_label, dtor_label; -/* From cp-typeck.c: */ +/* From typeck.c: */ extern tree unary_complex_lvalue (); /* Compute the ease with which a conversion can be performed @@ -2821,6 +2821,8 @@ build_method_call (instance, name, parms, basetype_path, flags) cp_error ("call to destructor for non-type `%D'", name); return void_zero_node; } + if (basetype != TREE_TYPE(instance)) + basetype = TREE_TYPE(instance); if (! TYPE_HAS_DESTRUCTOR (basetype)) return void_zero_node; instance = default_conversion (instance); @@ -3096,6 +3098,11 @@ 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) + { + TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0); + } if (TREE_CODE (t) == ARRAY_TYPE) { /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e6400105112..0c5cc264408 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -83,7 +83,7 @@ tree the_null_vtable_entry; /* Way of stacking language names. */ tree *current_lang_base, *current_lang_stack; -static int current_lang_stacksize; +int current_lang_stacksize; /* Names of languages we recognize. */ tree lang_name_c, lang_name_cplusplus; @@ -94,7 +94,7 @@ tree current_lang_name; via this node. */ static tree base_layout_decl; -/* Variables shared between cp-class.c and cp-call.c. */ +/* Variables shared between class.c and call.c. */ int n_vtables = 0; int n_vtable_entries = 0; @@ -471,7 +471,8 @@ build_vfn_ref (ptr_to_instptr, instance, idx) vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL_PTR); } - assemble_external (vtbl); + if (!flag_vtable_hack) + assemble_external (vtbl); aref = build_array_ref (vtbl, idx); /* Save the intermediate result in a SAVE_EXPR so we don't have to @@ -777,7 +778,8 @@ prepare_fresh_vtable (binfo, base_binfo, for_type) /* Access the virtual function table entry that logically contains BASE_FNDECL. VIRTUALS is the virtual function table's - initializer. */ + initializer. We can run off the end, when dealing with virtual + destructors in MI situations, return NULL_TREE in that case. */ static tree get_vtable_entry (virtuals, base_fndecl) tree virtuals, base_fndecl; @@ -794,7 +796,7 @@ get_vtable_entry (virtuals, base_fndecl) n_vtable_searches += i; #endif - while (i > 0) + while (i > 0 && virtuals) { virtuals = TREE_CHAIN (virtuals); i -= 1; @@ -1276,13 +1278,15 @@ modify_vtable_entries (t, fndecl, base_fndecl, pfn) prepare_fresh_vtable (binfo, base, t); } - saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl))), 0); + saved_pfn = get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl); + if (saved_pfn) + saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (saved_pfn)), 0); #ifdef NOTQUITE cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo))); #endif /* The this_offset can be wrong, if we try and modify an entry that had been modified once before. */ - if (! SAME_FN (saved_pfn, fndecl)) + if (saved_pfn && ! SAME_FN (saved_pfn, fndecl)) { modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl), build_vtable_entry (this_offset, pfn), @@ -1738,12 +1742,15 @@ alter_access (t, fdecl, access) return 0; } -static tree +/* Return the offset to the main vtable for a given base BINFO. */ +tree get_vfield_offset (binfo) tree binfo; { return size_binop (PLUS_EXPR, - DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), + size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), + size_int (BITS_PER_UNIT)), BINFO_OFFSET (binfo)); } @@ -2148,6 +2155,22 @@ finish_base_struct (t, b, t_binfo) b->cant_synth_copy_ctor = 1; } } + { + tree v = get_vbase_types (t_binfo); + + for (; v; v = TREE_CHAIN (v)) + { + tree basetype = BINFO_TYPE (v); + if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) + { + if (extra_warnings) + cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", + basetype, t); + b->cant_synth_asn_ref = 1; + b->cant_synth_copy_ctor = 1; + } + } + } { tree vfields; @@ -2726,7 +2749,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) enum tree_code code = TREE_CODE (t); register tree x, last_x, method_vec; int needs_virtual_dtor; - tree name = TYPE_NAME (t), fields, fn_fields, tail; + tree name = TYPE_NAME (t), fields, fn_fields, *tail; + tree *tail_user_methods = &CLASSTYPE_METHODS (t); enum access_type access; int all_virtual; int has_virtual; @@ -2902,8 +2926,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELD (t) = vfield; - fn_fields = NULL_TREE; - tail = NULL_TREE; + tail = &fn_fields; if (last_x && list_of_fieldlists) TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); @@ -2961,11 +2984,11 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (last_x) TREE_CHAIN (last_x) = TREE_CHAIN (x); - if (! fn_fields) - fn_fields = x; - else - TREE_CHAIN (tail) = x; - tail = x; + /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ + *tail = x; + tail = &TREE_CHAIN (x); + *tail_user_methods = x; + tail_user_methods = &DECL_NEXT_METHOD (x); #if 0 /* ??? What if we have duplicate declarations @@ -3284,8 +3307,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) } } - if (tail) TREE_CHAIN (tail) = NULL_TREE; - /* If this type has any constant members which did not come with their own initialization, mark that fact here. It is not an error here, since such types can be saved either by their @@ -3306,11 +3327,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_NEEDS_DESTRUCTOR (t) = 0; else { - if (! fn_fields) - fn_fields = dtor; - else - TREE_CHAIN (tail) = dtor; - tail = dtor; + /* Link dtor onto end of fn_fields. */ + *tail = dtor; + tail = &TREE_CHAIN (dtor); if (DECL_VINDEX (dtor) == NULL_TREE && ! CLASSTYPE_DECLARED_EXCEPTION (t) @@ -3325,6 +3344,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) } } + *tail = NULL_TREE; + *tail_user_methods = NULL_TREE; + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); /* Synthesize any needed methods. Note that methods will be synthesized diff --git a/gcc/cp/class.h b/gcc/cp/class.h index fb25a5f56b4..7e138243c01 100644 --- a/gcc/cp/class.h +++ b/gcc/cp/class.h @@ -149,7 +149,7 @@ struct candidate }; int rank_for_overload (); -/* Variables shared between cp-class.c and cp-call.c. */ +/* Variables shared between class.c and call.c. */ extern int n_vtables; extern int n_vtable_entries; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b431e160a6b..e4db0dc8c97 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -259,6 +259,11 @@ extern int flag_signed_bitfields; extern int write_virtuals; +/* True if we want output of vtables to be controlled by whether + we seen the class's first non-inline virtual function. + 0 is old behavior; 1 is new behavior. */ +extern flag_vtable_hack; + /* INTERFACE_ONLY nonzero means that we are in an "interface" section of the compiler. INTERFACE_UNKNOWN nonzero means we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN @@ -486,6 +491,8 @@ struct lang_type union tree_node *dossier; + union tree_node *methods; + union tree_node *signature; union tree_node *signature_pointer_to; union tree_node *signature_reference_to; @@ -604,6 +611,10 @@ struct lang_type /* The is the VAR_DECL that contains NODE's dossier. */ #define CLASSTYPE_DOSSIER(NODE) (TYPE_LANG_SPECIFIC(NODE)->dossier) +/* List of all explicit methods (chained using DECL_NEXT_METHOD), + in order they were parsed. */ +#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods) + /* Nonzero means that this _CLASSTYPE node overloads operator(). */ #define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded) @@ -927,7 +938,7 @@ struct lang_decl struct template_info *template_info; tree main_decl_variant; struct pending_inline *pending_inline_info; - tree vbase_init_list; + tree next_method; tree chain; }; @@ -1007,6 +1018,9 @@ struct lang_decl #define DECL_CHAIN(NODE) (TREE_CHAIN (NODE)) #endif +/* Next method in CLASSTYPE_METHODS list. */ +#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method) + /* Points back to the decl which caused this lang_decl to be allocated. */ #define DECL_MAIN_VARIANT(NODE) (DECL_LANG_SPECIFIC(NODE)->main_decl_variant) @@ -1024,11 +1038,6 @@ struct lang_decl which this signature member function pointer was created. */ #define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to) -/* Holds information about how virtual base classes should be initialized - by this constructor *if* this constructor is the one to perform - such initialization. */ -#define DECL_VBASE_INIT_LIST(NODE) (DECL_LANG_SPECIFIC(NODE)->vbase_init_list) - /* For a TEMPLATE_DECL: template-specific information. */ #define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info) @@ -1218,7 +1227,7 @@ struct lang_decl #define DECL_TEMPLATE_IS_CLASS(NODE) (DECL_RESULT(NODE) == NULL_TREE) #define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE) /* For class templates. */ -#define DECL_TEMPLATE_MEMBERS(NODE) DECL_INITIAL(NODE) +#define DECL_TEMPLATE_MEMBERS(NODE) DECL_SIZE(NODE) /* For function, method, class-data templates. */ #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) @@ -1279,7 +1288,7 @@ extern tree truthvalue_conversion PROTO((tree)); extern tree type_for_mode PROTO((enum machine_mode, int)); extern tree type_for_size PROTO((unsigned, int)); -/* in cp-decl{2}.c */ +/* in decl{2}.c */ extern tree void_list_node; extern tree void_zero_node; extern tree default_function_type; @@ -1319,12 +1328,12 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node; /* For building calls to `delete'. */ extern tree integer_two_node, integer_three_node; -/* in cp-except.c */ +/* in except.c */ extern tree current_exception_type; extern tree current_exception_decl; extern tree current_exception_object; -/* in cp-pt.c */ +/* in pt.c */ /* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those parameters. */ @@ -1358,7 +1367,7 @@ struct tinst_level extern struct tinst_level *current_tinst_level; -/* in cp-class.c */ +/* in class.c */ extern tree current_class_name; extern tree current_class_type; extern tree previous_class_type; @@ -1372,7 +1381,7 @@ extern tree original_function_name; extern tree current_class_name, current_class_type, current_class_decl, C_C_D; extern tree current_vtable_decl; -/* in cp-init.c */ +/* in init.c */ extern tree global_base_init_list; extern tree current_base_init_list, current_member_init_list; @@ -1568,7 +1577,7 @@ enum access_type { access_private_virtual }; -/* in cp-lex.c */ +/* in lex.c */ extern tree current_unit_name, current_unit_language; /* Things for handling inline functions. */ @@ -1590,7 +1599,7 @@ struct pending_inline unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */ }; -/* in cp-method.c */ +/* in method.c */ extern struct pending_inline *pending_inlines; /* 1 for -fall-virtual: make every member function (except @@ -1695,7 +1704,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \ TEMPLATE_CONST_IDX (NODE) = I) -/* in cp-lex.c */ +/* in lex.c */ /* Indexed by TREE_CODE, these tables give C-looking names to operators represented by TREE_CODES. For example, opname_tab[(int) MINUS_EXPR] == "-". */ @@ -1706,7 +1715,7 @@ extern tree convert_and_check PROTO((tree, tree)); extern void overflow_warning PROTO((tree)); extern void unsigned_conversion_warning PROTO((tree, tree)); -/* in cp-call.c */ +/* in call.c */ extern struct candidate *ansi_c_bullshit; extern int rank_for_overload PROTO((struct candidate *, struct candidate *)); @@ -1721,12 +1730,13 @@ extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate * extern tree build_overload_call PROTO((tree, tree, int, struct candidate *)); extern tree build_overload_call_maybe PROTO((tree, tree, int, struct candidate *)); -/* in cp-class.c */ +/* in class.c */ extern tree build_vbase_pointer PROTO((tree, tree)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); extern tree build_vtable_entry PROTO((tree, tree)); extern tree build_vfn_ref PROTO((tree *, tree, tree)); extern void add_method PROTO((tree, tree *, tree)); +extern tree get_vfield_offset PROTO((tree)); extern void duplicate_tag_error PROTO((tree)); extern tree finish_struct PROTO((tree, tree, int)); extern int resolves_to_fixed_type_p PROTO((tree, int *)); @@ -1742,7 +1752,7 @@ extern tree instantiate_type PROTO((tree, tree, int)); extern void print_class_statistics PROTO((void)); extern void maybe_push_cache_obstack PROTO((void)); -/* in cp-cvt.c */ +/* in cvt.c */ extern tree convert_to_reference PROTO((tree, tree, tree, tree, int, char *, int, int)); extern tree convert_from_reference PROTO((tree)); extern tree convert_to_aggr PROTO((tree, tree, char **, int)); @@ -1755,7 +1765,7 @@ extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int)); extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *)); extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *)); -/* cp-decl.c */ +/* decl.c */ extern int global_bindings_p PROTO((void)); extern void keep_next_level PROTO((void)); extern int kept_level_p PROTO((void)); @@ -1833,7 +1843,7 @@ extern void pop_implicit_try_blocks PROTO((tree)); extern void push_exception_cleanup PROTO((tree)); extern void revert_static_member_fn PROTO((tree *, tree *, tree *)); -/* in cp-decl2.c */ +/* in decl2.c */ extern int lang_decode_option PROTO((char *)); extern tree grok_method_quals PROTO((tree, tree, tree)); extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree)); @@ -1844,7 +1854,7 @@ extern void check_classfn PROTO((tree, tree, tree)); extern tree grokfield PROTO((tree, tree, tree, tree, tree)); extern tree grokbitfield PROTO((tree, tree, tree)); extern tree groktypefield PROTO((tree, tree)); -extern tree grokoptypename PROTO((tree, int)); +extern tree grokoptypename PROTO((tree, tree)); extern tree build_push_scope PROTO((tree, tree)); extern tree constructor_name_full PROTO((tree)); extern tree constructor_name PROTO((tree)); @@ -1862,10 +1872,14 @@ extern void walk_vtables PROTO((void (*)(), void (*)())); extern void finish_file PROTO((void)); extern void warn_if_unknown_interface PROTO((void)); extern tree grok_x_components PROTO((tree, tree)); +extern tree reparse_absdcl_as_expr PROTO((tree, tree)); +extern tree reparse_absdcl_as_casts PROTO((tree, tree)); +extern tree reparse_decl_as_expr PROTO((tree, tree)); +extern tree finish_decl_parsing PROTO((tree)); -/* in cp-edsel.c */ +/* in edsel.c */ -/* in cp-except.c */ +/* in except.c */ extern tree lookup_exception_cname PROTO((tree, tree, tree)); extern tree lookup_exception_tname PROTO((tree)); extern tree lookup_exception_object PROTO((tree, tree, int)); @@ -1888,13 +1902,13 @@ extern void setup_exception_throw_decl PROTO((void)); extern void init_exception_processing PROTO((void)); extern void init_exception_processing_1 PROTO((void)); -/* in cp-expr.c */ +/* in expr.c */ /* skip cplus_expand_expr */ extern void init_cplus_expand PROTO((void)); extern void fixup_result_decl PROTO((tree, struct rtx_def *)); extern int decl_in_memory_p PROTO((tree)); -/* in cp-gc.c */ +/* in gc.c */ extern int type_needs_gc_entry PROTO((tree)); extern int value_safe_from_gc PROTO((tree, tree)); extern void build_static_gc_entry PROTO((tree, tree)); @@ -1911,7 +1925,7 @@ extern tree build_typeid PROTO((tree)); extern tree get_typeid PROTO((tree)); extern tree build_dynamic_cast PROTO((tree, tree)); -/* in cp-init.c */ +/* in init.c */ extern void emit_base_init PROTO((tree, int)); extern void check_base_init PROTO((tree)); extern tree build_virtual_init PROTO((tree, tree, tree)); @@ -1941,9 +1955,9 @@ extern tree build_delete PROTO((tree, tree, tree, int, int)); extern tree build_vbase_delete PROTO((tree, tree)); extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, tree)); -/* in cp-input.c */ +/* in input.c */ -/* in cp-lex.c */ +/* in lex.c */ extern tree make_pointer_declarator PROTO((tree, tree)); extern tree make_reference_declarator PROTO((tree, tree)); extern char *operator_name_string PROTO((tree)); @@ -1986,7 +2000,7 @@ extern void dump_time_statistics PROTO((void)); extern void compiler_error_with_decl PROTO((tree, char *)); extern void yyerror PROTO((char *)); -/* in cp-error.c */ +/* in error.c */ extern void init_error PROTO((void)); extern char *fndecl_as_string PROTO((tree, tree, int)); extern char *type_as_string PROTO((tree, int)); @@ -1998,7 +2012,7 @@ extern char *language_as_string PROTO((enum languages, int)); extern char *parm_as_string PROTO((int, int)); extern char *op_as_string PROTO((enum tree_code, int)); -/* in cp-method.c */ +/* in method.c */ extern void init_method PROTO((void)); extern tree make_anon_parm_name PROTO((void)); extern void clear_anon_parm_name PROTO((void)); @@ -2017,11 +2031,11 @@ extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PROTO((tree, tree, int)); extern tree build_component_type_expr PROTO((tree, tree, tree, int)); -/* in cp-pt.c */ +/* in pt.c */ extern void begin_template_parm_list PROTO((void)); extern tree process_template_parm PROTO((tree, tree)); extern tree end_template_parm_list PROTO((tree)); -extern void end_template_decl PROTO((tree, tree, tree)); +extern void end_template_decl PROTO((tree, tree, tree, int)); extern tree lookup_template_class PROTO((tree, tree, tree)); extern void push_template_decls PROTO((tree, tree, int)); extern void pop_template_decls PROTO((tree, tree, int)); @@ -2039,7 +2053,7 @@ extern void do_pending_templates PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void)); extern void do_function_instantiation PROTO((tree, tree)); -/* in cp-search.c */ +/* in search.c */ extern tree make_memoized_table_entry PROTO((tree, tree, int)); extern void push_memoized_context PROTO((tree, int)); extern void pop_memoized_context PROTO((int)); @@ -2075,7 +2089,7 @@ extern void init_search_processing PROTO((void)); extern void reinit_search_statistics PROTO((void)); extern tree current_scope PROTO((void)); -/* in cp-sig.c */ +/* in sig.c */ extern tree build_signature_pointer_type PROTO((tree, int, int)); extern tree build_signature_reference_type PROTO((tree, int, int)); extern tree build_signature_pointer_constructor PROTO((tree, tree)); @@ -2084,12 +2098,12 @@ extern tree build_optr_ref PROTO((tree)); extern tree build_sptr_ref PROTO((tree)); extern tree build_vptr_ref PROTO((tree)); -/* in cp-spew.c */ +/* in spew.c */ extern void init_spew PROTO((void)); extern int yylex PROTO((void)); extern tree arbitrate_lookup PROTO((tree, tree, tree)); -/* in cp-tree.c */ +/* in tree.c */ extern int lvalue_p PROTO((tree)); extern int lvalue_or_else PROTO((tree, char *)); extern tree build_cplus_new PROTO((tree, tree, int)); @@ -2135,7 +2149,7 @@ extern void print_lang_statistics PROTO((void)); extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_top PROTO((tree)); -/* in cp-typeck.c */ +/* in typeck.c */ extern tree target_type PROTO((tree)); extern tree require_complete_type PROTO((tree)); extern int type_unknown_p PROTO((tree)); @@ -2191,7 +2205,7 @@ extern tree c_expand_start_case PROTO((tree)); extern tree build_component_ref PROTO((tree, tree, tree, int)); extern tree build_ptrmemfunc PROTO((tree, tree, int)); -/* in cp-type2.c */ +/* in typeck2.c */ extern tree error_not_base_type PROTO((tree, tree)); extern tree binfo_or_else PROTO((tree, tree)); extern void error_with_aggr_type (); /* PROTO((tree, char *, HOST_WIDE_INT)); */ @@ -2209,7 +2223,7 @@ extern tree build_functional_cast PROTO((tree, tree)); extern char *enum_name_string PROTO((tree, tree)); extern void report_case_error PROTO((int, tree, tree, tree)); -/* in cp-xref.c */ +/* in xref.c */ extern void GNU_xref_begin PROTO((char *)); extern void GNU_xref_end PROTO((int)); extern void GNU_xref_file PROTO((char *)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 347a901a821..5e41618a631 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -581,7 +581,11 @@ build_up_reference (type, arg, flags, checkconst) if (TYPE_USES_COMPLEX_INHERITANCE (argtype)) { TREE_TYPE (rval) = TYPE_POINTER_TO (argtype); - rval = convert_pointer_to (target_type, rval); + if (flags & LOOKUP_PROTECT) + rval = convert_pointer_to (target_type, rval); + else + rval + = convert_to_pointer_force (build_pointer_type (target_type), rval); TREE_TYPE (rval) = type; } TREE_CONSTANT (rval) = literal_flag; @@ -1439,18 +1443,16 @@ convert_force (type, expr) if (code == POINTER_TYPE) return fold (convert_to_pointer_force (type, e)); - /* From cp-typeck.c convert_for_assignment */ + /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE) - || integer_zerop (e)) + || integer_zerop (e) + || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) && TYPE_PTRMEMFUNC_P (type)) { /* compatible pointer to member functions. */ - e = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); - if (e == 0) - return error_mark_node; - return digest_init (type, e, (tree *)0); + return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); } { int old_equiv = flag_int_enum_equivalence; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f9ee26dca0c..1ad7849f8f3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -444,7 +444,7 @@ extern int flag_conserve_space; extern tree *current_lang_base, *current_lang_stack; -/* C and C++ flags are in cp-decl2.c. */ +/* C and C++ flags are in decl2.c. */ /* Set to 0 at beginning of a constructor, set to 1 if that function does an allocation before referencing its @@ -465,7 +465,7 @@ int current_function_obstack_index; int current_function_obstack_usage; -/* Flag used when debugging cp-spew.c */ +/* Flag used when debugging spew.c */ extern int spew_debug; @@ -1471,6 +1471,9 @@ struct saved_scope { tree class_name, class_type, class_decl, function_decl; struct binding_level *class_bindings; tree previous_class_type; + tree *lang_base, *lang_stack, lang_name; + int lang_stacksize; + tree named_labels; }; static struct saved_scope *current_saved_scope; extern tree prev_class_type; @@ -1478,6 +1481,7 @@ extern tree prev_class_type; void push_to_top_level () { + extern int current_lang_stacksize; struct saved_scope *s = (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); struct binding_level *b = current_binding_level; @@ -1543,10 +1547,21 @@ push_to_top_level () s->function_decl = current_function_decl; s->class_bindings = class_binding_level; s->previous_class_type = previous_class_type; + s->lang_stack = current_lang_stack; + s->lang_base = current_lang_base; + s->lang_stacksize = current_lang_stacksize; + s->lang_name = current_lang_name; + s->named_labels = named_labels; current_class_name = current_class_type = current_class_decl = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; previous_class_type = NULL_TREE; + current_lang_stacksize = 10; + current_lang_stack = current_lang_base + = (tree *) xmalloc (current_lang_stacksize * sizeof (tree)); + current_lang_name = lang_name_cplusplus; + strict_prototype = strict_prototypes_lang_cplusplus; + named_labels = NULL_TREE; s->prev = current_saved_scope; s->old_bindings = old_bindings; @@ -1556,6 +1571,7 @@ push_to_top_level () void pop_from_top_level () { + extern int current_lang_stacksize; struct saved_scope *s = current_saved_scope; tree t; @@ -1584,6 +1600,17 @@ pop_from_top_level () current_function_decl = s->function_decl; class_binding_level = s->class_bindings; previous_class_type = s->previous_class_type; + free (current_lang_base); + current_lang_base = s->lang_base; + current_lang_stack = s->lang_stack; + current_lang_name = s->lang_name; + current_lang_stacksize = s->lang_stacksize; + if (current_lang_name == lang_name_cplusplus) + strict_prototype = strict_prototypes_lang_cplusplus; + else if (current_lang_name == lang_name_c) + strict_prototype = strict_prototypes_lang_c; + named_labels = s->named_labels; + free (s); } @@ -1661,7 +1688,7 @@ set_nested_typename (decl, classname, name, type) incorrect results with `-g' unless they duplicate this code. This is currently needed mainly for dbxout.c, but we can make - use of it in cp-method.c later as well. */ + use of it in method.c later as well. */ tree make_type_decl (name, type) tree name, type; @@ -1958,6 +1985,37 @@ decls_match (newdecl, olddecl) else types_match = 0; } + else if (TREE_CODE (newdecl) == TEMPLATE_DECL + && TREE_CODE (olddecl) == TEMPLATE_DECL) + { + tree newargs = DECL_TEMPLATE_PARMS (newdecl); + tree oldargs = DECL_TEMPLATE_PARMS (olddecl); + int i, len = TREE_VEC_LENGTH (newargs); + + if (TREE_VEC_LENGTH (oldargs) != len) + return 0; + + for (i = 0; i < len; i++) + { + tree newarg = TREE_VEC_ELT (newargs, i); + tree oldarg = TREE_VEC_ELT (oldargs, i); + if (TREE_CODE (newarg) != TREE_CODE (oldarg)) + return 0; + else if (TREE_CODE (newarg) == IDENTIFIER_NODE) + /* continue */; + else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1)) + return 0; + } + + if (DECL_TEMPLATE_IS_CLASS (newdecl) + != DECL_TEMPLATE_IS_CLASS (olddecl)) + types_match = 0; + else if (DECL_TEMPLATE_IS_CLASS (newdecl)) + types_match = 1; + else + types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl), + DECL_TEMPLATE_RESULT (newdecl)); + } else { if (TREE_TYPE (newdecl) == error_mark_node) @@ -2028,7 +2086,7 @@ warn_extern_redeclared_static (newdecl, olddecl) If safely possible, alter OLDDECL to look like NEWDECL, and return 1. Otherwise, return 0. */ -static int +int duplicate_decls (newdecl, olddecl) register tree newdecl, olddecl; { @@ -2038,8 +2096,7 @@ duplicate_decls (newdecl, olddecl) int new_defines_function; tree previous_c_decl = NULL_TREE; - if (TREE_CODE (newdecl) == FUNCTION_DECL - && is_overloaded_fn (olddecl)) + if (TREE_CODE (newdecl) == FUNCTION_DECL && is_overloaded_fn (olddecl)) { olddecl = get_first_fn (olddecl); @@ -2144,6 +2201,8 @@ duplicate_decls (newdecl, olddecl) cp_error ("declaration of C function `%#D' conflicts with", newdecl); cp_error_at ("previous declaration `%#D' here", previous_c_decl); } + else if (!types_match && TREE_CODE (newdecl) == TEMPLATE_DECL) + return 0; else if (!types_match) { tree oldtype = TREE_TYPE (olddecl); @@ -2238,7 +2297,7 @@ duplicate_decls (newdecl, olddecl) char *errmsg = redeclaration_error_message (newdecl, olddecl); if (errmsg) { - error_with_decl (newdecl, errmsg); + cp_error (errmsg, newdecl); if (DECL_NAME (olddecl) != NULL_TREE) cp_error_at ((DECL_INITIAL (olddecl) && current_binding_level == global_binding_level) @@ -2295,6 +2354,8 @@ duplicate_decls (newdecl, olddecl) DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl); if (DECL_CHAIN (newdecl) == NULL_TREE) DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl); + if (DECL_NEXT_METHOD (newdecl) == NULL_TREE) + DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl); if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0) DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl); } @@ -2325,6 +2386,10 @@ duplicate_decls (newdecl, olddecl) #endif } + if (TREE_CODE (olddecl) == TEMPLATE_DECL + && DECL_TEMPLATE_INFO (olddecl)->length) + DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); + /* Special handling ensues if new decl is a function definition. */ new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != NULL_TREE); @@ -2381,7 +2446,8 @@ duplicate_decls (newdecl, olddecl) layout_type (TREE_TYPE (newdecl)); if (TREE_CODE (newdecl) != FUNCTION_DECL && TREE_CODE (newdecl) != TYPE_DECL - && TREE_CODE (newdecl) != CONST_DECL) + && TREE_CODE (newdecl) != CONST_DECL + && TREE_CODE (newdecl) != TEMPLATE_DECL) layout_decl (newdecl, 0); } else @@ -2630,7 +2696,7 @@ pushdecl (x) cp_error_at ("`%#D' used prior to declaration", x); } - if (t != NULL_TREE) + else if (t != NULL_TREE) { if (TREE_CODE (t) == PARM_DECL) { @@ -2639,25 +2705,23 @@ pushdecl (x) } file = DECL_SOURCE_FILE (t); line = DECL_SOURCE_LINE (t); - } - if (t != NULL_TREE - && (TREE_CODE (t) != TREE_CODE (x) || is_overloaded_fn (t))) - { - if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL) + if (TREE_CODE (t) != TREE_CODE (x)) { - /* We do nothing special here, because C++ does such nasty - things with TYPE_DECLs. Instead, just let the TYPE_DECL - get shadowed, and know that if we need to find a TYPE_DECL - for a given name, we can look in the IDENTIFIER_TYPE_VALUE - slot of the identifier. */ - ; + if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL) + { + /* We do nothing special here, because C++ does such nasty + things with TYPE_DECLs. Instead, just let the TYPE_DECL + get shadowed, and know that if we need to find a TYPE_DECL + for a given name, we can look in the IDENTIFIER_TYPE_VALUE + slot of the identifier. */ + ; + } + else if (duplicate_decls (x, t)) + return t; } else if (duplicate_decls (x, t)) - return t; - } - else if (t != NULL_TREE && duplicate_decls (x, t)) - { + { #if 0 /* This is turned off until I have time to do it right (bpk). */ @@ -2682,14 +2746,16 @@ pushdecl (x) } #endif - /* Due to interference in memory reclamation (X may be - obstack-deallocated at this point), we must guard against - one really special case. */ - if (current_function_decl == x) - current_function_decl = t; - - return t; + /* Due to interference in memory reclamation (X may be + obstack-deallocated at this point), we must guard against + one really special case. */ + if (current_function_decl == x) + current_function_decl = t; + + return t; + } } + /* If declaring a type as a typedef, and the type has no known typedef name, install this TYPE_DECL as its typedef name. */ @@ -3272,7 +3338,7 @@ redeclaration_error_message (newdecl, olddecl) if (comptypes (newdecl, olddecl, 0)) return 0; else - return "redefinition of `%s'"; + return "redefinition of `%#D'"; } else if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -3294,12 +3360,18 @@ redeclaration_error_message (newdecl, olddecl) && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) { if (DECL_NAME (olddecl) == NULL_TREE) - return "`%s' not declared in class"; + return "`%#D' not declared in class"; else - return "redefinition of `%s'"; + return "redefinition of `%#D'"; } return 0; } + else if (TREE_CODE (newdecl) == TEMPLATE_DECL) + { + if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl)) + return "redefinition of `%#D'"; + return 0; + } else if (current_binding_level == global_binding_level) { /* Objects declared at top level: */ @@ -3309,11 +3381,11 @@ redeclaration_error_message (newdecl, olddecl) /* Reject two definitions. */ if (DECL_INITIAL (olddecl) != NULL_TREE && DECL_INITIAL (newdecl) != NULL_TREE) - return "redefinition of `%s'"; + return "redefinition of `%#D'"; /* Now we have two tentative defs, or one tentative and one real def. */ /* Insist that the linkage match. */ if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl)) - return "conflicting declarations of `%s'"; + return "conflicting declarations of `%#D'"; return 0; } else @@ -3322,7 +3394,7 @@ redeclaration_error_message (newdecl, olddecl) /* Reject two definitions, and reject a definition together with an external reference. */ if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) - return "redeclaration of `%s'"; + return "redeclaration of `%#D'"; return 0; } } @@ -3780,8 +3852,7 @@ lookup_nested_type (type, context) definitions if there are many, or return 0 if it is undefined. If PREFER_TYPE is > 0, we prefer TYPE_DECLs. - If PREFER_TYPE is = 0, we prefer non-TYPE_DECLs. - If PREFER_TYPE is < 0, we arbitrate according to lexical context. */ + Otherwise we prefer non-TYPE_DECLs. */ tree lookup_name (name, prefer_type) @@ -3840,9 +3911,8 @@ lookup_name (name, prefer_type) if (val == val_as_type || prefer_type > 0 || looking_for_typename > 0) return val_as_type; - if (prefer_type == 0) - return val; - return arbitrate_lookup (name, val, val_as_type); + + return val; } if (TREE_TYPE (val) == error_mark_node) return error_mark_node; @@ -5233,7 +5303,7 @@ start_decl (declarator, declspecs, initialized, raises) my_friendly_abort (13); } else if (TREE_CODE (result) == FUNCTION_DECL) - tem = push_overloaded_decl (tem, 0); + /*tem = push_overloaded_decl (tem, 0)*/; else if (TREE_CODE (result) == VAR_DECL || TREE_CODE (result) == TYPE_DECL) { @@ -6329,9 +6399,17 @@ complete_array_type (type, initial_value, do_default) if (maxindex) { + tree itype; + TYPE_DOMAIN (type) = build_index_type (maxindex); if (!TREE_TYPE (maxindex)) TREE_TYPE (maxindex) = TYPE_DOMAIN (type); + if (initial_value) + itype = TREE_TYPE (initial_value); + else + itype = NULL; + if (itype && !TYPE_DOMAIN (itype)) + TYPE_DOMAIN (itype) = TYPE_DOMAIN (type); } /* Lay out the type now that we can get the real answer. */ @@ -6947,8 +7025,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) case IDENTIFIER_NODE: dname = decl; - name = IDENTIFIER_POINTER (decl); decl = NULL_TREE; + + if (IDENTIFIER_TYPENAME_P (dname)) + { + my_friendly_assert (flags == NO_SPECIAL, 154); + flags = TYPENAME_FLAG; + ctor_return_type = TREE_TYPE (dname); + return_type = return_conversion; + } + + if (IDENTIFIER_OPNAME_P (dname)) + name = operator_name_string (dname); + else + name = IDENTIFIER_POINTER (dname); break; case RECORD_TYPE: @@ -6965,15 +7055,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) decl = NULL_TREE; break; - case TYPE_EXPR: - my_friendly_assert (flags == NO_SPECIAL, 154); - flags = TYPENAME_FLAG; - name = "operator "; /* We don't know the type yet. */ - /* Go to the absdcl. */ - decl = TREE_OPERAND (decl, 0); - return_type = return_conversion; - break; - /* C++ extension */ case SCOPE_REF: /* @@ -7214,6 +7295,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = void_type_node; else if (return_type == return_ctor) type = TYPE_POINTER_TO (ctor_return_type); + else if (return_type == return_conversion) + type = ctor_return_type; else if (current_class_type && IS_SIGNATURE (current_class_type) && (RIDBIT_SETP (RID_TYPEDEF, specbits) @@ -7247,6 +7330,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) error ("return type specification for constructor invalid"); type = TYPE_POINTER_TO (ctor_return_type); } + else if (return_type == return_conversion) + { + if (comp_target_types (type, ctor_return_type, 1) == 0) + cp_error ("operator `%T' declared to return `%T'", + ctor_return_type, type); + else + cp_pedwarn ("return type specified for `operator %T'", + ctor_return_type); + + type = ctor_return_type; + } ctype = NULL_TREE; @@ -7508,11 +7602,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) error ("typedef declaration includes an initializer"); /* To process a class-local typedef declaration, we descend down - the chain of declspecs looking for the `typedef' spec. When we - find it, we splice it out of the chain of declspecs, and then - recursively call `grokdeclarator' with the original declarator - and with the newly adjusted declspecs. This call should return - a FIELD_DECL node with the TREE_TYPE (and other parts) set + the chain of declspecs looking for the `typedef' spec. When + we find it, we replace it with `static', and then recursively + call `grokdeclarator' with the original declarator and with + the newly adjusted declspecs. This call should return a + FIELD_DECL node with the TREE_TYPE (and other parts) set appropriately. We can then just change the TREE_CODE on that from FIELD_DECL to TYPE_DECL and we're done. */ @@ -7523,11 +7617,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF]) break; } - if (previous_declspec) - TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner); + + if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF])) + { + if (previous_declspec) + TREE_CHAIN (previous_declspec) + = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); + else + declspecs + = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); + } else - declspecs = TREE_CHAIN (scanner); - + TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC]; + /* In the recursive call to grokdeclarator we need to know whether we are working on a signature-local typedef. */ if (IS_SIGNATURE (current_class_type)) @@ -7650,7 +7752,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) qualify the member name. an ADDR_EXPR (for &...), a BIT_NOT_EXPR (for destructors) - a TYPE_EXPR (for operator typenames) At this point, TYPE is the type of elements of an array, or for a function to return, or for a pointer to point to. @@ -7854,7 +7955,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) && (friendp == 0 || dname == current_class_name)) ctype = current_class_type; - if (ctype && flags == TYPENAME_FLAG) + if (ctype && return_type == return_conversion) TYPE_HAS_CONVERSION (ctype) = 1; if (ctype && constructor_name (ctype) == dname) { @@ -7910,17 +8011,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) return void_type_node; } { - int inlinep, staticp; - inlinep = RIDBIT_SETP (RID_INLINE, specbits); - staticp = RIDBIT_SETP (RID_STATIC, specbits); - RIDBIT_RESET (RID_INLINE, specbits); - RIDBIT_RESET (RID_STATIC, specbits); - if (RIDBIT_ANY_SET (specbits)) + RID_BIT_TYPE tmp_bits; + bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE)); + RIDBIT_RESET (RID_INLINE, tmp_bits); + RIDBIT_RESET (RID_STATIC, tmp_bits); + if (RIDBIT_ANY_SET (tmp_bits)) error ("return value type specifier for constructor ignored"); - if (inlinep) - RIDBIT_SET (RID_INLINE, specbits); - if (staticp) - RIDBIT_SET (RID_STATIC, specbits); } type = TYPE_POINTER_TO (ctype); if (decl_context == FIELD && @@ -7982,9 +8078,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ funcdef_p = - (inner_decl && - (TREE_CODE (inner_decl) == IDENTIFIER_NODE - || TREE_CODE (inner_decl) == TYPE_EXPR)) ? funcdef_flag : 0; + (inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE) + ? funcdef_flag : 0; /* FIXME: This is where default args should be fully processed. */ @@ -8242,12 +8337,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) return t; } - if (flags == TYPENAME_FLAG) - cp_error ("type conversion is not a member of structure `%T'", ctype); - else - cp_error - ("field `%D' is not a member of structure `%T'", - sname, ctype); + cp_error + ("field `%D' is not a member of structure `%T'", + sname, ctype); } if (current_class_type) @@ -8283,28 +8375,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) declarator = sname; } - else if (TREE_CODE (sname) == TYPE_EXPR) - { - /* A TYPE_EXPR will change types out from under us. - So do the TYPE_EXPR now, and make this SCOPE_REF - inner to the TYPE_EXPR's CALL_EXPR. - - This does not work if we don't get a CALL_EXPR back. - I did not think about error recovery, hence the - my_friendly_abort. */ - - /* Get the CALL_EXPR. */ - sname = grokoptypename (sname, 0); - my_friendly_assert (TREE_CODE (sname) == CALL_EXPR, 157); - type = TREE_TYPE (TREE_OPERAND (sname, 0)); - /* Scope the CALL_EXPR's name. */ - TREE_OPERAND (declarator, 1) = TREE_OPERAND (sname, 0); - /* Put the SCOPE_EXPR in the CALL_EXPR's innermost position. */ - TREE_OPERAND (sname, 0) = declarator; - /* Now work from the CALL_EXPR. */ - declarator = sname; - continue; - } else if (TREE_CODE (sname) == SCOPE_REF) my_friendly_abort (17); else @@ -8329,21 +8399,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) declarator = TREE_OPERAND (declarator, 0); break; - case TYPE_EXPR: - declarator = grokoptypename (declarator, 0); - if (explicit_int != -1) - { - tree stype = TREE_TYPE (TREE_OPERAND (declarator, 0)); - if (comp_target_types (type, stype, 1) == 0) - cp_error ("`operator %T' declared to return `%T'", stype, - type); - else - cp_pedwarn ("return type specified for `operator %T'", type); - } - dname = declarator; - type = TREE_TYPE (TREE_OPERAND (declarator, 0)); - break; - case RECORD_TYPE: case UNION_TYPE: case ENUMERAL_TYPE: @@ -8667,6 +8722,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) && ! funcdef_flag && RIDBIT_NOTSETP (RID_STATIC, specbits) && RIDBIT_NOTSETP (RID_INLINE, specbits))); + if (TREE_CODE (type) == METHOD_TYPE) + publicp + |= (ctype && CLASSTYPE_INTERFACE_KNOWN (ctype)) + || (!funcdef_flag && RIDBIT_NOTSETP (RID_INLINE, specbits)); decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0, publicp); @@ -8843,8 +8902,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) into some other file, so we don't clear TREE_PUBLIC for them. */ publicp = ((ctype - && CLASSTYPE_INTERFACE_KNOWN (ctype) - && ! CLASSTYPE_INTERFACE_ONLY (ctype)) + && CLASSTYPE_INTERFACE_KNOWN (ctype)) || !(RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits))); @@ -10212,7 +10270,7 @@ build_enumerator (name, value) if (value) STRIP_TYPE_NOPS (value); - /* Make up for hacks in cp-lex.c. */ + /* Make up for hacks in lex.c. */ if (value == integer_zero_node) value = build_int_2 (0, 0); else if (value == integer_one_node) @@ -10573,7 +10631,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p) else if (pre_parsed_p == 0) { current_function_decl = pushdecl (decl1); - if (TREE_CODE (current_function_decl) == TREE_LIST) + if (TREE_CODE (current_function_decl) == TREE_LIST + || (DECL_ASSEMBLER_NAME (current_function_decl) + != DECL_ASSEMBLER_NAME (decl1))) { /* @@ revert to modified original declaration. */ decl1 = DECL_MAIN_VARIANT (decl1); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index db455777115..c752e2303f8 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -58,7 +58,7 @@ static int temp_name_counter; can have the same name. */ static int global_temp_name_counter; -/* Flag used when debugging cp-spew.c */ +/* Flag used when debugging spew.c */ extern int spew_debug; @@ -129,6 +129,10 @@ int warn_implicit = 1; int warn_ctor_dtor_privacy = 1; +/* True if we want output of vtables to be controlled by whether + we seen the class's first non-inline virtual function. */ +int flag_vtable_hack = 0; + /* Nonzero means give string constants the type `const char *' to get extra warnings from them. These warnings will be too numerous to be useful, except in thoroughly ANSIfied programs. */ @@ -360,6 +364,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"ansi-overloading", &flag_ansi_overloading, 1}, {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, + {"vtable-hack", &flag_vtable_hack, 1}, }; /* Decode the string P as a language-specific option. @@ -1619,107 +1624,12 @@ groktypefield (declspecs, parmlist) return decl; } -/* The precedence rules of this grammar (or any other deterministic LALR - grammar, for that matter), place the CALL_EXPR somewhere where we - may not want it. The solution is to grab the first CALL_EXPR we see, - pretend that that is the one that belongs to the parameter list of - the type conversion function, and leave everything else alone. - We pull it out in place. - - CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR - does not appear in DECL. */ tree -grokoptypename (decl, call_required) - tree decl; - int call_required; +grokoptypename (declspecs, declarator) + tree declspecs, declarator; { - tree tmp, last; - - my_friendly_assert (TREE_CODE (decl) == TYPE_EXPR, 195); - - tmp = TREE_OPERAND (decl, 0); - last = NULL_TREE; - - while (tmp) - { - switch (TREE_CODE (tmp)) - { - case CALL_EXPR: - { - tree parms = TREE_OPERAND (tmp, 1); - - if (last) - TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0); - else - TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0); - - last = grokdeclarator (TREE_OPERAND (decl, 0), - TREE_TYPE (decl), - TYPENAME, 0, NULL_TREE); - TREE_OPERAND (tmp, 0) = build_typename_overload (last); - TREE_TYPE (TREE_OPERAND (tmp, 0)) = last; - - if (parms - && TREE_CODE (TREE_VALUE (parms)) == TREE_LIST) - TREE_VALUE (parms) - = grokdeclarator (TREE_VALUE (TREE_VALUE (parms)), - TREE_PURPOSE (TREE_VALUE (parms)), - TYPENAME, 0, NULL_TREE); - if (parms) - { - if (TREE_VALUE (parms) != void_type_node) - cp_error ("`operator %T' requires empty parameter list", - last); - else - /* Canonicalize parameter lists. */ - TREE_OPERAND (tmp, 1) = void_list_node; - } - - return tmp; - } - - case INDIRECT_REF: - case ADDR_EXPR: - case ARRAY_REF: - break; - - case SCOPE_REF: - /* This is legal when declaring a conversion to - something of type pointer-to-member. */ - if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF) - { - tmp = TREE_OPERAND (tmp, 1); - } - else - { -#if 0 - /* We may need to do this if grokdeclarator cannot handle this. */ - error ("type `member of class %s' invalid return type", - TYPE_NAME_STRING (TREE_OPERAND (tmp, 0))); - TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1)); -#endif - tmp = TREE_OPERAND (tmp, 1); - } - break; - - default: - my_friendly_abort (196); - } - last = tmp; - tmp = TREE_OPERAND (tmp, 0); - } - - last = grokdeclarator (TREE_OPERAND (decl, 0), - TREE_TYPE (decl), - TYPENAME, 0, NULL_TREE); - - if (call_required) - cp_error ("`operator %T' construct requires parameter list", last); - - tmp = build_parse_node (CALL_EXPR, build_typename_overload (last), - void_list_node, NULL_TREE); - TREE_TYPE (TREE_OPERAND (tmp, 0)) = last; - return tmp; + tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); + return build_typename_overload (t); } /* When a function is declared with an initializer, @@ -2420,6 +2330,22 @@ static void finish_vtable_vardecl (prev, vars) tree prev, vars; { + tree ctype = DECL_CONTEXT (vars); + if (flag_vtable_hack && !CLASSTYPE_INTERFACE_KNOWN (ctype)) + { + tree method; + for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; + method = DECL_NEXT_METHOD (method)) + { + if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)) + { + TREE_PUBLIC (vars) = 1; + DECL_EXTERNAL (vars) = DECL_EXTERNAL (method); + break; + } + } + } + if (write_virtuals >= 0 && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) { @@ -2468,6 +2394,8 @@ finish_vtable_vardecl (prev, vars) rest_of_decl_compilation (vars, 0, 1, 1); } + else if (TREE_USED (vars) && flag_vtable_hack) + assemble_external (vars); /* We know that PREV must be non-zero here. */ TREE_CHAIN (prev) = TREE_CHAIN (vars); } @@ -2783,7 +2711,7 @@ finish_file () 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 - cp-decl.c (where we can manipulate global_binding_level directly), + 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. */ @@ -2821,3 +2749,134 @@ finish_file () if (flag_detailed_statistics) dump_time_statistics (); } + +/* This is something of the form 'A()()()()()+1' that has turned out to be an + expr. Since it was parsed like a type, we need to wade through and fix + that. Unfortunately, since operator() is left-associative, we can't use + tail recursion. In the above example, TYPE is `A', and DECL is + `()()()()()'. + + Maybe this shouldn't be recursive, but how often will it actually be + used? (jason) */ +tree +reparse_absdcl_as_expr (type, decl) + tree type, decl; +{ + /* do build_functional_cast (type, NULL_TREE) at bottom */ + if (TREE_OPERAND (decl, 0) == NULL_TREE) + return build_functional_cast (type, NULL_TREE); + + /* recurse */ + decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0)); + + decl = build_x_function_call (decl, NULL_TREE, current_class_decl); + + if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node) + decl = require_complete_type (decl); + + return decl; +} + +/* This is something of the form `int ((int)(int)(int)1)' that has turned + out to be an expr. Since it was parsed like a type, we need to wade + through and fix that. Since casts are right-associative, we are + reversing the order, so we don't have to recurse. + + In the above example, DECL is the `(int)(int)(int)', and EXPR is the + `1'. */ +tree +reparse_absdcl_as_casts (decl, expr) + tree decl, expr; +{ + tree type; + + if (TREE_CODE (expr) == CONSTRUCTOR) + { + type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); + decl = TREE_OPERAND (decl, 0); + + if (IS_SIGNATURE (type)) + { + error ("cast specifies signature type"); + return error_mark_node; + } + + expr = digest_init (type, expr, (tree *) 0); + if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) + { + int failure = complete_array_type (type, expr, 1); + if (failure) + my_friendly_abort (78); + } + } + + while (decl) + { + type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); + decl = TREE_OPERAND (decl, 0); + expr = build_c_cast (type, expr); + } + + return expr; +} + +/* Recursive helper function for reparse_decl_as_expr. It may be a good + idea to reimplement this using an explicit stack, rather than recursion. */ +static tree +reparse_decl_as_expr1 (decl) + tree decl; +{ + switch (TREE_CODE (decl)) + { + case IDENTIFIER_NODE: + return do_identifier (decl); + case INDIRECT_REF: + return build_x_indirect_ref + (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *"); + case ADDR_EXPR: + return build_x_unary_op (ADDR_EXPR, + reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); + case BIT_NOT_EXPR: + return build_x_unary_op (BIT_NOT_EXPR, + reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); + } + my_friendly_abort (5); +} + +/* This is something of the form `int (*a)++' that has turned out to be an + expr. It was only converted into parse nodes, so we need to go through + and build up the semantics. Most of the work is done by + reparse_decl_as_expr1, above. + + In the above example, TYPE is `int' and DECL is `*a'. */ +tree +reparse_decl_as_expr (type, decl) + tree type, decl; +{ + decl = build_tree_list (NULL_TREE, reparse_decl_as_expr1 (decl)); + return build_functional_cast (type, decl); +} + +/* This is something of the form `int (*a)' that has turned out to be a + decl. It was only converted into parse nodes, so we need to do the + checking that make_{pointer,reference}_declarator do. */ + +tree +finish_decl_parsing (decl) + tree decl; +{ + switch (TREE_CODE (decl)) + { + case IDENTIFIER_NODE: + return decl; + case INDIRECT_REF: + return make_pointer_declarator + (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); + case ADDR_EXPR: + return make_reference_declarator + (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); + case BIT_NOT_EXPR: + TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); + return decl; + } +} diff --git a/gcc/cp/errfn.c b/gcc/cp/errfn.c index 21feb772b47..335a304798a 100644 --- a/gcc/cp/errfn.c +++ b/gcc/cp/errfn.c @@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* cp_printer is the type of a function which converts an argument into a string for digestion by printf. The cp_printer function should deal with all memory management; the functions in this file will not free - the char*s returned. See cp-error.c for an example use of this code. */ + the char*s returned. See error.c for an example use of this code. */ typedef char* cp_printer PROTO((HOST_WIDE_INT, int)); extern cp_printer * cp_printers[256]; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 75167fcdf4e..3cc3ce8e05e 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -76,6 +76,7 @@ static char *scratch_firstobj; # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \ OB_PUTCP (digit_buffer); } while (0) +# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N)); # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t))) @@ -131,11 +132,11 @@ dump_type (t, v) switch (TREE_CODE (t)) { case ERROR_MARK: - OB_PUTS (""); + OB_PUTS ("{error}"); break; case UNKNOWN_TYPE: - OB_PUTS (""); + OB_PUTS ("{unknown type}"); break; case TREE_LIST: @@ -206,9 +207,7 @@ dump_type (t, v) break; case TEMPLATE_TYPE_PARM: - OB_PUTS ("