--- gcc/cp/decl.c 2018/04/24 18:20:21 1.1 +++ gcc/cp/decl.c 2018/04/24 18:27:02 1.1.1.2 @@ -1,5 +1,5 @@ /* Process declarations and variables for C compiler. - Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Process declarations and symbol lookup for C front end. @@ -49,6 +50,8 @@ extern int current_class_depth; extern tree cleanups_this_call; +extern tree static_ctors, static_dtors; + /* Stack of places to restore the search obstack back to. */ /* Obstack used for remembering local class declarations (like @@ -93,6 +96,14 @@ static struct stack_level *decl_stack; #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) #endif +#ifndef BOOL_TYPE_SIZE +#ifdef SLOW_BYTE_ACCESS +#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (BITS_PER_WORD) : (BITS_PER_UNIT)) +#else +#define BOOL_TYPE_SIZE BITS_PER_UNIT +#endif +#endif + /* We let tm.h override the types used here, to handle trivial differences such as the choice of unsigned int or long unsigned int for size_t. When machines start needing nontrivial differences in the size type, @@ -111,17 +122,6 @@ static struct stack_level *decl_stack; #define WCHAR_TYPE "int" #endif -#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ - define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME) -#define auto_function(NAME, TYPE, CODE) \ - do { \ - tree __name = NAME; \ - tree __type = TYPE; \ - define_function (IDENTIFIER_POINTER (__name), __type, CODE, \ - (void (*)())push_overloaded_decl_1, \ - IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\ - } while (0) - static tree grokparms PROTO((tree, int)); static tree lookup_nested_type PROTO((tree, tree)); static char *redeclaration_error_message PROTO((tree, tree)); @@ -207,7 +207,7 @@ tree int_array_type_node; tree wchar_array_type_node; /* The bool data type, and constants */ -tree bool_type_node, true_node, false_node; +tree boolean_type_node, boolean_true_node, boolean_false_node; /* type `int ()' -- used for implicit declaration of functions. */ @@ -234,11 +234,27 @@ tree int_ftype_cptr_cptr_sizet; /* C++ extensions */ tree vtable_entry_type; tree delta_type_node; -tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node; +#if 0 +/* Old rtti stuff. */ +tree __baselist_desc_type_node; +tree __i_desc_type_node, __m_desc_type_node; tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type; +#endif +tree __t_desc_type_node, __tp_desc_type_node; +tree __access_mode_type_node; +tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node; +tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node; +tree __ptmf_desc_type_node, __ptmd_desc_type_node; +#if 0 +/* Not needed yet? May be needed one day? */ +tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type; +tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type; +tree __ptmf_desc_array_type, __ptmd_desc_array_type; +#endif + tree class_star_type_node; tree class_type_node, record_type_node, union_type_node, enum_type_node; -tree exception_type_node, unknown_type_node; +tree unknown_type_node; tree opaque_type_node, signature_type_node; tree sigtable_entry_type; tree maybe_gc_cleanup; @@ -271,15 +287,16 @@ extern rtx cleanup_label, return_label; rtx original_result_rtx; /* Sequence of insns which represents base initialization. */ -rtx base_init_insns; +tree base_init_expr; /* C++: Keep these around to reduce calls to `get_identifier'. Identifiers for `this' in member functions and the auto-delete parameter for destructors. */ tree this_identifier, in_charge_identifier; -/* Used in pointer to member functions, and in vtables. */ +/* Used in pointer to member functions, in vtables, and in sigtables. */ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier; -tree pfn_or_delta2_identifier; +tree pfn_or_delta2_identifier, tag_identifier; +tree vb_off_identifier, vt_off_identifier; /* A list (chain of TREE_LIST nodes) of named label uses. The TREE_PURPOSE field is the list of variables defined @@ -391,10 +408,6 @@ tree current_function_return_value; static int warn_about_return_type; -/* Nonzero when starting a function declared `extern inline'. */ - -static int current_extern_inline; - /* Nonzero means give `double' the same size as `float'. */ extern int flag_short_double; @@ -408,7 +421,8 @@ extern int flag_no_builtin; extern int flag_no_nonansi_builtin; -/* Nonzero means disable GNU extensions. */ +/* Nonzero means enable obscure ANSI features and disable GNU extensions + that might cause ANSI-compliant code to be miscompiled. */ extern int flag_ansi; @@ -418,7 +432,7 @@ extern int flag_huge_objects; /* Nonzero if we want to conserve space in the .o files. We do this by putting uninitialized data and runtime initialized data into - .common instead of .data at the expense of not flaging multiple + .common instead of .data at the expense of not flagging multiple definitions. */ extern int flag_conserve_space; @@ -534,9 +548,14 @@ struct binding_level /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; - /* Number of decls in `names' that have incomplete + /* List of decls in `names' that have incomplete structure or union types. */ - unsigned short n_incomplete; + tree incomplete; + + /* List of VAR_DECLS saved from a previous for statement. + These would be dead in ANSI-conforming code, but might + be referenced in traditional code. */ + tree dead_vars_from_for; /* 1 for the level that holds the parameters of a function. 2 for the level that holds a class declaration. @@ -566,7 +585,13 @@ struct binding_level unfortunately.) */ unsigned pseudo_global : 1; - /* Two bits left for this word. */ + /* This is set for a namespace binding level. */ + unsigned namespace_p : 1; + + /* True if this level is that of a for-statement. */ + unsigned is_for_scope : 1; + + /* One bit left for this word. */ #if defined(DEBUG_CP_BINDING_LEVELS) /* Binding depth at which this level began. */ @@ -701,6 +726,90 @@ pop_binding_level () current_binding_level = current_binding_level->level_chain; } } + +static void +suspend_binding_level () +{ + if (class_binding_level) + current_binding_level = class_binding_level; + + if (global_binding_level) + { + /* cannot suspend a level, if there are none left to suspend. */ + if (current_binding_level == global_binding_level) + my_friendly_abort (123); + } + /* Suspend the current level. */ +#if defined(DEBUG_CP_BINDING_LEVELS) + binding_depth--; + indent (); + fprintf (stderr, "suspend %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", + current_binding_level, lineno); + if (is_class_level != (current_binding_level == class_binding_level)) +#if 0 /* XXX Don't abort when we're watching how things are being managed. */ + abort (); +#else + { + indent (); + fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); + } +#endif + is_class_level = 0; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + { + register struct binding_level *level = current_binding_level; + current_binding_level = current_binding_level->level_chain; +#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */ + if (level->binding_depth != binding_depth) + abort (); +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + + class_binding_level = current_binding_level; + if (class_binding_level->parm_flag != 2) + class_binding_level = 0; + while (current_binding_level->parm_flag == 2) + current_binding_level = current_binding_level->level_chain; + } +} + +void +resume_binding_level (b) + struct binding_level *b; +{ + if (class_binding_level) + { +#if 1 + /* These are here because we cannot deal with shadows yet. */ + sorry ("cannot resume a namespace inside class"); + return; +#else + b->level_chain = class_binding_level; + class_binding_level = (struct binding_level *)0; +#endif + } + else + { +#if 1 + /* These are here because we cannot deal with shadows yet. */ + if (b->level_chain != current_binding_level) + { + sorry ("cannot resume a namespace inside a different namespace"); + return; + } +#endif + b->level_chain = current_binding_level; + } + current_binding_level = b; +#if defined(DEBUG_CP_BINDING_LEVELS) + b->binding_depth = binding_depth; + indent (); + fprintf (stderr, "resume %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", b, lineno); + is_class_level = 0; + binding_depth++; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ +} /* Nonzero if we are currently in the global binding level. */ @@ -710,6 +819,33 @@ global_bindings_p () return current_binding_level == global_binding_level; } +/* Nonzero if we are currently in a toplevel binding level. This + means either the global binding level or a namespace in a toplevel + binding level. */ + +int +toplevel_bindings_p () +{ + struct binding_level *b = current_binding_level; + + while (1) + { + if (b == global_binding_level) + return 1; + if (! b->namespace_p) + return 0; + b=b->level_chain; + } +} + +/* Nonzero if this is a namespace scope. */ + +int +namespace_bindings_p () +{ + return current_binding_level->namespace_p; +} + void keep_next_level () { @@ -754,6 +890,12 @@ declare_pseudo_global_level () current_binding_level->pseudo_global = 1; } +void +declare_namespace_level () +{ + current_binding_level->namespace_p = 1; +} + int pseudo_global_level_p () { @@ -805,6 +947,12 @@ pushlevel (tag_transparent) keep_next_level_flag = 0; } +int +note_level_for_for () +{ + current_binding_level->is_for_scope = 1; +} + void pushlevel_temporary (tag_transparent) int tag_transparent; @@ -916,7 +1064,8 @@ poplevel (keep, reverse, functionbody) if (TREE_CODE (decl) == FUNCTION_DECL && ! TREE_ASM_WRITTEN (decl) && DECL_INITIAL (decl) != NULL_TREE - && TREE_ADDRESSABLE (decl)) + && TREE_ADDRESSABLE (decl) + && decl_function_context (decl) == current_function_decl) { /* If this decl was copied from a file-scope decl on account of a block-scope extern decl, @@ -962,28 +1111,81 @@ poplevel (keep, reverse, functionbody) /* Clear out the meanings of the local variables of this level. */ - for (link = decls; link; link = TREE_CHAIN (link)) + for (link = current_binding_level->dead_vars_from_for; + link != NULL_TREE; link = TREE_CHAIN (link)) { - if (DECL_NAME (link) != NULL_TREE) + if (DECL_DEAD_FOR_LOCAL (link)) { - /* If the ident. was used or addressed via a local extern decl, - don't forget that fact. */ - if (DECL_EXTERNAL (link)) + tree id = DECL_NAME (link); + if (IDENTIFIER_LOCAL_VALUE (id) == link) + IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); + } + } + + if (current_binding_level->is_for_scope && flag_new_for_scope == 1) + { + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (TREE_CODE (link) == VAR_DECL) + DECL_DEAD_FOR_LOCAL (link) = 1; + } + } + else + { + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != NULL_TREE) { - if (TREE_USED (link)) - TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1; - if (TREE_ADDRESSABLE (link)) - TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; + /* If the ident. was used or addressed via a local extern decl, + don't forget that fact. */ + if (DECL_EXTERNAL (link)) + { + if (TREE_USED (link)) + TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1; + if (TREE_ADDRESSABLE (link)) + TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; + } + IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } - IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } } /* Restore all name-meanings of the outer levels that were shadowed by this level. */ - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + if (current_binding_level->is_for_scope && flag_new_for_scope == 1) + { + struct binding_level *outer = current_binding_level->level_chain; + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + { + tree id = TREE_PURPOSE (link); + tree decl = IDENTIFIER_LOCAL_VALUE (id); + if (DECL_DEAD_FOR_LOCAL (decl)) + DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); + else + IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link); + } + + /* Save declarations made in a 'for' statement so we can support pre-ANSI + 'for' scoping semantics. */ + + /* We append the current names of for-variables to those from previous + declarations, so that when we get around to do an poplevel + on the OUTER level, we restore the any shadowed readl bindings. + Note that the new names are put first on the combined list, + so they get to be restored first. This is important if there are + two for-loops using the same for-variable in the same block. + The binding we really want restored is whatever binding was shadowed + by the *first* for-variable, not the binding shadowed by the + second for-variable (which would be the first for-variable). */ + outer->dead_vars_from_for + = chainon (current_binding_level->names, outer->dead_vars_from_for); + } + else + { + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + } for (link = current_binding_level->class_shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); @@ -1097,6 +1299,31 @@ poplevel (keep, reverse, functionbody) return block; } +/* Resume a binding level for a namespace. */ +void +resume_level (b) + struct binding_level *b; +{ + tree decls, link; + + resume_binding_level (b); + + /* Resume the variable caches. */ + decls = current_binding_level->names; + + /* Restore the meanings of the local variables of this level. */ + + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != NULL_TREE) + IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link; + + /* If this is a TYPE_DECL, push it into the type value slot. */ + if (TREE_CODE (link) == TYPE_DECL) + SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (link), TREE_TYPE (link)); + } +} + /* Delete the node BLOCK from the current binding level. This is used for the block inside a stmt expr ({...}) so that the block can be reinserted where appropriate. */ @@ -1210,9 +1437,9 @@ poplevel_class (force) for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); /* If we're leaving a toplevel class, don't bother to do the setting - of IDENTIFER_CLASS_VALUE to NULL_TREE, since first of all this slot + of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot shouldn't even be used when current_class_type isn't set, and second, - if we don't touch it here, we're able to use the caching effect if the + if we don't touch it here, we're able to use the cache effect if the next time we're entering a class scope, it is the same class. */ if (current_class_depth != 1 || force) for (shadowed = level->class_shadowed; @@ -1261,7 +1488,7 @@ print_binding_level (lvl) fprintf (stderr, " blocks="); fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", - lvl->n_incomplete, lvl->parm_flag, lvl->keep); + list_length (lvl->incomplete), lvl->parm_flag, lvl->keep); if (lvl->tag_transparent) fprintf (stderr, " tag-transparent"); if (lvl->more_cleanups_ok) @@ -1415,6 +1642,150 @@ print_binding_stack () fprintf (stderr, "global:\n"); print_binding_level (global_binding_level); } + +extern char * first_global_object_name; + +/* Get a unique name for each call to this routine for unnamed namespaces. + Mostly copied from get_file_function_name. */ +static tree +get_unique_name () +{ + static int temp_name_counter = 0; + char *buf; + register char *p; + + if (first_global_object_name) + p = first_global_object_name; + else if (main_input_filename) + p = main_input_filename; + else + p = input_filename; + +#define UNNAMED_NAMESPACE_FORMAT "__%s_%d" + + buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p)); + + sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++); + + /* Don't need to pull weird characters out of global names. */ + if (p != first_global_object_name) + { + for (p = buf+11; *p; p++) + if (! ((*p >= '0' && *p <= '9') +#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */ +#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */ + || *p == '.' +#endif +#endif +#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */ + || *p == '$' +#endif +#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */ + || *p == '.' +#endif + || (*p >= 'A' && *p <= 'Z') + || (*p >= 'a' && *p <= 'z'))) + *p = '_'; + } + + return get_identifier (buf); +} + +/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we + select a name that is unique to this compilation unit. */ +void +push_namespace (name) + tree name; +{ + extern tree current_namespace; + tree old_id = get_namespace_id (); + char *buf; + tree d = make_node (NAMESPACE_DECL); + + if (! name) + { + /* Create a truly ugly name! */ + name = get_unique_name (); + } + + DECL_NAME (d) = name; + DECL_ASSEMBLER_NAME (d) = name; + /* pushdecl wants to check the size of it to see if it is incomplete... */ + TREE_TYPE (d) = void_type_node; + /* Mark them as external, so redeclaration_error_message doesn't think + they are duplicates. */ + DECL_EXTERNAL (d) = 1; + d = pushdecl (d); + + if (NAMESPACE_LEVEL (d) == 0) + { + /* This is new for this compilation unit. */ + pushlevel (0); + declare_namespace_level (); + NAMESPACE_LEVEL (d) = (tree)current_binding_level; + } + else + { + resume_level ((struct binding_level*)NAMESPACE_LEVEL (d)); + } + + /* This code is just is bit old now... */ + current_namespace = tree_cons (NULL_TREE, name, current_namespace); + buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0) + + IDENTIFIER_LENGTH (name)); + sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "", + IDENTIFIER_POINTER (name)); + TREE_PURPOSE (current_namespace) = get_identifier (buf); +} + +/* Pop from the scope of the current namespace. */ +void +pop_namespace () +{ + extern tree current_namespace; + tree decls, link; + current_namespace = TREE_CHAIN (current_namespace); + + /* Just in case we get out of sync. */ + if (! namespace_bindings_p ()) + poplevel (0, 0, 0); + + decls = current_binding_level->names; + + /* Clear out the meanings of the local variables of this level. */ + + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != NULL_TREE) + { + /* If the ident. was used or addressed via a local extern decl, + don't forget that fact. */ + if (DECL_EXTERNAL (link)) + { + if (TREE_USED (link)) + TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1; + if (TREE_ADDRESSABLE (link)) + TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; + } + IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; + } + } + + /* Restore all name-meanings of the outer levels + that were shadowed by this level. */ + + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->class_shadowed; + link; link = TREE_CHAIN (link)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->type_shadowed; + link; link = TREE_CHAIN (link)) + IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + + /* suspend a level. */ + suspend_binding_level (); +} /* Subroutines for reverting temporarily to top-level for instantiation of templates and such. We actually need to clear out the class- and @@ -1425,7 +1796,8 @@ struct saved_scope { struct binding_level *old_binding_level; tree old_bindings; struct saved_scope *prev; - tree class_name, class_type, class_decl, function_decl; + tree class_name, class_type, 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; @@ -1500,8 +1872,9 @@ push_to_top_level () s->class_name = current_class_name; 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; @@ -1509,7 +1882,7 @@ push_to_top_level () 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_class_name = current_class_type = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; previous_class_type = NULL_TREE; @@ -1549,11 +1922,8 @@ pop_from_top_level () } current_class_name = s->class_name; current_class_type = s->class_type; - current_class_decl = s->class_decl; - if (current_class_type) - 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; @@ -1617,38 +1987,58 @@ static void set_nested_typename (decl, classname, name, type) tree decl, classname, name, type; { + char *buf; my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136); - if (classname != NULL_TREE) - { - char *buf; - my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137); - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138); - buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname) - + IDENTIFIER_LENGTH (name)); - sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname), - IDENTIFIER_POINTER (name)); - DECL_NESTED_TYPENAME (decl) = get_identifier (buf); - TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1; - /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no - correspondence in any binding_level. This is ok since the - DECL_NESTED_TYPENAME is just a convenience identifier whose - IDENTIFIER_TYPE_VALUE will remain constant from now on. */ - SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type); + /* No need to do this for anonymous names, since they're unique. */ + if (ANON_AGGRNAME_P (name)) + { + DECL_NESTED_TYPENAME (decl) = name; + return; } - else - DECL_NESTED_TYPENAME (decl) = name; + + if (classname == NULL_TREE) + classname = get_identifier (""); + + my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138); + buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname) + + IDENTIFIER_LENGTH (name)); + sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname), + IDENTIFIER_POINTER (name)); + DECL_NESTED_TYPENAME (decl) = get_identifier (buf); + TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1; + + /* Create an extra decl so that the nested name will have a type value + where appropriate. */ + { + tree nested, type_decl; + nested = DECL_NESTED_TYPENAME (decl); + type_decl = build_decl (TYPE_DECL, nested, type); + DECL_NESTED_TYPENAME (type_decl) = nested; + SET_DECL_ARTIFICIAL (type_decl); + /* Mark the TYPE_DECL node created just above as a gratuitous one so that + dwarfout.c will know not to generate a TAG_typedef DIE for it, and + sdbout.c won't try to output a .def for "::foo". */ + DECL_IGNORED_P (type_decl) = 1; + + /* Remove this when local classes are fixed. */ + SET_IDENTIFIER_TYPE_VALUE (nested, type); + + pushdecl_nonclass_level (type_decl); + } } -/* Pop off extraneous binding levels left over due to syntax errors. */ +/* Pop off extraneous binding levels left over due to syntax errors. + + We don't pop past namespaces, as they might be valid. */ void pop_everything () { #ifdef DEBUG_CP_BINDING_LEVELS fprintf (stderr, "XXX entering pop_everything ()\n"); #endif - while (current_binding_level != global_binding_level - && ! current_binding_level->pseudo_global) + while (! toplevel_bindings_p () && ! pseudo_global_level_p ()) { if (class_binding_level) pop_nested_class (1); @@ -1692,7 +2082,7 @@ make_type_decl (name, type) #endif /* Push a tag name NAME for struct/class/union/enum type TYPE. - Normally put into into the inner-most non-tag-tranparent scope, + Normally put into into the inner-most non-tag-transparent scope, but if GLOBALIZE is true, put it in the inner-most non-class scope. The latter is needed for implicit declarations. */ @@ -1710,7 +2100,7 @@ pushtag (name, type, globalize) || (globalize && b->parm_flag == 2)) b = b->level_chain; - if (b == global_binding_level) + if (toplevel_bindings_p ()) b->tags = perm_tree_cons (name, type, b->tags); else b->tags = saveable_tree_cons (name, type, b->tags); @@ -1722,17 +2112,16 @@ pushtag (name, type, globalize) context = current_scope (); if (context) c_decl = TREE_CODE (context) == FUNCTION_DECL - ? context : TYPE_NAME (context); + ? context : TYPE_MAIN_DECL (context); +#if 0 /* Record the identifier as the type's name if it has none. */ if (TYPE_NAME (type) == NULL_TREE) TYPE_NAME (type) = name; +#endif /* Do C++ gratuitous typedefing. */ - if (IDENTIFIER_TYPE_VALUE (name) != type - && (TREE_CODE (type) != RECORD_TYPE - || b->parm_flag != 2 - || !CLASSTYPE_DECLARED_EXCEPTION (type))) + if (IDENTIFIER_TYPE_VALUE (name) != type) { register tree d; int newdecl = 0; @@ -1749,6 +2138,7 @@ pushtag (name, type, globalize) d = make_type_decl (name, type); #else d = build_decl (TYPE_DECL, name, type); + DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d)); #endif SET_DECL_ARTIFICIAL (d); #ifdef DWARF_DEBUGGING_INFO @@ -1766,14 +2156,11 @@ pushtag (name, type, globalize) else d = TYPE_NAME (d); + TYPE_NAME (type) = d; + /* If it is anonymous, then we are called from pushdecl, - and we don't want to infinitely recurse. Also, if the - name is already in scope, we don't want to push it - again--pushdecl is only for pushing new decls. */ - if (! ANON_AGGRNAME_P (name) - && TYPE_NAME (type) - && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL - || lookup_name (name, 1) != TYPE_NAME (type))) + and we don't want to infinitely recurse. */ + if (! ANON_AGGRNAME_P (name)) { if (b->parm_flag == 2) d = pushdecl_class_level (d); @@ -1797,6 +2184,9 @@ pushtag (name, type, globalize) DECL_IGNORED_P (d) = 1; } #endif /* DWARF_DEBUGGING_INFO */ + + TYPE_MAIN_DECL (type) = d; + /* Make sure we're in this type's scope when we push the decl for a template, otherwise class_binding_level will be NULL and we'll end up dying inside of @@ -1807,38 +2197,31 @@ pushtag (name, type, globalize) if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) popclass (0); } - if (write_symbols != DWARF_DEBUG) + if (newdecl) { - if (ANON_AGGRNAME_P (name)) - DECL_IGNORED_P (d) = 1; - } - TYPE_NAME (type) = d; + if (write_symbols != DWARF_DEBUG) + { + if (ANON_AGGRNAME_P (name)) + DECL_IGNORED_P (d) = 1; + } + + if (context == NULL_TREE) + /* Non-nested class. */ + set_nested_typename (d, NULL_TREE, name, type); + else if (context && TREE_CODE (context) == FUNCTION_DECL) + /* Function-nested class. */ + set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), + name, type); + else /* if (context && IS_AGGR_TYPE (context)) */ + /* Class-nested class. */ + set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), + name, type); - if (context == NULL_TREE) - /* Non-nested class. */ - DECL_NESTED_TYPENAME (d) = name; - else if (context && TREE_CODE (context) == FUNCTION_DECL) - { - /* Function-nested class. */ - set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), - name, type); - /* This builds the links for classes nested in fn scope. */ - DECL_CONTEXT (d) = context; - } -/* else if (TYPE_SIZE (current_class_type) == NULL_TREE) -*/ - else if (context && IS_AGGR_TYPE (context)) - { - /* Class-nested class. */ - set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), - name, type); - /* This builds the links for classes nested in type scope. */ DECL_CONTEXT (d) = context; + TYPE_CONTEXT (type) = DECL_CONTEXT (d); + DECL_ASSEMBLER_NAME (d) + = get_identifier (build_overload_name (type, 1, 1)); } - TYPE_CONTEXT (type) = DECL_CONTEXT (d); - if (newdecl) - DECL_ASSEMBLER_NAME (d) - = get_identifier (build_overload_name (type, 1, 1)); } if (b->parm_flag == 2) { @@ -1920,7 +2303,7 @@ clear_anon_tags () For C++, we must compare the parameter list so that `int' can match `int&' in a parameter position, but `int&' is not confused with `const int&'. */ -static int +int decls_match (newdecl, olddecl) tree newdecl, olddecl; { @@ -2049,13 +2432,11 @@ warn_extern_redeclared_static (newdecl, = "`%D' was declared implicitly `extern' and later `static'"; if (flag_traditional - || TREE_CODE (newdecl) == TYPE_DECL - || (! warn_extern_inline - && DECL_INLINE (newdecl))) + || TREE_CODE (newdecl) == TYPE_DECL) return; name = DECL_ASSEMBLER_NAME (newdecl); - if (TREE_PUBLIC (name) && ! TREE_PUBLIC (newdecl)) + if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl)) { /* It's okay to redeclare an ANSI built-in function as static, or to declare a non-ANSI built-in function as anything. */ @@ -2065,11 +2446,11 @@ warn_extern_redeclared_static (newdecl, && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))) { - cp_warning (IDENTIFIER_IMPLICIT_DECL (name) + cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name) ? implicit_extern_static_warning : explicit_extern_static_warning, newdecl); if (olddecl != NULL_TREE) - cp_warning_at ("previous declaration of `%D'", olddecl); + cp_pedwarn_at ("previous declaration of `%D'", olddecl); } } } @@ -2091,6 +2472,9 @@ duplicate_decls (newdecl, olddecl) int new_defines_function; tree previous_c_decl = NULL_TREE; + if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd') + DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl); + types_match = decls_match (newdecl, olddecl); if (TREE_CODE (olddecl) != TREE_LIST) @@ -2119,7 +2503,7 @@ duplicate_decls (newdecl, olddecl) /* If you declare a built-in or predefined function name as static, the old definition is overridden, but optionally warn this was a bad choice of name. Ditto for overloads. */ - if (! TREE_PUBLIC (newdecl) + if (! DECL_PUBLIC (newdecl) || (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))) { @@ -2199,7 +2583,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); @@ -2208,16 +2592,6 @@ duplicate_decls (newdecl, olddecl) return 0; } - if (olddecl == wchar_decl_node) - { - if (pedantic && ! DECL_IN_SYSTEM_HEADER (newdecl)) - cp_pedwarn ("redeclaration of wchar_t as `%T'", - TREE_TYPE (newdecl)); - - /* Throw away the redeclaration. */ - return 1; - } - /* Already complained about this, so don't do so again. */ else if (current_class_type == NULL_TREE || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) @@ -2264,12 +2638,69 @@ duplicate_decls (newdecl, olddecl) } } - /* These bits are logically part of the type. */ - if (pedantic - && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) - || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))) - cp_error_at ("type qualifiers for `%D' conflict with previous decl", - newdecl); + if (TREE_CODE (olddecl) == FUNCTION_DECL) + { + tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); + tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); + int i = 1; + + if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE) + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2); + + for (; t1 && t1 != void_list_node; + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++) + if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) + { + if (1 == simple_cst_equal (TREE_PURPOSE (t1), + TREE_PURPOSE (t2))) + { + if (pedantic) + { + cp_pedwarn ("default argument given for parameter %d of `%#D'", + i, newdecl); + cp_pedwarn_at ("after previous specification in `%#D'", + olddecl); + } + } + else + { + cp_error ("default argument given for parameter %d of `%#D'", + i, newdecl); + cp_error_at ("conflicts with previous specification in `%#D'", + olddecl); + } + } + + if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl)) + { +#if 0 /* I think this will be correct, but it's really annoying. We should + fix the compiler to find vtables by indirection so it isn't + necessary. (jason 8/25/95) */ + if (DECL_VINDEX (olddecl) && ! DECL_ABSTRACT_VIRTUAL_P (olddecl)) + { + cp_pedwarn ("virtual function `%#D' redeclared inline", + newdecl); + cp_pedwarn_at ("previous non-inline declaration here", + olddecl); + } + else +#endif + if (TREE_ADDRESSABLE (olddecl)) + { + cp_pedwarn ("`%#D' was used before it was declared inline", + newdecl); + cp_pedwarn_at ("previous non-inline declaration here", + olddecl); + } + } + } + /* These bits are logically part of the type for non-functions. */ + else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) + || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)) + { + cp_pedwarn ("type qualifiers for `%#D'", newdecl); + cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl); + } } /* If new decl is `static' and an `extern' was seen previously, @@ -2295,6 +2726,9 @@ duplicate_decls (newdecl, olddecl) 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); + DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl); + DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); + DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl); } /* Deal with C++: must preserve virtual function table size. */ @@ -2303,6 +2737,8 @@ duplicate_decls (newdecl, olddecl) register tree newtype = TREE_TYPE (newdecl); register tree oldtype = TREE_TYPE (olddecl); + DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl); + if (newtype != error_mark_node && oldtype != error_mark_node && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype)) { @@ -2337,7 +2773,7 @@ duplicate_decls (newdecl, olddecl) && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))) { cp_warning ("redundant redeclaration of `%D' in same scope", newdecl); - cp_warning ("previous declaration of `%D'", olddecl); + cp_warning_at ("previous declaration of `%D'", olddecl); } /* Copy all the DECL_... slots specified in the new decl @@ -2347,13 +2783,10 @@ duplicate_decls (newdecl, olddecl) { /* Automatically handles default parameters. */ tree oldtype = TREE_TYPE (olddecl); - /* Merge the data types specified in the two decls. */ - tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); + tree newtype; - /* Make sure we put the new type in the same obstack as the old ones. - If the old types are not both in the same obstack, use the permanent - one. */ - if (oldtype && TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype)) + /* Make sure we put the new type in the same obstack as the old one. */ + if (oldtype) push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype)); else { @@ -2361,6 +2794,9 @@ duplicate_decls (newdecl, olddecl) end_temporary_allocation (); } + /* Merge the data types specified in the two decls. */ + newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); + if (TREE_CODE (newdecl) == VAR_DECL) DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); /* Do this after calling `common_type' so that default @@ -2371,14 +2807,14 @@ duplicate_decls (newdecl, olddecl) { tree ctype = NULL_TREE; ctype = DECL_CLASS_CONTEXT (newdecl); - TREE_TYPE (newdecl) = build_exception_variant (ctype, newtype, + TREE_TYPE (newdecl) = build_exception_variant (newtype, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))); - TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype, + TREE_TYPE (olddecl) = build_exception_variant (newtype, TYPE_RAISES_EXCEPTIONS (oldtype)); if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0)) { - cp_error ("declaration of `%D' raises different exceptions...", + cp_error ("declaration of `%D' throws different exceptions...", newdecl); cp_error_at ("...from previous declaration here", olddecl); } @@ -2386,21 +2822,16 @@ duplicate_decls (newdecl, olddecl) TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; /* Lay the type out, unless already done. */ - if (oldtype != TREE_TYPE (newdecl)) - { - if (TREE_TYPE (newdecl) != error_mark_node) - layout_type (TREE_TYPE (newdecl)); - if (TREE_CODE (newdecl) != FUNCTION_DECL - && TREE_CODE (newdecl) != TYPE_DECL - && TREE_CODE (newdecl) != CONST_DECL - && TREE_CODE (newdecl) != TEMPLATE_DECL) - layout_decl (newdecl, 0); - } - else - { - /* Since the type is OLDDECL's, make OLDDECL's size go with. */ - DECL_SIZE (newdecl) = DECL_SIZE (olddecl); - } + if (oldtype != TREE_TYPE (newdecl) + && TREE_TYPE (newdecl) != error_mark_node) + layout_type (TREE_TYPE (newdecl)); + + if (TREE_CODE (newdecl) == VAR_DECL + || TREE_CODE (newdecl) == PARM_DECL + || TREE_CODE (newdecl) == RESULT_DECL + || TREE_CODE (newdecl) == FIELD_DECL + || TREE_CODE (newdecl) == TYPE_DECL) + layout_decl (newdecl, 0); /* Merge the type qualifiers. */ if (TREE_READONLY (newdecl)) @@ -2449,47 +2880,29 @@ duplicate_decls (newdecl, olddecl) } /* Merge the storage class information. */ - if (DECL_EXTERNAL (newdecl)) - { - TREE_STATIC (newdecl) = TREE_STATIC (olddecl); - DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); + DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); + TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl); + if (! DECL_EXTERNAL (olddecl)) + DECL_EXTERNAL (newdecl) = 0; - if (TREE_CODE (newdecl) != FUNCTION_DECL) - TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); - } - else + if (TREE_CODE (newdecl) == FUNCTION_DECL) { - TREE_STATIC (olddecl) = TREE_STATIC (newdecl); - /* A `const' which was not declared `extern' and is - in static storage is invisible. */ - if (TREE_CODE (newdecl) == VAR_DECL - && TREE_READONLY (newdecl) && TREE_STATIC (newdecl) - && ! DECL_THIS_EXTERN (newdecl)) - TREE_PUBLIC (newdecl) = 0; - else if (TREE_CODE (newdecl) != FUNCTION_DECL) - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); + DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl); + DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl); + DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl); } - /* For functions, static overrides non-static. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { - TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); - /* This is since we don't automatically - copy the attributes of NEWDECL into OLDDECL. */ - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - /* If this clears `static', clear it in the identifier too. */ - if (! TREE_PUBLIC (olddecl)) - TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0; - } + DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl); - /* If either decl says `inline', this fn is inline, - unless its definition was passed already. */ - if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE) - DECL_INLINE (olddecl) = 1; - DECL_INLINE (newdecl) = DECL_INLINE (olddecl); + /* If either decl says `inline', this fn is inline, unless its + definition was passed already. */ + if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE) + DECL_INLINE (olddecl) = 1; + DECL_INLINE (newdecl) = DECL_INLINE (olddecl); - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { if (! types_match) { DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); @@ -2526,6 +2939,13 @@ duplicate_decls (newdecl, olddecl) if (DECL_ARGUMENTS (olddecl)) DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); } + if (DECL_LANG_SPECIFIC (olddecl)) + DECL_MAIN_VARIANT (newdecl) = DECL_MAIN_VARIANT (olddecl); + } + + if (TREE_CODE (newdecl) == NAMESPACE_DECL) + { + NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl); } if (TREE_CODE (newdecl) == TEMPLATE_DECL) @@ -2551,6 +2971,7 @@ duplicate_decls (newdecl, olddecl) { DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl); + DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); } if (TREE_CODE (newdecl) == FUNCTION_DECL) @@ -2661,7 +3082,8 @@ pushdecl (x) #else /* Type are looked up using the DECL_NAME, as that is what the rest of the compiler wants to use. */ - if (TREE_CODE (x) == TYPE_DECL) + if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL + || TREE_CODE (x) == NAMESPACE_DECL) name = DECL_NAME (x); #endif @@ -2680,19 +3102,28 @@ pushdecl (x) else if (t != NULL_TREE) { - if (TREE_CODE (t) == PARM_DECL) + file = DECL_SOURCE_FILE (t); + line = DECL_SOURCE_LINE (t); + if (TREE_CODE (x) == VAR_DECL && DECL_DEAD_FOR_LOCAL (x)) + ; /* This is OK. */ + else if (TREE_CODE (t) == PARM_DECL) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); } - file = DECL_SOURCE_FILE (t); - line = DECL_SOURCE_LINE (t); - - if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) + else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) || (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))) && is_overloaded_fn (t)) /* don't do anything just yet */; + else if (t == wchar_decl_node) + { + if (pedantic && ! DECL_IN_SYSTEM_HEADER (x)) + cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x)); + + /* Throw away the redeclaration. */ + return t; + } else if (TREE_CODE (t) != TREE_CODE (x)) { if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)) @@ -2742,6 +3173,8 @@ pushdecl (x) #endif if (TREE_CODE (t) == TYPE_DECL) SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t)); + else if (TREE_CODE (t) == FUNCTION_DECL) + check_default_args (t); return t; } @@ -2775,6 +3208,7 @@ pushdecl (x) { tree tname = DECL_NAME (name); + /* This is a disgusting kludge for dealing with UPTs. */ if (global_bindings_p () && ANON_AGGRNAME_P (tname)) { /* do gratuitous C++ typedefing, and make sure that @@ -2786,9 +3220,11 @@ pushdecl (x) } my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140); - if (DECL_NAME (name) && !DECL_NESTED_TYPENAME (name)) - set_nested_typename (x, current_class_name, - DECL_NAME (name), type); + /* Don't set nested_typename on template type parms, for instance. + Any artificial decls that need DECL_NESTED_TYPENAME will have it + set in pushtag. */ + if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) + set_nested_typename (x, current_class_name, DECL_NAME (x), type); if (type != error_mark_node && TYPE_NAME (type) @@ -2835,22 +3271,16 @@ pushdecl (x) { /* Install a global value. */ - /* Rule for VAR_DECLs, but not for other kinds of _DECLs: - A `const' which was not declared `extern' is invisible. */ - if (TREE_CODE (x) == VAR_DECL - && TREE_READONLY (x) && ! DECL_THIS_EXTERN (x)) - TREE_PUBLIC (x) = 0; - /* If the first global decl has external linkage, warn if we later see static one. */ - if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x)) + if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x)) TREE_PUBLIC (name) = 1; - /* Don't install a TYPE_DECL if we already have another - sort of _DECL with that name. */ + /* Don't install an artificial TYPE_DECL if we already have + another _DECL with that name. */ if (TREE_CODE (x) != TYPE_DECL || t == NULL_TREE - || TREE_CODE (t) == TYPE_DECL) + || ! DECL_ARTIFICIAL (x)) IDENTIFIER_GLOBAL_VALUE (name) = x; /* Don't forget if the function was used via an implicit decl. */ @@ -2882,55 +3312,42 @@ pushdecl (x) tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name); - b->shadowed = tree_cons (name, oldlocal, b->shadowed); - IDENTIFIER_LOCAL_VALUE (name) = x; + /* Don't install an artificial TYPE_DECL if we already have + another _DECL with that name. */ + if (TREE_CODE (x) != TYPE_DECL + || t == NULL_TREE + || ! DECL_ARTIFICIAL (x)) + { + b->shadowed = tree_cons (name, oldlocal, b->shadowed); + IDENTIFIER_LOCAL_VALUE (name) = x; + } /* If this is a TYPE_DECL, push it into the type value slot. */ if (TREE_CODE (x) == TYPE_DECL) set_identifier_type_value_with_scope (name, TREE_TYPE (x), b); + /* Clear out any TYPE_DECL shadowed by a namespace so that + we won't think this is a type. The C struct hack doesn't + go through namespaces. */ + if (TREE_CODE (x) == NAMESPACE_DECL) + set_identifier_type_value_with_scope (name, NULL_TREE, b); + /* If this is an extern function declaration, see if we have a global definition or declaration for the function. */ if (oldlocal == NULL_TREE - && DECL_EXTERNAL (x) && !DECL_INLINE (x) + && DECL_EXTERNAL (x) && oldglobal != NULL_TREE && TREE_CODE (x) == FUNCTION_DECL && TREE_CODE (oldglobal) == FUNCTION_DECL) { /* We have one. Their types must agree. */ - if (! comptypes (TREE_TYPE (x), TREE_TYPE (oldglobal), 1)) + if (decls_match (x, oldglobal)) + /* OK */; + else { cp_warning ("extern declaration of `%#D' doesn't match", x); cp_warning_at ("global declaration `%#D'", oldglobal); } - else - { - /* Inner extern decl is inline if global one is. - Copy enough to really inline it. */ - if (DECL_INLINE (oldglobal)) - { - DECL_INLINE (x) = DECL_INLINE (oldglobal); - DECL_INITIAL (x) = (current_function_decl == oldglobal - ? NULL_TREE : DECL_INITIAL (oldglobal)); - DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); - DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal); - DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); - DECL_RESULT (x) = DECL_RESULT (oldglobal); - TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal); - DECL_ABSTRACT_ORIGIN (x) = oldglobal; - } - /* Inner extern decl is built-in if global one is. */ - if (DECL_BUILT_IN (oldglobal)) - { - DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal); - DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal); - } - /* Keep the arg types from a file-scope fcn defn. */ - if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != NULL_TREE - && DECL_INITIAL (oldglobal) - && TYPE_ARG_TYPES (TREE_TYPE (x)) == NULL_TREE) - TREE_TYPE (x) = TREE_TYPE (oldglobal); - } } /* If we have a local external declaration, and no file-scope declaration has yet been seen, @@ -2962,6 +3379,13 @@ pushdecl (x) if (b->parm_flag == 1) cp_error ("declaration of `%#D' shadows a parameter", name); } + else if (oldlocal != NULL_TREE && b->is_for_scope + && !DECL_DEAD_FOR_LOCAL (oldlocal)) + { + warning ("variable `%s' shadows local", + IDENTIFIER_POINTER (name)); + cp_warning_at (" this is the shadowed declaration", oldlocal); + } /* Maybe warn if shadowing something else. */ else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ @@ -2974,6 +3398,7 @@ pushdecl (x) if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) warnstring = "declaration of `%s' shadows a parameter"; else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE + && current_class_decl && !TREE_STATIC (name)) warnstring = "declaration of `%s' shadows a member of `this'"; else if (oldlocal != NULL_TREE) @@ -2984,31 +3409,20 @@ pushdecl (x) if (warnstring) warning (warnstring, IDENTIFIER_POINTER (name)); } - - /* If storing a local value, there may already be one (inherited). - If so, record it for restoration when this binding level ends. */ - if (oldlocal != NULL_TREE) - b->shadowed = tree_cons (name, oldlocal, b->shadowed); } - /* Keep count of variables in this level with incomplete type. */ - if (TREE_CODE (x) != TEMPLATE_DECL - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE - && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE)) - { - if (++b->n_incomplete == 0) - error ("too many incomplete variables at this point"); - } - } + if (TREE_CODE (x) == FUNCTION_DECL) + check_default_args (x); - if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE) - { - if (current_class_name) - { - if (! TREE_MANGLED (name)) - set_nested_typename (x, current_class_name, DECL_NAME (x), - TREE_TYPE (x)); - } + /* Keep count of variables in this level with incomplete type. */ + if (TREE_CODE (x) == VAR_DECL + && TREE_TYPE (x) != error_mark_node + && ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE + && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE)) + /* RTTI TD entries are created while defining the type_info. */ + || (TYPE_LANG_SPECIFIC (TREE_TYPE (x)) + && TYPE_BEING_DEFINED (TREE_TYPE (x))))) + b->incomplete = tree_cons (NULL_TREE, x, b->incomplete); } /* Put decls on list in reverse order. @@ -3135,7 +3549,11 @@ pushdecl_class_level (x) if (TREE_CODE (x) == TYPE_DECL) { set_identifier_type_value (name, TREE_TYPE (x)); - if (!DECL_NESTED_TYPENAME (x)) + + /* Don't set nested_typename on template type parms, for instance. + Any artificial decls that need DECL_NESTED_TYPENAME will have it + set in pushtag. */ + if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) set_nested_typename (x, current_class_name, name, TREE_TYPE (x)); } } @@ -3174,6 +3592,10 @@ push_class_level_binding (name, x) tree name; tree x; { + if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x) + && purpose_member (name, class_binding_level->class_shadowed)) + return; + maybe_push_cache_obstack (); class_binding_level->class_shadowed = tree_cons (name, IDENTIFIER_CLASS_VALUE (name), @@ -3257,13 +3679,7 @@ push_overloaded_decl (decl, forgettable) old = TREE_OPERAND (old, 0); else #endif - if (TREE_CODE (old) == VAR_DECL) - { - cp_error_at ("previous non-function declaration `%#D'", old); - cp_error ("conflicts with function declaration `%#D'", decl); - return error_mark_node; - } - else if (TREE_CODE (old) == TYPE_DECL) + if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old)) { tree t = TREE_TYPE (old); if (IS_AGGR_TYPE (t) && warn_shadow) @@ -3278,6 +3694,12 @@ push_overloaded_decl (decl, forgettable) if (decl == tmp || duplicate_decls (decl, tmp)) return tmp; } + else + { + cp_error_at ("previous non-function declaration `%#D'", old); + cp_error ("conflicts with function declaration `%#D'", decl); + return decl; + } } if (old || TREE_CODE (decl) == TEMPLATE_DECL) @@ -3316,8 +3738,7 @@ implicitly_declare (functionid) /* Save the decl permanently so we can warn if definition follows. In ANSI C, warn_implicit is usually false, so the saves little space. But in C++, it's usually true, hence the extra code. */ - if (temp && (flag_traditional || !warn_implicit - || current_binding_level == global_binding_level)) + if (temp && (flag_traditional || !warn_implicit || toplevel_bindings_p ())) end_temporary_allocation (); /* We used to reuse an old implicit decl here, @@ -3376,34 +3797,18 @@ redeclaration_error_message (newdecl, ol if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl)) return 0; - /* Declarations of functions can insist on internal linkage - but they can't be inconsistent with internal linkage, - so there can be no error on that account. - However defining the same name twice is no good. */ + /* We'll complain about linkage mismatches in + warn_extern_redeclared_static. */ + + /* defining the same name twice is no good. */ if (DECL_INITIAL (olddecl) != NULL_TREE - && DECL_INITIAL (newdecl) != NULL_TREE - /* However, defining once as extern inline and a second - time in another way is ok. */ - && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl) - && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) + && DECL_INITIAL (newdecl) != NULL_TREE) { if (DECL_NAME (olddecl) == NULL_TREE) return "`%#D' not declared in class"; else return "redefinition of `%#D'"; } - - { - tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); - tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); - - if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE) - t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2); - - for (; t1; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) - if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) - return "duplicate default arguments given for `%#D'"; - } return 0; } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) @@ -3418,10 +3823,6 @@ redeclaration_error_message (newdecl, ol /* If at least one is a reference, it's ok. */ if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) return 0; - /* 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 `%#D'"; /* Reject two definitions. */ return "redefinition of `%#D'"; } @@ -3542,6 +3943,9 @@ define_label (filename, line, name) decl = lookup_label (name); } + if (name == get_identifier ("wchar_t")) + cp_pedwarn ("label named wchar_t"); + if (DECL_INITIAL (decl) != NULL_TREE) { cp_error ("duplicate label `%D'", decl); @@ -3550,6 +3954,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; @@ -3580,10 +3985,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); } @@ -3602,6 +4008,30 @@ define_label (filename, line, name) } } +struct cp_switch +{ + struct binding_level *level; + struct cp_switch *next; +}; + +static struct cp_switch *switch_stack; + +void +push_switch () +{ + struct cp_switch *p + = (struct cp_switch *) oballoc (sizeof (struct cp_switch)); + p->level = current_binding_level; + p->next = switch_stack; + switch_stack = p; +} + +void +pop_switch () +{ + switch_stack = switch_stack->next; +} + /* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */ /* XXX Note decl is never actually used. (bpk) */ void @@ -3609,19 +4039,46 @@ define_case_label (decl) tree decl; { tree cleanup = last_cleanup_this_contour (); + struct binding_level *b = current_binding_level; + int identified = 0; + if (cleanup) { static int explained = 0; - cp_error_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup)); - error ("where case label appears here"); + cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup)); + warning ("where case label appears here"); if (!explained) { - error ("(enclose actions of previous case statements requiring"); - error ("destructors in their own binding contours.)"); + warning ("(enclose actions of previous case statements requiring"); + warning ("destructors in their own binding contours.)"); explained = 1; } } + for (; b && b != switch_stack->level; b = b->level_chain) + { + tree new_decls = b->names; + for (; new_decls; new_decls = TREE_CHAIN (new_decls)) + { + if (TREE_CODE (new_decls) == VAR_DECL + /* Don't complain about crossing initialization + of internal entities. They can't be accessed, + and they should be cleaned up + by the time we get to the label. */ + && ! DECL_ARTIFICIAL (new_decls) + && ((DECL_INITIAL (new_decls) != NULL_TREE + && DECL_INITIAL (new_decls) != error_mark_node) + || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))) + { + if (! identified) + error ("jump to case label"); + identified = 1; + cp_error_at (" crosses initialization of `%#D'", + new_decls); + } + } + } + /* After labels, make any new cleanups go into their own new (temporary) binding contour. */ @@ -3873,9 +4330,9 @@ lookup_nested_type (type, context) } break; case FUNCTION_DECL: - return TYPE_IDENTIFIER (type) ? - lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE; - break; + if (TYPE_NAME (type) && TYPE_IDENTIFIER (type)) + return lookup_name (TYPE_IDENTIFIER (type), 1); + return NULL_TREE; default: my_friendly_abort (12); } @@ -3883,6 +4340,25 @@ lookup_nested_type (type, context) return NULL_TREE; } +/* Look up NAME in the NAMESPACE. */ +tree +lookup_namespace_name (namespace, name) + tree namespace, name; +{ + struct binding_level *b = (struct binding_level *)NAMESPACE_LEVEL (namespace); + tree x; + + for (x = NULL_TREE; b && !x; b = b->level_chain) + { + for (x = b->names; x; x = TREE_CHAIN (x)) + if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name) + break; + /* Must find directly in the namespace. */ + break; + } + return x; +} + /* Look up NAME in the current binding level and its superiors in the namespace of variables, functions and typedefs. Return a ..._DECL node of some kind representing its definition if there is only one @@ -3900,43 +4376,54 @@ lookup_name_real (name, prefer_type, non { register tree val; int yylex = 0; + tree from_obj = NULL_TREE; if (prefer_type == -2) { extern int looking_for_typename; + tree type; yylex = 1; prefer_type = looking_for_typename; + + if (got_scope) + type = got_scope; + else if (got_object != error_mark_node) + type = got_object; - if (got_scope != NULL_TREE) + if (type) { - if (got_scope == error_mark_node) + if (type == error_mark_node) return error_mark_node; - else if (got_scope == void_type_node) + else if (type == void_type_node) val = IDENTIFIER_GLOBAL_VALUE (name); - else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM + else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM /* TFIXME -- don't do this for UPTs in new model. */ - || TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE) + || TREE_CODE (type) == UNINSTANTIATED_P_TYPE) { if (prefer_type > 0) - val = create_nested_upt (got_scope, name); + val = create_nested_upt (type, name); else val = NULL_TREE; } - else if (! IS_AGGR_TYPE (got_scope)) + else if (TREE_CODE (type) == NAMESPACE_DECL) + { + val = lookup_namespace_name (type, name); + } + else if (! IS_AGGR_TYPE (type)) /* Someone else will give an error about this if needed. */ val = NULL_TREE; - else if (TYPE_BEING_DEFINED (got_scope)) + else if (TYPE_BEING_DEFINED (type)) { val = IDENTIFIER_CLASS_VALUE (name); - if (val && DECL_CONTEXT (val) != got_scope) + if (val && DECL_CONTEXT (val) != type) { struct binding_level *b = class_binding_level; for (val = NULL_TREE; b; b = b->level_chain) { tree t = purpose_member (name, b->class_shadowed); if (t && TREE_VALUE (t) - && DECL_CONTEXT (TREE_VALUE (t)) == got_scope) + && DECL_CONTEXT (TREE_VALUE (t)) == type) { val = TREE_VALUE (t); break; @@ -3944,16 +4431,23 @@ lookup_name_real (name, prefer_type, non } } if (val == NULL_TREE - && CLASSTYPE_LOCAL_TYPEDECLS (got_scope)) - val = lookup_field (got_scope, name, 0, 1); + && CLASSTYPE_LOCAL_TYPEDECLS (type)) + val = lookup_field (type, name, 0, 1); } - else if (got_scope == current_class_type) + else if (type == current_class_type) val = IDENTIFIER_CLASS_VALUE (name); else - val = lookup_field (got_scope, name, 0, 0); - - goto done; + val = lookup_field (type, name, 0, prefer_type); } + else + val = NULL_TREE; + + if (got_scope) + goto done; + + /* This special lookup only applies to types. */ + else if (got_object && val && TREE_CODE (val) == TYPE_DECL) + from_obj = val; } if (current_binding_level != global_binding_level @@ -3987,16 +4481,20 @@ lookup_name_real (name, prefer_type, non done: if (val) { + if (from_obj && from_obj != val) + cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope", + got_object); + if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template) || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0) - return val; - - if (IDENTIFIER_HAS_TYPE_VALUE (name)) - return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); - - if (TREE_TYPE (val) == error_mark_node) - return error_mark_node; + ; + else if (IDENTIFIER_HAS_TYPE_VALUE (name)) + val = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); + else if (TREE_TYPE (val) == error_mark_node) + val = error_mark_node; } + else if (from_obj) + val = from_obj; return val; } @@ -4038,7 +4536,7 @@ lookup_name_current_level (name) while (1) { for (t = b->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) + if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name) goto out; if (b->keep == 2) b = b->level_chain; @@ -4134,7 +4632,7 @@ record_builtin_type (rid_index, name, ty } } - if (flag_dossier) + if (flag_rtti) { if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max) { @@ -4192,6 +4690,22 @@ push_overloaded_decl_1 (x) push_overloaded_decl (x, 0); } +#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ + define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME) + +#ifdef __GNUC__ +__inline +#endif +tree auto_function (name, type, code) + tree name, type; + enum built_in_function code; +{ + return define_function + (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1, + IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type), + 0))); +} + /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *)0). Initialize the global binding level. @@ -4214,13 +4728,19 @@ init_decl_processing () int wchar_type_size; tree temp; tree array_domain_type; + extern int flag_strict_prototype; /* Have to make these distinct before we try using them. */ lang_name_cplusplus = get_identifier ("C++"); lang_name_c = get_identifier ("C"); - if (flag_ansi || pedantic) - strict_prototypes_lang_c = strict_prototypes_lang_cplusplus; + if (flag_strict_prototype == 2) + { + if (pedantic) + strict_prototypes_lang_c = strict_prototypes_lang_cplusplus; + } + else + strict_prototypes_lang_c = flag_strict_prototype; /* Initially, C. */ current_lang_name = lang_name_c; @@ -4254,7 +4774,7 @@ init_decl_processing () #endif gcc_obstack_init (&decl_obstack); - if (flag_dossier) + if (flag_rtti) { builtin_type_tdescs_max = 100; builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree)); @@ -4278,6 +4798,12 @@ init_decl_processing () delta_identifier = get_identifier (VTABLE_DELTA_NAME); delta2_identifier = get_identifier (VTABLE_DELTA2_NAME); pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2"); + if (flag_handle_signatures) + { + tag_identifier = get_identifier (SIGTABLE_TAG_NAME); + vb_off_identifier = get_identifier (SIGTABLE_VB_OFF_NAME); + vt_off_identifier = get_identifier (SIGTABLE_VT_OFF_NAME); + } /* Define `int' and `char' first so that dbx will output them first. */ @@ -4389,13 +4915,13 @@ init_decl_processing () integer_three_node = build_int_2 (3, 0); TREE_TYPE (integer_three_node) = integer_type_node; - bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE); - TREE_SET_CODE (bool_type_node, BOOLEAN_TYPE); - record_builtin_type (RID_BOOL, "bool", bool_type_node); - false_node = build_int_2 (0, 0); - TREE_TYPE (false_node) = bool_type_node; - true_node = build_int_2 (1, 0); - TREE_TYPE (true_node) = bool_type_node; + boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); + TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + record_builtin_type (RID_BOOL, "bool", boolean_type_node); + boolean_false_node = build_int_2 (0, 0); + TREE_TYPE (boolean_false_node) = boolean_type_node; + boolean_true_node = build_int_2 (1, 0); + TREE_TYPE (boolean_true_node) = boolean_type_node; /* These are needed by stor-layout.c. */ size_zero_node = size_int (0); @@ -4824,22 +5350,39 @@ init_decl_processing () if (flag_handle_signatures) { sigtable_entry_type = make_lang_type (RECORD_TYPE); - fields[0] = build_lang_field_decl (FIELD_DECL, - get_identifier (SIGTABLE_CODE_NAME), - short_integer_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, - get_identifier (SIGTABLE_OFFSET_NAME), - short_integer_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, - get_identifier (SIGTABLE_PFN_NAME), + fields[0] = build_lang_field_decl (FIELD_DECL, tag_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, vb_off_identifier, + delta_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[3] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[4] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node); - finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 2, - double_type_node); + + /* Set the alignment to the max of the alignment of ptr_type_node and + delta_type_node. Double alignment wastes a word on the Sparc. */ + finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 4, + (TYPE_ALIGN (ptr_type_node) > TYPE_ALIGN (delta_type_node)) + ? ptr_type_node + : delta_type_node); + + /* Make this part of an invisible union. */ + fields[5] = copy_node (fields[4]); + TREE_TYPE (fields[5]) = delta_type_node; + DECL_NAME (fields[5]) = vt_off_identifier; + DECL_MODE (fields[5]) = TYPE_MODE (delta_type_node); + DECL_SIZE (fields[5]) = TYPE_SIZE (delta_type_node); + TREE_UNSIGNED (fields[5]) = 0; + TREE_CHAIN (fields[4]) = fields[5]; + sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0); record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type); } - if (flag_dossier) +#if 0 + if (flag_rtti) { /* Must build __t_desc type. Currently, type descriptors look like this: @@ -4863,11 +5406,11 @@ init_decl_processing () __i_desc_type_node = make_lang_type (RECORD_TYPE); __m_desc_type_node = make_lang_type (RECORD_TYPE); __t_desc_array_type = - build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE); + build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE); __i_desc_array_type = - build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE); + build_array_type (build_pointer_type (__i_desc_type_node), NULL_TREE); __m_desc_array_type = - build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE); + build_array_type (build_pointer_type (__m_desc_type_node), NULL_TREE); fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), string_type_node); @@ -4877,7 +5420,7 @@ init_decl_processing () unsigned_type_node); fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("points_to"), - TYPE_POINTER_TO (__t_desc_type_node)); + build_pointer_type (__t_desc_type_node)); fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("ivars_count"), integer_type_node); @@ -4911,7 +5454,7 @@ init_decl_processing () fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"), integer_type_node); fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), - TYPE_POINTER_TO (__t_desc_type_node)); + build_pointer_type (__t_desc_type_node)); finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, integer_type_node); @@ -4935,9 +5478,9 @@ init_decl_processing () fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"), integer_type_node); fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"), - TYPE_POINTER_TO (__t_desc_type_node)); + build_pointer_type (__t_desc_type_node)); fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"), - TYPE_POINTER_TO (__t_desc_type_node)); + build_pointer_type (__t_desc_type_node)); fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"), build_pointer_type (default_function_type)); fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"), @@ -4945,14 +5488,12 @@ init_decl_processing () fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"), short_integer_type_node); fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"), - build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE))); + build_pointer_type (build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE))); finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node); } - /* Now, C++. */ - current_lang_name = lang_name_cplusplus; - if (flag_dossier) + if (flag_rtti) { int i = builtin_type_tdescs_len; while (i > 0) @@ -4962,6 +5503,10 @@ init_decl_processing () TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1; } } +#endif /*flag_rtti*/ + + /* Now, C++. */ + current_lang_name = lang_name_cplusplus; auto_function (ansi_opname[(int) NEW_EXPR], build_function_type (ptr_type_node, @@ -5002,7 +5547,7 @@ init_decl_processing () { flag_inline_functions = 0; #if 0 - /* This causes uneccessary emission of inline functions. */ + /* This causes unnecessary emission of inline functions. */ flag_default_inline = 0; #endif } @@ -5016,6 +5561,74 @@ init_decl_processing () init_function_format_info (); } +/* initialize type descriptor type node of various rtti type. */ + +int +init_type_desc() +{ + tree tdecl; + + tdecl = lookup_name (get_identifier ("type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __t_desc_type_node = TREE_TYPE(tdecl); + __tp_desc_type_node = build_pointer_type (__t_desc_type_node); + +#if 0 + tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __baselist_desc_type_node = TREE_TYPE (tdecl); +#endif + + tdecl = lookup_name (get_identifier ("__builtin_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __bltn_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__user_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __user_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__class_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __class_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_field (__class_desc_type_node, + get_identifier ("access_mode"), 0, 0); + if (tdecl == NULL_TREE) + return 0; + __access_mode_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__attr_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __attr_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__pointer_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __ptr_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__func_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __func_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__ptmf_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __ptmf_desc_type_node = TREE_TYPE (tdecl); + + tdecl = lookup_name (get_identifier ("__ptmd_type_info"), 0); + if (tdecl == NULL_TREE) + return 0; + __ptmd_desc_type_node = TREE_TYPE (tdecl); + + return 1; +} /* Make a definition for a builtin function named NAME and whose data type is TYPE. TYPE should be a function type with argument types. FUNCTION_CODE tells later passes how to compile calls to this function. @@ -5035,6 +5648,7 @@ define_function (name, type, function_co tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type); DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME, we cannot change DECL_ASSEMBLER_NAME until we have installed this @@ -5091,7 +5705,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; } @@ -5112,7 +5729,7 @@ shadow_tag (declspecs) if (TYPE_FIELDS (t)) { tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, - NULL_TREE); + NULL_TREE, NULL_TREE); finish_anon_union (decl); } else @@ -5122,9 +5739,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"); @@ -5143,7 +5770,7 @@ groktypename (typename) return typename; return grokdeclarator (TREE_VALUE (typename), TREE_PURPOSE (typename), - TYPENAME, 0, NULL_TREE); + TYPENAME, 0, NULL_TREE, NULL_TREE); } /* Decode a declarator in an ordinary declaration or data definition. @@ -5154,7 +5781,7 @@ groktypename (typename) The ..._DECL node is returned as the value. Exception: for arrays where the length is not specified, - the type is left null, to be filled in by `finish_decl'. + the type is left null, to be filled in by `cp_finish_decl'. Function definitions do not come here; they go to start_function instead. However, external and forward declarations of functions @@ -5187,7 +5814,8 @@ start_decl (declarator, declspecs, initi used_extern_spec = 1; } - decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises); + decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises, + NULL_TREE); if (decl == NULL_TREE || decl == void_type_node) return NULL_TREE; @@ -5213,12 +5841,7 @@ start_decl (declarator, declspecs, initi pop_obstacks (); } - /* Interesting work for this is done in `finish_exception_decl'. */ - if (TREE_CODE (type) == RECORD_TYPE - && CLASSTYPE_DECLARED_EXCEPTION (type)) - return decl; - - /* Corresponding pop_obstacks is done in `finish_decl'. */ + /* Corresponding pop_obstacks is done in `cp_finish_decl'. */ push_obstacks_nochange (); context @@ -5258,9 +5881,6 @@ start_decl (declarator, declspecs, initi DECL_ARGUMENTS (decl) = args; } d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl)); - if (interface_unknown && flag_external_templates - && ! DECL_IN_SYSTEM_HEADER (decl)) - warn_if_unknown_interface (); TREE_PUBLIC (d) = TREE_PUBLIC (decl); TREE_STATIC (d) = TREE_STATIC (decl); DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) @@ -5279,12 +5899,12 @@ start_decl (declarator, declspecs, initi if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly - tell `finish_decl' to ignore the initializer once it is parsed. */ + tell `cp_finish_decl' to ignore the initializer once it is parsed. */ switch (TREE_CODE (decl)) { case TYPE_DECL: /* typedef foo = bar means give foo the same type as bar. - We haven't parsed bar yet, so `finish_decl' will fix that up. + We haven't parsed bar yet, so `cp_finish_decl' will fix that up. Any other case of an initialization in a TYPE_DECL is an error. */ if (pedantic || list_length (declspecs) > 1) { @@ -5346,17 +5966,17 @@ start_decl (declarator, declspecs, initi if (initialized) { - if (current_binding_level != global_binding_level + if (! toplevel_bindings_p () && DECL_EXTERNAL (decl)) cp_warning ("declaration of `%#D' has `extern' and is initialized", decl); DECL_EXTERNAL (decl) = 0; - if (current_binding_level == global_binding_level) + if ( toplevel_bindings_p ()) TREE_STATIC (decl) = 1; /* Tell `pushdecl' this is an initialized decl even though we don't yet have the initializer expression. - Also tell `finish_decl' it may store the real initializer. */ + Also tell `cp_finish_decl' it may store the real initializer. */ DECL_INITIAL (decl) = error_mark_node; } @@ -5370,13 +5990,25 @@ start_decl (declarator, declspecs, initi else if (duplicate_decls (decl, field)) decl = field; } - - /* If it was not explicitly declared `extern', - revoke any previous claims of DECL_EXTERNAL. */ - if (DECL_THIS_EXTERN (decl) == 0) - DECL_EXTERNAL (decl) = 0; + else + { + tree field = check_classfn (context, NULL_TREE, decl); + if (field && duplicate_decls (decl, field)) + decl = field; + } + + /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */ if (DECL_LANG_SPECIFIC (decl)) DECL_IN_AGGR_P (decl) = 0; + if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context)) + SET_DECL_TEMPLATE_SPECIALIZATION (decl); + + /* Stupid stupid stupid stupid (jason 7/21/95) */ + if (pedantic && DECL_EXTERNAL (decl) + && ! DECL_TEMPLATE_SPECIALIZATION (decl)) + cp_pedwarn ("declaration of `%#D' outside of class is not definition", + decl); + pushclass (context, 2); } @@ -5403,7 +6035,7 @@ start_decl (declarator, declspecs, initi #if 0 /* We don't do this yet for GNU C++. */ /* For a local variable, define the RTL now. */ - if (current_binding_level != global_binding_level + if (! toplevel_bindings_p () /* But not if this is a duplicate decl and we preserved the rtl from the previous one (which may or may not happen). */ @@ -5480,7 +6112,7 @@ start_decl (declarator, declspecs, initi { /* When parsing and digesting the initializer, use temporary storage. Do this even if we will ignore the value. */ - if (current_binding_level == global_binding_level && debug_temp_inits) + if (toplevel_bindings_p () && debug_temp_inits) { if (TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE) @@ -5518,17 +6150,16 @@ make_temporary_for_reference (decl, ctor } else { - tmp = get_temp_name (target_type, - current_binding_level == global_binding_level); + tmp = get_temp_name (target_type, toplevel_bindings_p ()); tmp_addr = build_unary_op (ADDR_EXPR, tmp, 0); } TREE_TYPE (tmp_addr) = build_pointer_type (target_type); - DECL_INITIAL (decl) = convert (TYPE_POINTER_TO (target_type), tmp_addr); + DECL_INITIAL (decl) = convert (build_pointer_type (target_type), tmp_addr); TREE_TYPE (DECL_INITIAL (decl)) = type; if (TYPE_NEEDS_CONSTRUCTING (target_type)) { - if (current_binding_level == global_binding_level) + if (toplevel_bindings_p ()) { /* lay this variable out now. Otherwise `output_addressed_constants' gets confused by its initializer. */ @@ -5551,8 +6182,8 @@ make_temporary_for_reference (decl, ctor else { DECL_INITIAL (tmp) = init; - TREE_STATIC (tmp) = current_binding_level == global_binding_level; - finish_decl (tmp, init, 0, 0); + TREE_STATIC (tmp) = toplevel_bindings_p (); + cp_finish_decl (tmp, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } if (TREE_STATIC (tmp)) preserve_initializer (); @@ -5560,7 +6191,7 @@ make_temporary_for_reference (decl, ctor #endif /* Handle initialization of references. - These three arguments from from `finish_decl', and have the + These three arguments from from `cp_finish_decl', and have the same meaning here that they do there. */ /* quotes on semantics can be found in ARM 8.4.3. */ static void @@ -5572,8 +6203,9 @@ grok_reference_init (decl, type, init, c if (init == NULL_TREE) { - if (DECL_LANG_SPECIFIC (decl) == 0 - || DECL_IN_AGGR_P (decl) == 0) + if ((DECL_LANG_SPECIFIC (decl) == 0 + || DECL_IN_AGGR_P (decl) == 0) + && ! DECL_THIS_EXTERN (decl)) { cp_error ("`%D' declared as reference but not initialized", decl); if (TREE_CODE (decl) == VAR_DECL) @@ -5595,6 +6227,9 @@ grok_reference_init (decl, type, init, c if (TREE_CODE (init) == TREE_LIST) init = build_compound_expr (init); + if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) + init = convert_from_reference (init); + if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) { @@ -5628,7 +6263,7 @@ grok_reference_init (decl, type, init, c if (TREE_CODE (tmp) == TARGET_EXPR) { *cleanupp = build_delete - (TYPE_POINTER_TO (subtype), + (build_pointer_type (subtype), build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); TREE_OPERAND (tmp, 2) = error_mark_node; @@ -5667,6 +6302,31 @@ grok_reference_init (decl, type, init, c return; } +/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from + mucking with forces it does not comprehend (i.e. initialization with a + constructor). If we are at global scope and won't go into COMMON, fill + it in with a dummy CONSTRUCTOR to force the variable into .data; + otherwise we can use error_mark_node. */ + +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 (toplevel_bindings_p () && ! 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; install its line number and initial value. If the length of an array type is not known before, @@ -5674,23 +6334,27 @@ grok_reference_init (decl, type, init, c Call `pop_obstacks' iff NEED_POP is nonzero. - For C++, `finish_decl' must be fairly evasive: it must keep initializers + For C++, `cp_finish_decl' must be fairly evasive: it must keep initializers for aggregates that have constructors alive on the permanent obstack, so that the global initializing functions can be written at the end. INIT0 holds the value of an initializer that should be allowed to escape the normal rules. + FLAGS is LOOKUP_ONLYCONVERTING is the = init syntax was used, else 0 + if the (init) syntax was used. + For functions that take default parameters, DECL points to its - "maximal" instantiation. `finish_decl' must then also declared its + "maximal" instantiation. `cp_finish_decl' must then also declared its subsequently lower and lower forms of instantiation, checking for ambiguity as it goes. This can be sped up later. */ void -finish_decl (decl, init, asmspec_tree, need_pop) +cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) tree decl, init; tree asmspec_tree; int need_pop; + int flags; { register tree type; tree cleanup = NULL_TREE, ttype; @@ -5721,7 +6385,7 @@ finish_decl (decl, init, asmspec_tree, n if (type == error_mark_node) { - if (current_binding_level == global_binding_level && temporary) + if (toplevel_bindings_p () && temporary) end_temporary_allocation (); return; @@ -5751,12 +6415,6 @@ finish_decl (decl, init, asmspec_tree, n DECL_CONTEXT (decl) == NULL_TREE, 0); goto finish_end; } - if (type != error_mark_node && IS_AGGR_TYPE (type) - && CLASSTYPE_DECLARED_EXCEPTION (type)) - { - CLASSTYPE_GOT_SEMICOLON (type) = 1; - goto finish_end; - } if (TREE_CODE (decl) != FUNCTION_DECL) { ttype = target_type (type); @@ -5804,10 +6462,7 @@ finish_decl (decl, init, asmspec_tree, n if (asmspec) { /* This must override the asm specifier which was placed - by grokclassfn. Lay this out fresh. - - @@ Should emit an error if this redefines an asm-specified - @@ name, or if we have already used the function's name. */ + by grokclassfn. Lay this out fresh. */ DECL_RTL (TREE_TYPE (decl)) = NULL_RTX; DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec); make_decl_rtl (decl, asmspec, 0); @@ -5823,7 +6478,7 @@ finish_decl (decl, init, asmspec_tree, n { if (TREE_STATIC (decl)) make_decl_rtl (decl, NULL_PTR, - current_binding_level == global_binding_level + toplevel_bindings_p () || pseudo_global_level_p ()); grok_reference_init (decl, type, init, &cleanup); init = NULL_TREE; @@ -5851,7 +6506,7 @@ finish_decl (decl, init, asmspec_tree, n init = digest_init (type, init, (tree *) 0); else if (TREE_CODE (init) == CONSTRUCTOR) { - if (TYPE_NEEDS_CONSTRUCTING (type)) + if (TYPE_NON_AGGREGATE_CLASS (type)) { cp_error ("`%D' must be initialized by constructor, not by `{...}'", decl); @@ -5860,81 +6515,18 @@ finish_decl (decl, init, asmspec_tree, n else goto dont_use_constructor; } -#if 0 - /* fix this in `build_functional_cast' instead. - Here's the trigger code: - - struct ostream - { - ostream (); - ostream (int, char *); - ostream (char *); - operator char *(); - ostream (void *); - operator void *(); - operator << (int); - }; - int buf_size = 1024; - static char buf[buf_size]; - const char *debug(int i) { - char *b = &buf[0]; - ostream o = ostream(buf_size, b); - o << i; - return buf; - } - */ - - else if (TREE_CODE (init) == TARGET_EXPR - && TREE_CODE (TREE_OPERAND (init, 1) == NEW_EXPR)) - { - /* User wrote something like `foo x = foo (args)' */ - my_friendly_assert (TREE_CODE (TREE_OPERAND (init, 0)) == VAR_DECL, 150); - my_friendly_assert (DECL_NAME (TREE_OPERAND (init, 0)) == NULL_TREE, 151); - - /* User wrote exactly `foo x = foo (args)' */ - if (TYPE_MAIN_VARIANT (type) == TREE_TYPE (init)) - { - init = build (CALL_EXPR, TREE_TYPE (init), - TREE_OPERAND (TREE_OPERAND (init, 1), 0), - TREE_OPERAND (TREE_OPERAND (init, 1), 1), 0); - TREE_SIDE_EFFECTS (init) = 1; - } - } -#endif - - /* We must hide the initializer so that expand_decl - won't try to do something it does not understand. */ - if (current_binding_level == global_binding_level) - { - tree value; - if (DECL_COMMON (decl)) - /* Should this be a NULL_TREE? */ - value = error_mark_node; - else - value = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); - DECL_INITIAL (decl) = value; - } - else - DECL_INITIAL (decl) = error_mark_node; } 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) - { - tree value; - if (DECL_COMMON (decl)) - value = error_mark_node; - else - value = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); - DECL_INITIAL (decl) = value; - } } + + 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)) ; @@ -5959,20 +6551,9 @@ finish_decl (decl, init, asmspec_tree, n && (TYPE_READONLY (type) || TREE_READONLY (decl))) cp_error ("uninitialized const `%D'", decl); - /* Initialize variables in need of static initialization with - an empty CONSTRUCTOR to keep assemble_variable from putting them in - the wrong program space. */ - if (flag_pic == 0 - && TREE_STATIC (decl) - && TREE_PUBLIC (decl) - && ! DECL_EXTERNAL (decl) - && TREE_CODE (decl) == VAR_DECL - && TYPE_NEEDS_CONSTRUCTING (type) - && (DECL_INITIAL (decl) == NULL_TREE - || DECL_INITIAL (decl) == error_mark_node) - && ! DECL_COMMON (decl)) - DECL_INITIAL (decl) = build (CONSTRUCTOR, type, NULL_TREE, - NULL_TREE); + if (TYPE_SIZE (type) != NULL_TREE + && TYPE_NEEDS_CONSTRUCTING (type)) + init = obscure_complex_init (decl, NULL_TREE); } else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (type) != REFERENCE_TYPE @@ -5995,7 +6576,7 @@ finish_decl (decl, init, asmspec_tree, n must go in the permanent obstack; but don't discard the temporary data yet. */ - if (current_binding_level == global_binding_level && temporary) + if (toplevel_bindings_p () && temporary) end_temporary_allocation (); /* Deduce size of array from initialization, if not already known. */ @@ -6064,6 +6645,10 @@ finish_decl (decl, init, asmspec_tree, n /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); + if (TREE_STATIC (decl) && DECL_CONTEXT (decl) + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') + note_debug_info_needed (DECL_CONTEXT (decl)); + if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != NULL_TREE && ! TREE_CONSTANT (DECL_SIZE (decl))) @@ -6110,8 +6695,7 @@ finish_decl (decl, init, asmspec_tree, n || TREE_CODE (decl) == RESULT_DECL) { /* ??? FIXME: What about nested classes? */ - int toplev = (current_binding_level == global_binding_level - || pseudo_global_level_p ()); + int toplev = toplevel_bindings_p () || pseudo_global_level_p (); int was_temp = ((flag_traditional || (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type))) @@ -6121,7 +6705,7 @@ finish_decl (decl, init, asmspec_tree, n end_temporary_allocation (); if (TREE_CODE (decl) == VAR_DECL - && current_binding_level != global_binding_level + && ! toplevel_bindings_p () && ! TREE_STATIC (decl) && type_needs_gc_entry (type)) DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index); @@ -6158,7 +6742,7 @@ finish_decl (decl, init, asmspec_tree, n else if (toplev && ! TREE_PUBLIC (decl)) { /* If this is a static const, change its apparent linkage - if it belongs to a #pragma interface. */ + if it belongs to a #pragma interface. */ if (!interface_unknown) { TREE_PUBLIC (decl) = 1; @@ -6219,65 +6803,15 @@ finish_decl (decl, init, asmspec_tree, n signature_error (decl, TREE_TYPE (type)); if (TREE_CODE (decl) == FUNCTION_DECL) - { -#if 0 - /* C++: Handle overloaded functions with default parameters. */ - if (DECL_OVERLOADED (decl)) - { - tree parmtypes = TYPE_ARG_TYPES (type); - tree prev = NULL_TREE; - tree original_name = DECL_NAME (decl); - struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl); - /* All variants will share an uncollectible lang_decl. */ - copy_decl_lang_specific (decl); - - while (parmtypes && parmtypes != void_list_node) - { - /* The default value for the parameter in parmtypes is - stored in the TREE_PURPOSE of the TREE_LIST. */ - if (TREE_PURPOSE (parmtypes)) - { - tree fnname, fndecl; - tree *argp; - - argp = prev ? & TREE_CHAIN (prev) - : & TYPE_ARG_TYPES (type); - - *argp = NULL_TREE; - fnname = build_decl_overload (original_name, - TYPE_ARG_TYPES (type), 0); - *argp = parmtypes; - fndecl = build_decl (FUNCTION_DECL, fnname, type); - DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl); - TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl); - DECL_INLINE (fndecl) = DECL_INLINE (decl); - /* Keep G++ from thinking this function is unused. - It is only used to speed up search in name space. */ - TREE_USED (fndecl) = 1; - TREE_ASM_WRITTEN (fndecl) = 1; - DECL_INITIAL (fndecl) = NULL_TREE; - DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl); - fndecl = pushdecl (fndecl); - DECL_INITIAL (fndecl) = error_mark_node; - DECL_RTL (fndecl) = DECL_RTL (decl); - } - prev = parmtypes; - parmtypes = TREE_CHAIN (parmtypes); - } - DECL_LANG_SPECIFIC (decl) = tmp_lang_decl; - } -#endif - } + ; else if (DECL_EXTERNAL (decl)) ; else if (TREE_STATIC (decl) && type != error_mark_node) { /* Cleanups for static variables are handled by `finish_file'. */ - if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE) + if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE + || TYPE_NEEDS_DESTRUCTOR (type)) expand_static_init (decl, init); - else if (TYPE_NEEDS_DESTRUCTOR (type)) - static_aggregates = perm_tree_cons (NULL_TREE, decl, - static_aggregates); /* Make entry in appropriate vector. */ if (flag_gc && type_needs_gc_entry (type)) @@ -6312,7 +6846,7 @@ finish_decl (decl, init, asmspec_tree, n { /* XXX: Why don't we use decl here? */ /* Ans: Because it was already expanded? */ - if (! expand_decl_cleanup (NULL_TREE, cleanup)) + if (! cp_expand_decl_cleanup (NULL_TREE, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); /* Cleanup used up here. */ @@ -6329,7 +6863,7 @@ finish_decl (decl, init, asmspec_tree, n { emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); - expand_aggr_init (decl, init, 0); + expand_aggr_init (decl, init, 0, flags); } /* Set this to 0 so we can tell whether an aggregate which @@ -6342,7 +6876,7 @@ finish_decl (decl, init, asmspec_tree, n /* Store the cleanup, if there was one. */ if (cleanup) { - if (! expand_decl_cleanup (decl, cleanup)) + if (! cp_expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); } @@ -6356,7 +6890,7 @@ finish_decl (decl, init, asmspec_tree, n due to initialization of qualified member variable. I.e., Foo::x = 10; */ { - tree context = DECL_CONTEXT (decl); + tree context = DECL_REAL_CONTEXT (decl); if (context && TREE_CODE_CLASS (TREE_CODE (context)) == 't' && (TREE_CODE (decl) == VAR_DECL @@ -6412,6 +6946,15 @@ finish_decl (decl, init, asmspec_tree, n cadillac_finish_decl (decl); } +/* This is here for a midend callback from c-common.c */ +void +finish_decl (decl, init, asmspec_tree) + tree decl, init; + tree asmspec_tree; +{ + cp_finish_decl (decl, init, asmspec_tree, 1, 0); +} + void expand_static_init (decl, init) tree decl; @@ -6425,8 +6968,7 @@ expand_static_init (decl, init) if (TREE_PURPOSE (oldstatic) && init != NULL_TREE) cp_error ("multiple initializations given for `%D'", decl); } - else if (current_binding_level != global_binding_level - && current_binding_level->pseudo_global == 0) + else if (! toplevel_bindings_p () && ! pseudo_global_level_p ()) { /* Emit code to perform this initialization but once. */ tree temp; @@ -6441,13 +6983,15 @@ 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)) + || (init && TREE_CODE (init) == TREE_LIST)) { - expand_aggr_init (decl, init, 0); + expand_aggr_init (decl, init, 0, 0); do_pending_stack_adjust (); } - else + else if (init) expand_assignment (decl, init, 0, 0); + /* Cleanup any temporaries needed for the initial value. */ expand_cleanups_to (old_cleanups); expand_end_cond (); @@ -6489,12 +7033,24 @@ complete_array_type (type, initial_value /* Note MAXINDEX is really the maximum index, one less than the size. */ if (TREE_CODE (initial_value) == STRING_CST) - maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) - 1, 0); + { + int eltsize + = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); + maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value) + / eltsize) - 1, 0); + } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { - register int nelts - = list_length (CONSTRUCTOR_ELTS (initial_value)); - maxindex = build_int_2 (nelts - 1, - (nelts == 0)); + tree elts = CONSTRUCTOR_ELTS (initial_value); + maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node); + for (; elts; elts = TREE_CHAIN (elts)) + { + if (TREE_PURPOSE (elts)) + maxindex = TREE_PURPOSE (elts); + else + maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node); + } + maxindex = copy_node (maxindex); } else { @@ -6519,7 +7075,7 @@ complete_array_type (type, initial_value tree itype; TYPE_DOMAIN (type) = build_index_type (maxindex); - if (!TREE_TYPE (maxindex)) + if (! TREE_TYPE (maxindex)) TREE_TYPE (maxindex) = TYPE_DOMAIN (type); if (initial_value) itype = TREE_TYPE (initial_value); @@ -6527,6 +7083,11 @@ complete_array_type (type, initial_value itype = NULL; if (itype && !TYPE_DOMAIN (itype)) TYPE_DOMAIN (itype) = TYPE_DOMAIN (type); + /* The type of the main variant should never be used for arrays + of different sizes. It should only ever be completed with the + size of the array. */ + if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type))) + TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type); } /* Lay out the type now that we can get the real answer. */ @@ -6572,7 +7133,7 @@ bad_specifiers (object, type, virtualp, if (friendp) cp_error_at ("invalid friend declaration", object); if (raises) - cp_error_at ("invalid raises declaration", object); + cp_error_at ("invalid exception specifications", object); } /* CTYPE is class type, or null if non-class. @@ -6588,13 +7149,13 @@ bad_specifiers (object, type, virtualp, not look, and -1 if we should not call `grokclassfn' at all. */ static tree grokfndecl (ctype, type, declarator, virtualp, flags, quals, - raises, check, publicp) + raises, attrlist, check, publicp, inlinep) tree ctype, type; tree declarator; int virtualp; enum overload_flags flags; - tree quals, raises; - int check, publicp; + tree quals, raises, attrlist; + int check, publicp, inlinep; { tree cname, decl; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; @@ -6607,7 +7168,7 @@ grokfndecl (ctype, type, declarator, vir if (raises) { - type = build_exception_variant (ctype, type, raises); + type = build_exception_variant (type, raises); raises = TYPE_RAISES_EXCEPTIONS (type); } decl = build_lang_decl (FUNCTION_DECL, declarator, type); @@ -6623,8 +7184,25 @@ grokfndecl (ctype, type, declarator, vir DECL_CLASS_CONTEXT (decl) = ctype; } - if (publicp) - TREE_PUBLIC (decl) = 1; + /* All function decls start out public; we'll fix their linkage later (at + definition or EOF) if appropriate. */ + TREE_PUBLIC (decl) = 1; + + if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) + { + if (inlinep) + error ("cannot declare `main' to be inline"); + else if (! publicp) + error ("cannot declare `main' to be static"); + inlinep = 0; + publicp = 1; + } + + if (! publicp) + DECL_C_STATIC (decl) = 1; + + if (inlinep) + DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1; DECL_EXTERNAL (decl) = 1; if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) @@ -6711,6 +7289,10 @@ grokfndecl (ctype, type, declarator, vir /* avoid creating circularities. */ DECL_CHAIN (decl) = NULL_TREE; } + + if (attrlist) + cplus_decl_attributes (decl, TREE_PURPOSE (attrlist), + TREE_VALUE (attrlist)); make_decl_rtl (decl, NULL_PTR, 1); } @@ -6761,7 +7343,7 @@ grokfndecl (ctype, type, declarator, vir type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes); if (raises) { - type = build_exception_variant (ctype, type, raises); + type = build_exception_variant (type, raises); raises = TYPE_RAISES_EXCEPTIONS (type); } TREE_TYPE (decl) = type; @@ -6794,11 +7376,12 @@ grokfndecl (ctype, type, declarator, vir } static tree -grokvardecl (type, declarator, specbits, initialized) +grokvardecl (type, declarator, specbits, initialized, constp) tree type; tree declarator; RID_BIT_TYPE specbits; int initialized; + int constp; { tree decl; @@ -6816,6 +7399,8 @@ grokvardecl (type, declarator, specbits, else decl = build_decl (VAR_DECL, declarator, type); + DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl)); + if (RIDBIT_SETP (RID_EXTERN, specbits)) { DECL_THIS_EXTERN (decl) = 1; @@ -6833,9 +7418,10 @@ grokvardecl (type, declarator, specbits, } /* At top level, either `static' or no s.c. makes a definition (perhaps tentative), and absence of `static' makes it public. */ - else if (current_binding_level == global_binding_level) + else if (toplevel_bindings_p ()) { - TREE_PUBLIC (decl) = RIDBIT_NOTSETP (RID_STATIC, specbits); + TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits) + && (DECL_THIS_EXTERN (decl) || ! constp)); TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ @@ -6867,6 +7453,7 @@ build_ptrmemfunc_type (type) push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); u = make_lang_type (UNION_TYPE); + IS_AGGR_TYPE (u) = 0; fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type); fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, delta_type_node); @@ -6876,7 +7463,7 @@ build_ptrmemfunc_type (type) t = make_lang_type (RECORD_TYPE); /* Let the front-end know this is a pointer to member function. */ - TYPE_PTRMEMFUNC_FLAG(t) = 1; + TYPE_PTRMEMFUNC_FLAG (t) = 1; /* and not really an aggregate. */ IS_AGGR_TYPE (t) = 0; @@ -6920,6 +7507,7 @@ build_ptrmemfunc_type (type) try to parse. PARM for a parameter declaration (either within a function prototype or before a function body). Make a PARM_DECL, or return void_type_node. + CATCHPARM for a parameter declaration before a catch clause. TYPENAME if for a typename (in a cast or sizeof). Don't make a DECL node; just return the ..._TYPE node. FIELD for a struct or union field; make a FIELD_DECL. @@ -6958,12 +7546,12 @@ build_ptrmemfunc_type (type) enum return_types { return_normal, return_ctor, return_dtor, return_conversion }; tree -grokdeclarator (declarator, declspecs, decl_context, initialized, raises) +grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrlist) tree declspecs; tree declarator; enum decl_context decl_context; int initialized; - tree raises; + tree raises, attrlist; { RID_BIT_TYPE specbits; int nclasses = 0; @@ -6972,7 +7560,7 @@ grokdeclarator (declarator, declspecs, d int longlong = 0; int constp; int volatilep; - int virtualp, friendp, inlinep, staticp; + int virtualp, explicitp, friendp, inlinep, staticp; int explicit_int = 0; int explicit_char = 0; int opaque_typedef = 0; @@ -6983,6 +7571,7 @@ grokdeclarator (declarator, declspecs, d enum tree_code innermost_code = ERROR_MARK; int bitfield = 0; int size_varies = 0; + tree decl_machine_attr = NULL_TREE; /* Set this to error_mark_node for FIELD_DECLs we could not handle properly. All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */ tree init = NULL_TREE; @@ -7079,7 +7668,7 @@ grokdeclarator (declarator, declspecs, d if (parmlist_is_exprlist (TREE_OPERAND (decl, 1))) { /* This is actually a variable declaration using constructor - syntax. We need to call start_decl and finish_decl so we + syntax. We need to call start_decl and cp_finish_decl so we can get the variable initialized... */ if (last) @@ -7092,13 +7681,16 @@ grokdeclarator (declarator, declspecs, d init = TREE_OPERAND (decl, 1); decl = start_decl (declarator, declspecs, 1, NULL_TREE); - finish_decl (decl, init, NULL_TREE, 1); + finish_decl (decl, init, NULL_TREE); return 0; } innermost_code = TREE_CODE (decl); - decl = TREE_OPERAND (decl, 0); if (decl_context == FIELD && ctype == NULL_TREE) ctype = current_class_type; + if (ctype + && TREE_OPERAND (decl, 0) == constructor_name_full (ctype)) + TREE_OPERAND (decl, 0) = constructor_name (ctype); + decl = TREE_OPERAND (decl, 0); if (ctype != NULL_TREE && decl != NULL_TREE && flags != DTOR_FLAG && decl == constructor_name (ctype)) @@ -7192,6 +7784,9 @@ grokdeclarator (declarator, declspecs, d } } + if (ctype + && TREE_OPERAND (decl, 1) == constructor_name_full (ctype)) + TREE_OPERAND (decl, 1) = constructor_name (ctype); decl = TREE_OPERAND (decl, 1); if (ctype) { @@ -7203,12 +7798,13 @@ grokdeclarator (declarator, declspecs, d } else if (TREE_CODE (decl) == BIT_NOT_EXPR && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE - && constructor_name (ctype) == TREE_OPERAND (decl, 0)) + && (constructor_name (ctype) == TREE_OPERAND (decl, 0) + || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) { return_type = return_dtor; ctor_return_type = ctype; flags = DTOR_FLAG; - decl = TREE_OPERAND (decl, 0); + decl = TREE_OPERAND (decl, 0) = constructor_name (ctype); } } } @@ -7231,6 +7827,14 @@ grokdeclarator (declarator, declspecs, d if (funcdef_flag && innermost_code != CALL_EXPR) return 0; + if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG) + && innermost_code != CALL_EXPR + && ! (ctype && declspecs == NULL_TREE)) + { + cp_error ("declaration of `%D' as non-function", dname); + return void_type_node; + } + /* Anything declared one level down from the top level must be one of the parameters of a function (because the body is at least two levels down). */ @@ -7241,11 +7845,18 @@ grokdeclarator (declarator, declspecs, d Since we now wait to push a class scope until we are sure that we are in a legitimate method context, we must set oldcname - explicitly (since current_class_name is not yet alive). */ + explicitly (since current_class_name is not yet alive). + + We also want to avoid calling this a PARM if it is in a namespace. */ - if (decl_context == NORMAL - && current_binding_level->level_chain == global_binding_level) - decl_context = PARM; + if (decl_context == NORMAL && ! namespace_bindings_p ()) + { + struct binding_level *b = current_binding_level; + current_binding_level = b->level_chain; + if (current_binding_level != 0 && toplevel_bindings_p ()) + decl_context = PARM; + current_binding_level = b; + } /* Look through the decl specs and record which ones appear. Some typespecs are defined as built-in typenames. @@ -7284,7 +7895,12 @@ grokdeclarator (declarator, declspecs, d || id == ridpointers[(int) RID_WCHAR]) { if (type) - error ("extraneous `%T' ignored", id); + { + if (id == ridpointers[(int) RID_BOOL]) + error ("`bool' is now a keyword"); + else + cp_error ("extraneous `%T' ignored", id); + } else { if (id == ridpointers[(int) RID_INT]) @@ -7311,8 +7927,8 @@ grokdeclarator (declarator, declspecs, d { if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits)) { - if (pedantic && flag_ansi) - pedwarn ("duplicate `long'"); + if (pedantic && ! in_system_header) + pedwarn ("ANSI C++ does not support `long long'"); else if (longlong) error ("`long long long' is too long for GCC"); else @@ -7336,6 +7952,7 @@ grokdeclarator (declarator, declspecs, d else { type = TREE_TYPE (t); + decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id); typedef_decl = t; } } @@ -7371,7 +7988,7 @@ grokdeclarator (declarator, declspecs, d if (return_type == return_dtor) type = void_type_node; else if (return_type == return_ctor) - type = TYPE_POINTER_TO (ctor_return_type); + type = build_pointer_type (ctor_return_type); else if (return_type == return_conversion) type = ctor_return_type; else if (current_class_type @@ -7414,11 +8031,11 @@ grokdeclarator (declarator, declspecs, d else if (return_type == return_ctor) { error ("return type specification for constructor invalid"); - type = TYPE_POINTER_TO (ctor_return_type); + type = build_pointer_type (ctor_return_type); } else if (return_type == return_conversion) { - if (comp_target_types (type, ctor_return_type, 1) == 0) + if (comptypes (type, ctor_return_type, 1) == 0) cp_error ("operator `%T' declared to return `%T'", ctor_return_type, type); else @@ -7461,7 +8078,7 @@ grokdeclarator (declarator, declspecs, d if (TREE_CODE (type) == REAL_TYPE) error ("short, signed or unsigned invalid for `%s'", name); - else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node) + else if (TREE_CODE (type) != INTEGER_TYPE) error ("long, short, signed or unsigned invalid for `%s'", name); else if (RIDBIT_SETP (RID_LONG, specbits) && RIDBIT_SETP (RID_SHORT, specbits)) @@ -7553,6 +8170,9 @@ grokdeclarator (declarator, declspecs, d warning ("duplicate `volatile'"); #endif virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); + RIDBIT_RESET (RID_VIRTUAL, specbits); + explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0; + RIDBIT_RESET (RID_EXPLICIT, specbits); if (RIDBIT_SETP (RID_STATIC, specbits)) staticp = 1 + (decl_context == FIELD); @@ -7564,37 +8184,31 @@ grokdeclarator (declarator, declspecs, d staticp = 0; } friendp = RIDBIT_SETP (RID_FRIEND, specbits); - RIDBIT_RESET (RID_VIRTUAL, specbits); RIDBIT_RESET (RID_FRIEND, specbits); if (RIDBIT_SETP (RID_MUTABLE, specbits)) { if (decl_context == PARM) { - error ("non-member `%s' cannot be declared mutable", name); + error ("non-member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } else if (friendp || decl_context == TYPENAME) { - error ("non-object member `%s' cannot be declared mutable", name); - RIDBIT_RESET (RID_MUTABLE, specbits); - } - else if (staticp) - { - error ("static `%s' cannot be declared mutable", name); + error ("non-object member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } #if 0 if (RIDBIT_SETP (RID_TYPEDEF, specbits)) { - error ("non-object member `%s' cannot be declared mutable", name); + error ("non-object member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } /* Because local typedefs are parsed twice, we don't want this message here. */ else if (decl_context != FIELD) { - error ("non-member `%s' cannot be declared mutable", name); + error ("non-member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } #endif @@ -7619,7 +8233,8 @@ grokdeclarator (declarator, declspecs, d } /* Give error if `virtual' is used outside of class declaration. */ - if (virtualp && current_class_name == NULL_TREE) + if (virtualp + && (current_class_name == NULL_TREE || decl_context != FIELD)) { error ("virtual outside class declaration"); virtualp = 0; @@ -7682,7 +8297,7 @@ grokdeclarator (declarator, declspecs, d error ("multiple storage classes in declaration of `%s'", name); else if (decl_context != NORMAL && nclasses > 0) { - if (decl_context == PARM + if ((decl_context == PARM || decl_context == CATCHPARM) && (RIDBIT_SETP (RID_REGISTER, specbits) || RIDBIT_SETP (RID_AUTO, specbits))) ; @@ -7729,7 +8344,7 @@ grokdeclarator (declarator, declspecs, d SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1; loc_typedecl = - grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE); + grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE, NULL_TREE); if (previous_declspec) TREE_CHAIN (previous_declspec) = scanner; @@ -7771,18 +8386,24 @@ grokdeclarator (declarator, declspecs, d { if (decl_context == FIELD) { - tree tmp = TREE_OPERAND (declarator, 0); - register int op = IDENTIFIER_OPNAME_P (tmp); + tree tmp = NULL_TREE; + register int op = 0; + + if (declarator) + { + tmp = TREE_OPERAND (declarator, 0); + op = IDENTIFIER_OPNAME_P (tmp); + } error ("storage class specified for %s `%s'", IS_SIGNATURE (current_class_type) ? (op ? "signature member operator" : "signature member function") - : (op ? "member operator" : "structure field"), + : (op ? "member operator" : "field"), op ? operator_name_string (tmp) : name); } else - error ((decl_context == PARM + error (((decl_context == PARM || decl_context == CATCHPARM) ? "storage class specified for parameter `%s'" : "storage class specified for typename"), name); RIDBIT_RESET (RID_REGISTER, specbits); @@ -7798,9 +8419,9 @@ grokdeclarator (declarator, declspecs, d } else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag) { - if (current_binding_level == global_binding_level) + if (toplevel_bindings_p ()) { - /* It's common practice (and completely legal) to have a const + /* It's common practice (and completely valid) to have a const be initialized and declared extern. */ if (! constp) warning ("`%s' initialized and declared `extern'", name); @@ -7809,9 +8430,9 @@ grokdeclarator (declarator, declspecs, d error ("`%s' has both `extern' and initializer", name); } else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag - && current_binding_level != global_binding_level) + && ! toplevel_bindings_p ()) error ("nested function `%s' declared `extern'", name); - else if (current_binding_level == global_binding_level) + else if (toplevel_bindings_p ()) { if (RIDBIT_SETP (RID_AUTO, specbits)) error ("top-level declaration of `%s' specifies `auto'", name); @@ -7891,6 +8512,8 @@ grokdeclarator (declarator, declspecs, d { register tree itype = NULL_TREE; register tree size = TREE_OPERAND (declarator, 1); + /* The index is a signed object `sizetype' bits wide. */ + tree index_type = signed_type (sizetype); declarator = TREE_OPERAND (declarator, 0); @@ -7910,7 +8533,7 @@ grokdeclarator (declarator, declspecs, d /* ARM $8.4.3: Since you can't have a pointer to a reference, you can't have arrays of references. If we allowed them, - then we'd be saying x[i] is legal for an array x, but + then we'd be saying x[i] is valid for an array x, but then you'd have to ask: what does `*(x + i)' mean? */ if (TREE_CODE (type) == REFERENCE_TYPE) { @@ -7970,22 +8593,26 @@ grokdeclarator (declarator, declspecs, d } if (TREE_READONLY_DECL_P (size)) size = decl_constant_value (size); - if (flag_ansi && integer_zerop (size)) + if (pedantic && integer_zerop (size)) cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname); if (TREE_CONSTANT (size)) { + int old_flag_pedantic_errors = flag_pedantic_errors; + int old_pedantic = pedantic; + pedantic = flag_pedantic_errors = 1; + /* Always give overflow errors on array subscripts. */ constant_expression_warning (size); + pedantic = old_pedantic; + flag_pedantic_errors = old_flag_pedantic_errors; if (INT_CST_LT (size, integer_zero_node)) { cp_error ("size of array `%D' is negative", dname); size = integer_one_node; } - itype = build_index_type (size_binop (MINUS_EXPR, size, - integer_one_node)); } else { - if (flag_ansi) + if (pedantic) { if (dname) cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", @@ -7993,15 +8620,20 @@ grokdeclarator (declarator, declspecs, d else cp_pedwarn ("ANSI C++ forbids variable-size array"); } - dont_grok_size: - itype = - build_binary_op (MINUS_EXPR, size, integer_one_node, 1); /* Make sure the array size remains visibly nonconstant - even if it is (eg) a const variable with known value. */ + even if it is (eg) a const variable with known value. */ size_varies = 1; - itype = variable_size (itype); - itype = build_index_type (itype); } + + dont_grok_size: + itype = + fold (build_binary_op (MINUS_EXPR, + convert (index_type, size), + convert (index_type, + integer_one_node), 1)); + if (! TREE_CONSTANT (itype)) + itype = variable_size (itype); + itype = build_index_type (itype); resume_momentary (yes); } @@ -8061,10 +8693,14 @@ grokdeclarator (declarator, declspecs, d if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) inner_decl = TREE_OPERAND (inner_decl, 1); + /* Pick up type qualifiers which should be applied to `this'. */ + quals = TREE_OPERAND (declarator, 2); + /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ funcdecl_p = - inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE; + inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE + || TREE_CODE (inner_decl) == BIT_NOT_EXPR); if (ctype == NULL_TREE && decl_context == FIELD @@ -8088,14 +8724,9 @@ grokdeclarator (declarator, declspecs, d may not be static. */ if (staticp == 2) error ("destructor cannot be static member function"); - if (TYPE_READONLY (type)) - { - error ("destructors cannot be declared `const'"); - return void_type_node; - } - if (TYPE_VOLATILE (type)) + if (quals) { - error ("destructors cannot be declared `volatile'"); + error ("destructors cannot be declared `const' or `volatile'"); return void_type_node; } if (decl_context == FIELD) @@ -8107,6 +8738,8 @@ grokdeclarator (declarator, declspecs, d } else /* it's a constructor. */ { + if (explicitp == 1) + explicitp = 2; /* ANSI C++ June 5 1992 WP 12.1.2. A constructor may not be declared const or volatile. A constructor may not be virtual. A constructor may not be static. */ @@ -8117,16 +8750,11 @@ grokdeclarator (declarator, declspecs, d pedwarn ("constructors cannot be declared virtual"); virtualp = 0; } - if (TYPE_READONLY (type)) + if (quals) { - error ("constructors cannot be declared `const'"); + error ("constructors cannot be declared `const' or `volatile'"); return void_type_node; } - if (TYPE_VOLATILE (type)) - { - error ("constructors cannot be declared `volatile'"); - return void_type_node; - } { RID_BIT_TYPE tmp_bits; bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE)); @@ -8135,7 +8763,7 @@ grokdeclarator (declarator, declspecs, d if (RIDBIT_ANY_SET (tmp_bits)) error ("return value type specifier for constructor ignored"); } - type = TYPE_POINTER_TO (ctype); + type = build_pointer_type (ctype); if (decl_context == FIELD && IS_SIGNATURE (current_class_type)) { @@ -8155,20 +8783,24 @@ grokdeclarator (declarator, declspecs, d if (decl_context == FIELD) staticp = 0; } - else if (friendp && virtualp) + else if (friendp) { - /* Cannot be both friend and virtual. */ - error ("virtual functions cannot be friends"); - RIDBIT_RESET (RID_FRIEND, specbits); - friendp = 0; + if (initialized) + error ("can't initialize friend function `%s'", name); + if (virtualp) + { + /* Cannot be both friend and virtual. */ + error ("virtual functions cannot be friends"); + 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"); - - /* Pick up type qualifiers which should be applied to `this'. */ - quals = TREE_OPERAND (declarator, 2); - /* Traditionally, declaring return type float means double. */ if (flag_traditional @@ -8231,6 +8863,15 @@ grokdeclarator (declarator, declspecs, d continue; } + if (TREE_CODE (type) == OFFSET_TYPE + && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE + || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE)) + { + cp_error ("cannot declare pointer to `%#T' member", + TREE_TYPE (type)); + type = TREE_TYPE (type); + } + /* Merge any constancy or volatility into the target type for the pointer. */ @@ -8330,9 +8971,9 @@ grokdeclarator (declarator, declspecs, d && (constp || volatilep)) { if (constp) - warning ("discarding `const' applied to a reference"); + pedwarn ("discarding `const' applied to a reference"); if (volatilep) - warning ("discarding `volatile' applied to a reference"); + pedwarn ("discarding `volatile' applied to a reference"); constp = volatilep = 0; } } @@ -8389,10 +9030,21 @@ grokdeclarator (declarator, declspecs, d /* This is the `standard' use of the scoping operator: basetype :: member . */ - if (TREE_CODE (type) == FUNCTION_TYPE) + if (ctype == current_class_type) + { + /* 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 - || TYPE_MAIN_VARIANT (ctype) == current_class_type || friendp) type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type)); @@ -8403,19 +9055,14 @@ grokdeclarator (declarator, declspecs, d return void_type_node; } } - else if (TYPE_MAIN_VARIANT (ctype) == current_class_type) - { - if (extra_warnings) - cp_warning ("redundant qualification `%T' on member `%s' ignored", - ctype, name); - type = build_offset_type (ctype, type); - } else if (TYPE_SIZE (ctype) != NULL_TREE || (RIDBIT_SETP (RID_TYPEDEF, specbits))) { tree t; /* have to move this code elsewhere in this function. - this code is used for i.e., typedef int A::M; M *pm; */ + this code is used for i.e., typedef int A::M; M *pm; + + It is? How? jason 10/2/94 */ if (explicit_int == -1 && decl_context == FIELD && funcdef_flag == 0) @@ -8441,7 +9088,8 @@ grokdeclarator (declarator, declspecs, d /* Don't include destructor with constructors. */ t = DECL_CHAIN (TREE_VALUE (t)); if (t == NULL_TREE) - error ("class `%s' does not have any constructors", IDENTIFIER_POINTER (sname)); + cp_error ("`%T' does not have any constructors", + ctype); t = build_tree_list (NULL_TREE, t); } t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type); @@ -8456,15 +9104,9 @@ grokdeclarator (declarator, declspecs, d if (current_class_type) { - if (TYPE_MAIN_VARIANT (ctype) != current_class_type) - { - cp_error ("cannot declare member `%T::%s' within `%T'", - ctype, name, current_class_type); - return void_type_node; - } - else if (extra_warnings) - cp_warning ("extra qualification `%T' on member `%s' ignored", - ctype, name); + cp_error ("cannot declare member `%T::%s' within `%T'", + ctype, name, current_class_type); + return void_type_node; } type = build_offset_type (ctype, type); } @@ -8526,10 +9168,30 @@ grokdeclarator (declarator, declspecs, d } } + if (explicitp == 1) + { + error ("only constructors can be declared `explicit'"); + explicitp = 0; + } + /* Now TYPE has the actual type. */ /* If this is declaring a typedef name, return a TYPE_DECL. */ + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + { + if (constp) + { + error ("const `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + else if (staticp) + { + error ("static `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + } + if (RIDBIT_SETP (RID_TYPEDEF, specbits)) { tree decl; @@ -8565,6 +9227,10 @@ grokdeclarator (declarator, declspecs, d declarator, type); else set_nested_typename (d, TYPE_NESTED_NAME (c), declarator, type); + + DECL_ASSEMBLER_NAME (d) = DECL_NAME (d); + DECL_ASSEMBLER_NAME (d) + = get_identifier (build_overload_name (type, 1, 1)); } } @@ -8631,13 +9297,28 @@ grokdeclarator (declarator, declspecs, d /* Special case: "friend class foo" looks like a TYPENAME context. */ if (friendp) { - /* A friendly class? */ - if (current_class_type) - make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); - else - error("trying to make class `%s' a friend of global scope", - TYPE_NAME_STRING (type)); - type = void_type_node; + if (volatilep) + { + cp_error ("`volatile' specified for friend class declaration"); + volatilep = 0; + } + if (inlinep) + { + cp_error ("`inline' specified for friend class declaration"); + inlinep = 0; + } + + /* Only try to do this stuff if we didn't already give up. */ + if (type != integer_type_node) + { + /* A friendly class? */ + if (current_class_type) + make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); + else + error ("trying to make class `%s' a friend of global scope", + TYPE_NAME_STRING (type)); + type = void_type_node; + } } else if (quals) { @@ -8658,6 +9339,7 @@ grokdeclarator (declarator, declspecs, d return type; } else if (declarator == NULL_TREE && decl_context != PARM + && decl_context != CATCHPARM && TREE_CODE (type) != UNION_TYPE && ! bitfield) { @@ -8672,7 +9354,9 @@ grokdeclarator (declarator, declspecs, d if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) { - if (TREE_CODE (declarator) == IDENTIFIER_NODE) + if (! declarator) + error ("unnamed variable or field declared void"); + else if (TREE_CODE (declarator) == IDENTIFIER_NODE) { if (IDENTIFIER_OPNAME_P (declarator)) #if 0 /* How could this happen? */ @@ -8715,6 +9399,11 @@ grokdeclarator (declarator, declspecs, d type = build_pointer_type (type); else if (TREE_CODE (type) == OFFSET_TYPE) type = build_pointer_type (type); + else if (type == void_type_node && declarator) + { + error ("declaration of `%s' as void", name); + return NULL_TREE; + } decl = build_decl (PARM_DECL, declarator, type); @@ -8789,48 +9478,38 @@ grokdeclarator (declarator, declspecs, d } /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ - publicp = (RIDBIT_SETP (RID_EXTERN, specbits) - || (ctype != NULL_TREE - && funcdef_flag >= 0 - && RIDBIT_NOTSETP (RID_INLINE, specbits)) - || (friendp - && ! funcdef_flag - && RIDBIT_NOTSETP (RID_STATIC, specbits) - && RIDBIT_NOTSETP (RID_INLINE, specbits))); + publicp = (! friendp + || RIDBIT_SETP (RID_EXTERN, specbits) + || ! (funcdef_flag < 0 || inlinep)); decl = grokfndecl (ctype, type, declarator, - virtualp, flags, quals, - raises, friendp ? -1 : 0, publicp); + virtualp, flags, quals, raises, attrlist, + friendp ? -1 : 0, publicp, inlinep); if (decl == NULL_TREE) return NULL_TREE; + decl = build_decl_attribute_variant (decl, decl_machine_attr); - DECL_INLINE (decl) = inlinep; + if (explicitp == 2) + DECL_NONCONVERTING_P (decl) = 1; } else if (TREE_CODE (type) == METHOD_TYPE) { + /* We only get here for friend declarations of + members of other classes. */ /* All method decls are public, so tell grokfndecl to set TREE_PUBLIC, also. */ decl = grokfndecl (ctype, type, declarator, - virtualp, flags, quals, - raises, friendp ? -1 : 0, 1); + virtualp, flags, quals, raises, attrlist, + friendp ? -1 : 0, 1, 0); if (decl == NULL_TREE) return NULL_TREE; - - DECL_INLINE (decl) = inlinep; - } - else if (TREE_CODE (type) == RECORD_TYPE - && CLASSTYPE_DECLARED_EXCEPTION (type)) - { - /* Handle a class-local exception declaration. */ - decl = build_lang_field_decl (VAR_DECL, declarator, type); - if (ctype == NULL_TREE) - ctype = current_class_type; - return void_type_node; } else if (TYPE_SIZE (type) == NULL_TREE && !staticp && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { - error ("field `%s' has incomplete type", - IDENTIFIER_POINTER (declarator)); + if (declarator) + cp_error ("field `%D' has incomplete type", declarator); + else + cp_error ("name `%T' has incomplete type", type); /* If we're instantiating a template, tell them which instantiation made the field's type be incomplete. */ @@ -8839,9 +9518,9 @@ grokdeclarator (declarator, declspecs, d && IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (current_class_type))) && declspecs && TREE_VALUE (declspecs) && TREE_TYPE (TREE_VALUE (declspecs)) == type) - error (" in instantiation of template `%s'", - TYPE_NAME_STRING (current_class_type)); - + cp_error (" in instantiation of template `%T'", + current_class_type); + type = error_mark_node; decl = NULL_TREE; } @@ -8906,13 +9585,18 @@ grokdeclarator (declarator, declspecs, d initialize the named nonstatic member.... This (or an initializer list) is the only way to initialize nonstatic const and reference members. */ - else if (flag_ansi || ! constp) + else if (pedantic || ! constp) cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'", constp ? "const member" : "member", declarator); } if (staticp || (constp && initialized)) { + /* ANSI C++ Apr '95 wp 9.2 */ + if (staticp && declarator == current_class_name) + cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class", + declarator); + /* C++ allows static class members. All other work for this is done by grokfield. This VAR_DECL is built by build_lang_field_decl. @@ -8952,7 +9636,7 @@ grokdeclarator (declarator, declspecs, d /* Function declaration not at top level. Storage classes other than `extern' are not allowed and `extern' makes no difference. */ - if (current_binding_level != global_binding_level + if (! toplevel_bindings_p () && ! processing_template_decl && (RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits)) @@ -8987,21 +9671,21 @@ grokdeclarator (declarator, declspecs, d type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type)); - /* Record presence of `static'. In C++, `inline' is like `static'. */ - publicp - = !(RIDBIT_SETP (RID_STATIC, specbits) - || RIDBIT_SETP (RID_INLINE, specbits)); + /* Record presence of `static'. In C++, `inline' implies `static'. */ + publicp = (ctype != NULL_TREE + || RIDBIT_SETP (RID_EXTERN, specbits) + || (!RIDBIT_SETP (RID_STATIC, specbits) + && !RIDBIT_SETP (RID_INLINE, specbits))); decl = grokfndecl (ctype, type, original_name, - virtualp, flags, quals, - raises, + virtualp, flags, quals, raises, attrlist, processing_template_decl ? 0 : friendp ? 2 : 1, - publicp); + publicp, inlinep); if (decl == NULL_TREE) return NULL_TREE; if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c) - DECL_ASSEMBLER_NAME (decl) = declarator; + DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator); if (staticp == 1) { @@ -9014,14 +9698,6 @@ grokdeclarator (declarator, declspecs, d cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl); illegal_static = 1; } - else if (! ctype - && IDENTIFIER_LENGTH (original_name) == 4 - && IDENTIFIER_POINTER (original_name)[0] == 'm' - && ! strcmp (IDENTIFIER_POINTER (original_name), "main")) - { - error ("cannot declare function `main' to have static linkage"); - illegal_static = 1; - } else if (current_function_decl) { /* FIXME need arm citation */ @@ -9035,35 +9711,38 @@ grokdeclarator (declarator, declspecs, d RIDBIT_RESET (RID_STATIC, specbits); } } + } + else + { + /* It's a variable. */ - /* Record presence of `inline', if it is reasonable. */ - if (inlinep) + if (decl_context == CATCHPARM) { - tree last = tree_last (TYPE_ARG_TYPES (type)); + if (ctype) + { + ctype = NULL_TREE; + error ("cannot use `::' in parameter declaration"); + } - if (! ctype - && ! strcmp (IDENTIFIER_POINTER (original_name), "main")) - error ("cannot inline function `main'"); - else if (last && last != void_list_node) - cp_warning ("cannot inline function `%D' which takes `...'", original_name); - else - /* Assume that otherwise the function can be inlined. */ - DECL_INLINE (decl) = 1; + /* A parameter declared as an array of T is really a pointer to T. + One declared as a function is really a pointer to a function. + One declared as a member is really a pointer to member. */ - if (RIDBIT_SETP (RID_EXTERN, specbits)) + if (TREE_CODE (type) == ARRAY_TYPE) { - current_extern_inline = 1; - if (flag_ansi) - pedwarn ("ANSI C++ does not permit `extern inline'"); - } + /* Transfer const-ness of array into that of type pointed to. */ + type = build_pointer_type + (cp_build_type_variant (TREE_TYPE (type), constp, volatilep)); + volatilep = constp = 0; + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + type = build_pointer_type (type); + else if (TREE_CODE (type) == OFFSET_TYPE) + type = build_pointer_type (type); } - } - else - { - /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - decl = grokvardecl (type, declarator, specbits, initialized); + decl = grokvardecl (type, declarator, specbits, initialized, constp); bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); @@ -9072,15 +9751,19 @@ grokdeclarator (declarator, declspecs, d DECL_CONTEXT (decl) = ctype; if (staticp == 1) { - cp_error ("static member `%D' re-declared as static", - decl); + cp_pedwarn ("static member `%D' re-declared as static", decl); staticp = 0; RIDBIT_RESET (RID_STATIC, specbits); } - if (RIDBIT_SETP (RID_EXTERN, specbits)) + if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl)) { - cp_error ("cannot explicitly declare member `%#D' to have extern linkage", - decl); + cp_error ("static member `%D' declared `register'", decl); + RIDBIT_RESET (RID_REGISTER, specbits); + } + if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic) + { + cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage", + decl); RIDBIT_RESET (RID_EXTERN, specbits); } } @@ -9100,6 +9783,9 @@ grokdeclarator (declarator, declspecs, d if (RIDBIT_SETP (RID_EXTERN, specbits)) DECL_THIS_EXTERN (decl) = 1; + if (RIDBIT_SETP (RID_STATIC, specbits)) + DECL_THIS_STATIC (decl) = 1; + /* Record constancy and volatility. */ if (constp) @@ -9125,7 +9811,7 @@ parmlist_is_exprlist (exprs) if (exprs == NULL_TREE || TREE_PARMLIST (exprs)) return 0; - if (current_binding_level == global_binding_level) + if (toplevel_bindings_p ()) { /* At the global level, if these are all identifiers, then it is a parmlist. */ @@ -9280,7 +9966,8 @@ grokparms (first_parm, funcdef_flag) /* @@ May need to fetch out a `raises' here. */ decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl), - PARM, init != NULL_TREE, NULL_TREE); + PARM, init != NULL_TREE, + NULL_TREE, NULL_TREE); if (! decl) continue; type = TREE_TYPE (decl); @@ -9358,7 +10045,8 @@ grokparms (first_parm, funcdef_flag) any_init++; if (TREE_CODE (init) == SAVE_EXPR) PARM_DECL_EXPR (init) = 1; - else if (TREE_CODE (init) == VAR_DECL) + else if (TREE_CODE (init) == VAR_DECL + || TREE_CODE (init) == PARM_DECL) { if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init))) { @@ -9375,12 +10063,15 @@ grokparms (first_parm, funcdef_flag) } else init = require_instantiated_type (type, init, integer_zero_node); - } + } +#if 0 /* This is too early to check; trailing parms might be merged in by + duplicate_decls. */ else if (any_init) { error ("all trailing parameters must have default arguments"); any_error = 1; } +#endif } else init = NULL_TREE; @@ -9765,73 +10456,6 @@ grok_op_properties (decl, virtualp, frie the current frame for the name (since C++ allows new names in any scope.) */ -/* avoid rewriting all callers of xref_tag */ -static int xref_next_defn = 0; - -tree -xref_defn_tag (code_type_node, name, binfo) - tree code_type_node; - tree name, binfo; -{ - tree rv, ncp; - xref_next_defn = 1; - - if (class_binding_level) - { - tree n1; - char *buf; - /* we need to build a new IDENTIFIER_NODE for name which nukes - * the pieces... */ -/* - n1 = IDENTIFIER_LOCAL_VALUE (current_class_name); - if (n1) - n1 = DECL_NAME (n1); - else - n1 = current_class_name; -*/ - n1 = TYPE_NAME (current_class_type); - if (n1) - n1 = DECL_NESTED_TYPENAME(n1); - else - n1 = current_class_name; - - buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1) - + IDENTIFIER_LENGTH (name)); - - sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1), - IDENTIFIER_POINTER (name)); - ncp = get_identifier (buf); -#ifdef SPEW_DEBUG - if (spew_debug) - printf("*** %s ***\n", IDENTIFIER_POINTER (ncp)); -#endif -#if 0 - IDENTIFIER_LOCAL_VALUE (name) = - build_decl (TYPE_DECL, ncp, NULL_TREE); -#endif - rv = xref_tag (code_type_node, name, binfo, 0); - if (! ANON_AGGRNAME_P (name)) - { - register tree type_decl = build_decl (TYPE_DECL, ncp, rv); - SET_DECL_ARTIFICIAL (type_decl); -#ifdef DWARF_DEBUGGING_INFO - /* Mark the TYPE_DECL node created just above as a gratuitous one - so that dwarfout.c will know not to generate a TAG_typedef DIE - for it. */ - if (write_symbols == DWARF_DEBUG) - DECL_IGNORED_P (type_decl) = 1; -#endif /* DWARF_DEBUGGING_INFO */ - pushdecl_nonclass_level (type_decl); - } - } - else - { - rv = xref_tag (code_type_node, name, binfo, 0); - } - xref_next_defn = 0; - return rv; -} - tree xref_tag (code_type_node, name, binfo, globalize) tree code_type_node; @@ -9841,7 +10465,7 @@ xref_tag (code_type_node, name, binfo, g enum tag_types tag_code; enum tree_code code; int temp = 0; - int i, len; + int i; register tree ref, t; struct binding_level *b = inner_binding_level; @@ -9850,19 +10474,11 @@ xref_tag (code_type_node, name, binfo, g { case record_type: case class_type: - case exception_type: case signature_type: code = RECORD_TYPE; - len = list_length (binfo); break; case union_type: code = UNION_TYPE; - if (binfo) - { - cp_error ("derived union `%T' invalid", name); - binfo = NULL_TREE; - } - len = 0; break; case enum_type: code = ENUMERAL_TYPE; @@ -9877,18 +10493,12 @@ xref_tag (code_type_node, name, binfo, g if (t && TREE_CODE (t) != code) t = NULL_TREE; - if (xref_next_defn) + if (! globalize) { /* If we know we are defining this tag, only look it up in this scope * and don't try to find it as a type. */ - xref_next_defn = 0; - if (t && TYPE_CONTEXT(t)) - { - if (TREE_MANGLED (name)) - ref = t; - else - ref = lookup_tag (code, name, b, 1); - } + if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name)) + ref = t; else ref = lookup_tag (code, name, b, 1); } @@ -9949,17 +10559,6 @@ xref_tag (code_type_node, name, binfo, g if (flag_cadillac) cadillac_start_enum (ref); } - else if (tag_code == exception_type) - { - ref = make_lang_type (code); - /* Enable us to recognize when an exception type is created in - class context. To do nested classes correctly, this should - probably be cleared out when we leave this class's scope. */ - CLASSTYPE_DECLARED_EXCEPTION (ref) = 1; - pushtag (name, ref, globalize); - if (flag_cadillac) - cadillac_start_struct (ref); - } else { struct binding_level *old_b = class_binding_level; @@ -9990,23 +10589,13 @@ xref_tag (code_type_node, name, binfo, g } else { - if (IS_AGGR_TYPE_CODE (code)) - { - if (IS_AGGR_TYPE (ref) - && ((tag_code == exception_type) - != (CLASSTYPE_DECLARED_EXCEPTION (ref) == 1))) - { - cp_error ("type `%T' is both exception and aggregate type", ref); - CLASSTYPE_DECLARED_EXCEPTION (ref) = (tag_code == exception_type); - } - } - /* If it no longer looks like a nested type, make sure it's in global scope. */ if (b == global_binding_level && !class_binding_level && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE) IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref); +#if 0 if (binfo) { tree tt1 = binfo; @@ -10029,128 +10618,11 @@ xref_tag (code_type_node, name, binfo, g build them on the permanent obstack. */ end_temporary_allocation (); } +#endif } if (binfo) - { - /* In the declaration `A : X, Y, ... Z' we mark all the types - (A, X, Y, ..., Z) so we can check for duplicates. */ - tree binfos; - - SET_CLASSTYPE_MARKED (ref); - BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len); - - for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) - { - /* The base of a derived struct is public by default. */ - int via_public - = (TREE_PURPOSE (binfo) == (tree)access_public - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || (tag_code != class_type - && (TREE_PURPOSE (binfo) == (tree)access_default - || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); - int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; - int via_virtual - = (TREE_PURPOSE (binfo) == (tree)access_private_virtual - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || TREE_PURPOSE (binfo) == (tree)access_default_virtual); - tree basetype = TREE_TYPE (TREE_VALUE (binfo)); - tree base_binfo; - - GNU_xref_hier (IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (TREE_VALUE (binfo)), - via_public, via_virtual, 0); - - if (basetype && TREE_CODE (basetype) == TYPE_DECL) - basetype = TREE_TYPE (basetype); - if (!basetype || TREE_CODE (basetype) != RECORD_TYPE) - { - error ("base type `%s' fails to be a struct or class type", - IDENTIFIER_POINTER (TREE_VALUE (binfo))); - continue; - } -#if 1 - /* This code replaces similar code in layout_basetypes. */ - else if (TYPE_SIZE (basetype) == NULL_TREE) - { - cp_error ("base class `%T' has incomplete type", basetype); - continue; - } -#endif - else - { - if (CLASSTYPE_MARKED (basetype)) - { - if (basetype == ref) - cp_error ("recursive type `%T' undefined", basetype); - else - cp_error ("duplicate base type `%T' invalid", basetype); - continue; - } - - /* Note that the BINFO records which describe individual - inheritances are *not* shared in the lattice! They - cannot be shared because a given baseclass may be - inherited with different `accessibility' by different - derived classes. (Each BINFO record describing an - individual inheritance contains flags which say what - the `accessibility' of that particular inheritance is.) */ - - base_binfo = make_binfo (integer_zero_node, basetype, - TYPE_BINFO_VTABLE (basetype), - TYPE_BINFO_VIRTUALS (basetype), NULL_TREE); - - TREE_VEC_ELT (binfos, i) = base_binfo; - TREE_VIA_PUBLIC (base_binfo) = via_public; - TREE_VIA_PROTECTED (base_binfo) = via_protected; - TREE_VIA_VIRTUAL (base_binfo) = via_virtual; - BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); - - SET_CLASSTYPE_MARKED (basetype); -#if 0 -/* XYZZY TEST VIRTUAL BASECLASSES */ -if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE - && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) - && via_virtual == 0) - { - warning ("making type `%s' a virtual baseclass", - TYPE_NAME_STRING (basetype)); - via_virtual = 1; - } -#endif - /* We are free to modify these bits because they are meaningless - at top level, and BASETYPE is a top-level type. */ - if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) - { - TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; - TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; - } - - TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); - TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); - TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); - CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); - i += 1; - } - } - if (i) - TREE_VEC_LENGTH (binfos) = i; - else - BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE; - - if (i > 1) - TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; - else if (i == 1) - TYPE_USES_MULTIPLE_INHERITANCE (ref) - = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0))); - if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) - TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; - - /* Unmark all the types. */ - while (--i >= 0) - CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i))); - CLEAR_CLASSTYPE_MARKED (ref); - } + xref_basetypes (code_type_node, name, ref, binfo); just_return: @@ -10171,6 +10643,145 @@ if (CLASSTYPE_N_BASECLASSES (basetype) = return ref; } + +void +xref_basetypes (code_type_node, name, ref, binfo) + tree code_type_node; + tree name, ref; + tree binfo; +{ + /* In the declaration `A : X, Y, ... Z' we mark all the types + (A, X, Y, ..., Z) so we can check for duplicates. */ + tree binfos; + int i, len; + enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node); + + if (tag_code == union_type) + { + cp_error ("derived union `%T' invalid", ref); + return; + } + + len = list_length (binfo); + push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref)); + + SET_CLASSTYPE_MARKED (ref); + BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len); + + for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) + { + /* The base of a derived struct is public by default. */ + int via_public + = (TREE_PURPOSE (binfo) == (tree)access_public + || TREE_PURPOSE (binfo) == (tree)access_public_virtual + || (tag_code != class_type + && (TREE_PURPOSE (binfo) == (tree)access_default + || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); + int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; + int via_virtual + = (TREE_PURPOSE (binfo) == (tree)access_private_virtual + || TREE_PURPOSE (binfo) == (tree)access_public_virtual + || TREE_PURPOSE (binfo) == (tree)access_default_virtual); + tree basetype = TREE_TYPE (TREE_VALUE (binfo)); + tree base_binfo; + + GNU_xref_hier (IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (TREE_VALUE (binfo)), + via_public, via_virtual, 0); + + if (basetype && TREE_CODE (basetype) == TYPE_DECL) + basetype = TREE_TYPE (basetype); + if (!basetype || TREE_CODE (basetype) != RECORD_TYPE) + { + cp_error ("base type `%T' fails to be a struct or class type", + TREE_VALUE (binfo)); + continue; + } +#if 1 + /* This code replaces similar code in layout_basetypes. */ + else if (TYPE_INCOMPLETE (basetype)) + { + cp_error ("base class `%T' has incomplete type", basetype); + continue; + } +#endif + else + { + if (CLASSTYPE_MARKED (basetype)) + { + if (basetype == ref) + cp_error ("recursive type `%T' undefined", basetype); + else + cp_error ("duplicate base type `%T' invalid", basetype); + continue; + } + + /* Note that the BINFO records which describe individual + inheritances are *not* shared in the lattice! They + cannot be shared because a given baseclass may be + inherited with different `accessibility' by different + derived classes. (Each BINFO record describing an + individual inheritance contains flags which say what + the `accessibility' of that particular inheritance is.) */ + + base_binfo = make_binfo (integer_zero_node, basetype, + TYPE_BINFO_VTABLE (basetype), + TYPE_BINFO_VIRTUALS (basetype), NULL_TREE); + + TREE_VEC_ELT (binfos, i) = base_binfo; + TREE_VIA_PUBLIC (base_binfo) = via_public; + TREE_VIA_PROTECTED (base_binfo) = via_protected; + TREE_VIA_VIRTUAL (base_binfo) = via_virtual; + BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); + + SET_CLASSTYPE_MARKED (basetype); +#if 0 + /* XYZZY TEST VIRTUAL BASECLASSES */ + if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE + && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) + && via_virtual == 0) + { + warning ("making type `%s' a virtual baseclass", + TYPE_NAME_STRING (basetype)); + via_virtual = 1; + } +#endif + /* We are free to modify these bits because they are meaningless + at top level, and BASETYPE is a top-level type. */ + if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) + { + TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + } + + TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); + TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); + TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); + CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); + i += 1; + } + } + if (i) + TREE_VEC_LENGTH (binfos) = i; + else + BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE; + + if (i > 1) + TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; + else if (i == 1) + TYPE_USES_MULTIPLE_INHERITANCE (ref) + = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0))); + if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + + /* Unmark all the types. */ + while (--i >= 0) + CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i))); + CLEAR_CLASSTYPE_MARKED (ref); + + pop_obstacks (); +} + static tree current_local_enum = NULL_TREE; @@ -10277,30 +10888,25 @@ finish_enum (enumtype, values) int highprec = min_precision (maxnode, unsignedp); int precision = MAX (lowprec, highprec); - if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node)) - precision = TYPE_PRECISION (integer_type_node); - + TYPE_SIZE (enumtype) = NULL_TREE; - /* - * The following code is unnecessary since the function - * type_promotes_to deals correctly with promotion of enums of - * underlying unsigned types to signed integer types. - * Moreover, it causes an enum bitfield to require one more bit of - * storage than defined by the ANSI/ISO C++ resolution section r.7.2 - * which defines the range of an enum. - */ -#if 0 - /* Unlike the C frontend, we prefer signed types. */ - if (unsignedp && int_fits_type_p (maxnode, type_for_size (precision, 0))) - unsignedp = 0; -#endif + /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */ TYPE_PRECISION (enumtype) = precision; - TYPE_SIZE (enumtype) = NULL_TREE; if (unsignedp) fixup_unsigned_type (enumtype); else fixup_signed_type (enumtype); + + if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node)) + /* Use the width of the narrowest normal C type which is wide enough. */ + TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size + (precision, 1)); + else + TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); + + TYPE_SIZE (enumtype) = 0; + layout_type (enumtype); } if (flag_cadillac) @@ -10486,8 +11092,8 @@ grok_enum_decls (type, decl) @@ something we had previously. */ int -start_function (declspecs, declarator, raises, pre_parsed_p) - tree declarator, declspecs, raises; +start_function (declspecs, declarator, raises, attrs, pre_parsed_p) + tree declspecs, declarator, raises, attrs; int pre_parsed_p; { tree decl1, olddecl; @@ -10506,13 +11112,19 @@ start_function (declspecs, declarator, r current_function_returns_value = 0; current_function_returns_null = 0; warn_about_return_type = 0; - current_extern_inline = 0; + named_labels = 0; + shadowed_labels = 0; current_function_assigns_this = 0; current_function_just_assigned_this = 0; current_function_parms_stored = 0; original_result_rtx = NULL_RTX; current_function_obstack_index = 0; current_function_obstack_usage = 0; + base_init_expr = NULL_TREE; + protect_list = NULL_TREE; + current_base_init_list = NULL_TREE; + current_member_init_list = NULL_TREE; + ctor_label = dtor_label = NULL_TREE; clear_temp_name (); @@ -10540,6 +11152,16 @@ start_function (declspecs, declarator, r cp_error_at ("previous declaration here", IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1))); } + /* This can happen if a template class is instantiated as part of the + specialization of a member function which is defined in the class + template. We should just use the specialization, but for now give an + error. */ + if (DECL_INITIAL (decl1) != NULL_TREE) + { + cp_error_at ("specialization of `%#D' not supported", decl1); + cp_error ("when defined in the class template body", decl1); + } + last_function_parms = DECL_ARGUMENTS (decl1); last_function_parm_tags = NULL_TREE; fntype = TREE_TYPE (decl1); @@ -10562,19 +11184,23 @@ start_function (declspecs, declarator, r doing_friend = 1; } - if ( !(DECL_VINDEX (decl1) - && write_virtuals >= 2 - && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype))) - current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1); - raises = TYPE_RAISES_EXCEPTIONS (fntype); /* In a fcn definition, arg types must be complete. */ require_complete_types_for_parms (last_function_parms); + + /* In case some arg types were completed since the declaration was + parsed, fix up the decls. */ + { + tree t = last_function_parms; + for (; t; t = TREE_CHAIN (t)) + layout_decl (t, 0); + } } else { - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises); + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises, + NULL_TREE); /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0; @@ -10608,7 +11234,7 @@ start_function (declspecs, declarator, r if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) { if (pedantic || warn_return_type) - warning ("return type for `main' changed to integer type"); + pedwarn ("return type for `main' changed to integer type"); TREE_TYPE (decl1) = fntype = default_function_type; } warn_about_return_type = 0; @@ -10649,9 +11275,16 @@ start_function (declspecs, declarator, r TREE_TYPE (decl1) = build_function_type (void_type_node, TYPE_ARG_TYPES (TREE_TYPE (decl1))); - DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype)); + DECL_RESULT (decl1) + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype))); + TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype)); + TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype)); } + if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) + && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype))) + abstract_virtuals_error (decl1, TREE_TYPE (fntype)); + if (warn_about_return_type) warning ("return-type defaults to `int'"); @@ -10679,29 +11312,39 @@ start_function (declspecs, declarator, r else current_function_decl = decl1; + if (DECL_INTERFACE_KNOWN (decl1)) + { + if (DECL_NOT_REALLY_EXTERN (decl1)) + DECL_EXTERNAL (decl1) = 0; + } /* If this function belongs to an interface, it is public. If it belongs to someone else's interface, it is also external. It doesn't matter whether it's inline or not. */ - if (interface_unknown == 0 - && ! TREE_PUBLIC (decl1)) + else if (interface_unknown == 0) { - TREE_PUBLIC (decl1) = 1; - DECL_EXTERNAL (decl1) - = (interface_only - || (DECL_INLINE (decl1) && ! flag_implement_inlines)); + if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) + DECL_EXTERNAL (decl1) + = (interface_only + || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); + else + DECL_EXTERNAL (decl1) = 0; + DECL_NOT_REALLY_EXTERN (decl1) = 0; + DECL_INTERFACE_KNOWN (decl1) = 1; } else { /* This is a definition, not a reference. - So normally clear DECL_EXTERNAL. - However, `extern inline' acts like a declaration except for - defining how to inline. So set DECL_EXTERNAL in that case. */ - DECL_EXTERNAL (decl1) = current_extern_inline; - - DECL_DEFER_OUTPUT (decl1) - = DECL_INLINE (decl1) && ! TREE_PUBLIC (decl1) - && (DECL_FUNCTION_MEMBER_P (decl1) - || DECL_TEMPLATE_INSTANTIATION (decl1)); + So clear DECL_EXTERNAL. */ + DECL_EXTERNAL (decl1) = 0; + + if (DECL_THIS_INLINE (decl1) && ! DECL_INTERFACE_KNOWN (decl1)) + DECL_DEFER_OUTPUT (decl1) = 1; + else + { + DECL_INTERFACE_KNOWN (decl1) = 1; + if (DECL_C_STATIC (decl1)) + TREE_PUBLIC (decl1) = 0; + } } if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) @@ -10716,18 +11359,6 @@ start_function (declspecs, declarator, r } restype = TREE_TYPE (fntype); - pushlevel (0); - current_binding_level->parm_flag = 1; - - /* Save the parm names or decls from this function's declarator - where store_parm_decls will find them. */ - current_function_parms = last_function_parms; - current_function_parm_tags = last_function_parm_tags; - - GNU_xref_function (decl1, current_function_parms); - - make_function_rtl (decl1); - if (ctype) { push_nested_class (ctype, 1); @@ -10741,32 +11372,25 @@ start_function (declspecs, declarator, r parse errors may never get us to that point. Here we keep the consistency between `current_class_type' and `current_class_decl'. */ - current_class_decl = last_function_parms; - my_friendly_assert (current_class_decl != NULL_TREE - && TREE_CODE (current_class_decl) == PARM_DECL, 162); - if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE) - { - tree variant = TREE_TYPE (TREE_TYPE (current_class_decl)); - if (CLASSTYPE_INST_VAR (ctype) == NULL_TREE) - { - /* Can't call build_indirect_ref here, because it has special - logic to return C_C_D given this argument. */ - C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl); - CLASSTYPE_INST_VAR (ctype) = C_C_D; - } - else - { - C_C_D = CLASSTYPE_INST_VAR (ctype); - /* `current_class_decl' is different for every - function we compile. */ - TREE_OPERAND (C_C_D, 0) = current_class_decl; - } - TREE_READONLY (C_C_D) = TYPE_READONLY (variant); - TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (variant); - TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (variant); + tree t = last_function_parms; + + my_friendly_assert (t != NULL_TREE + && TREE_CODE (t) == PARM_DECL, 162); + + if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) + { + int i = suspend_momentary (); + + /* Fool build_indirect_ref. */ + current_class_decl = NULL_TREE; + C_C_D = build_indirect_ref (t, NULL_PTR); + current_class_decl = t; + resume_momentary (i); } else - C_C_D = current_class_decl; + /* We're having a signature pointer here. */ + C_C_D = current_class_decl = t; + } } else @@ -10775,8 +11399,23 @@ start_function (declspecs, declarator, r push_nested_class (DECL_CONTEXT (decl1), 2); else push_memoized_context (0, 1); + current_class_decl = C_C_D = NULL_TREE; } + pushlevel (0); + current_binding_level->parm_flag = 1; + + /* Save the parm names or decls from this function's declarator + where store_parm_decls will find them. */ + current_function_parms = last_function_parms; + current_function_parm_tags = last_function_parm_tags; + + GNU_xref_function (decl1, current_function_parms); + + if (attrs) + cplus_decl_attributes (decl1, NULL_TREE, attrs); + make_function_rtl (decl1); + /* Allocate further tree nodes temporarily during compilation of this function only. Tiemann moved up here from bottom of fn. */ temporary_allocation (); @@ -10795,9 +11434,15 @@ start_function (declspecs, declarator, r restype = integer_type_node; } if (DECL_RESULT (decl1) == NULL_TREE) - DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype); + { + DECL_RESULT (decl1) + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); + TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype); + TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype); + } - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))) + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1)) + && DECL_LANGUAGE (decl1) == lang_cplusplus) { dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ctor_label = NULL_TREE; @@ -10817,6 +11462,30 @@ start_function (declspecs, declarator, r return 1; } +void +expand_start_early_try_stmts () +{ + rtx insns; + start_sequence (); + expand_start_try_stmts (); + insns = get_insns (); + end_sequence (); + store_in_parms (insns); +} + +void +store_in_parms (insns) + rtx insns; +{ + rtx last_parm_insn; + + last_parm_insn = get_first_nonparm_insn (); + if (last_parm_insn == NULL_RTX) + emit_insns (insns); + else + emit_insns_before (insns, previous_insn (last_parm_insn)); +} + /* Store the parameter declarations into the current function declaration. This is called after parsing the parameter declarations, before digesting the body of the function. @@ -10841,7 +11510,7 @@ store_parm_decls () then CONST_DECLs for foo and bar are put here. */ tree nonparms = NULL_TREE; - if (current_binding_level == global_binding_level) + if (toplevel_bindings_p ()) fatal ("parse errors have confused me too much"); /* Initialize RTL machinery. */ @@ -10906,7 +11575,7 @@ store_parm_decls () if (cleanup) { expand_decl (parm); - if (! expand_decl_cleanup (parm, cleanup)) + if (! cp_expand_decl_cleanup (parm, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", parm); parms_have_cleanups = 1; @@ -10956,7 +11625,7 @@ store_parm_decls () if (flag_gc) { maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node); - if (! expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup)) + if (! cp_expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup)) cp_error ("parser lost in parsing declaration of `%D'", fndecl); } @@ -10972,9 +11641,31 @@ store_parm_decls () if (flag_gc) expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE), 0, VOIDmode, 0); - - if (flag_dossier) +#if 0 + /* done at a different time */ + if (flag_rtti) output_builtin_tdesc_entries (); +#endif + } + + /* Take care of exception handling things. */ + if (flag_handle_exceptions) + { + rtx insns; + start_sequence (); + + /* Mark the start of a stack unwinder if we need one. */ + start_eh_unwinder (); + + /* Do the starting of the exception specifications, if we have any. */ + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) + expand_start_eh_spec (); + + insns = get_insns (); + end_sequence (); + + if (insns) + store_in_parms (insns); } } @@ -10986,7 +11677,7 @@ store_return_init (return_id, init) { tree decl = DECL_RESULT (current_function_decl); - if (flag_ansi) + if (pedantic) /* Give this error as many times as there are occurrences, so that users can use Emacs compilation buffers to find and fix all such places. */ @@ -11022,10 +11713,10 @@ store_return_init (return_id, init) DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); } - /* Let `finish_decl' know that this initializer is ok. */ + /* Let `cp_finish_decl' know that this initializer is ok. */ DECL_INITIAL (decl) = init; pushdecl (decl); - finish_decl (decl, init, 0, 0); + cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } } @@ -11043,13 +11734,14 @@ store_return_init (return_id, init) constructors. */ void -finish_function (lineno, call_poplevel) +finish_function (lineno, call_poplevel, nested) int lineno; int call_poplevel; + int nested; { register tree fndecl = current_function_decl; tree fntype, ctype = NULL_TREE; - rtx head, last_parm_insn, mark; + rtx last_parm_insn, insns; /* Label to use if this function is supposed to return a value. */ tree no_return_label = NULL_TREE; tree decls = NULL_TREE; @@ -11103,7 +11795,7 @@ finish_function (lineno, call_poplevel) 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 { @@ -11111,12 +11803,9 @@ finish_function (lineno, call_poplevel) /* If this destructor is empty, then we don't need to check whether `this' is NULL in some cases. */ - mark = get_last_insn (); - last_parm_insn = get_first_nonparm_insn (); - if ((flag_this_is_variable & 1) == 0) ok_to_optimize_dtor = 1; - else if (mark == last_parm_insn) + else if (get_last_insn () == get_first_nonparm_insn ()) ok_to_optimize_dtor = (n_baseclasses == 0 || (n_baseclasses == 1 @@ -11181,8 +11870,8 @@ finish_function (lineno, call_poplevel) { if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) { - tree ptr = convert_pointer_to_vbase (vbases, current_class_decl); - expand_expr_stmt (build_delete (TYPE_POINTER_TO (BINFO_TYPE (vbases)), + tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl); + expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)), ptr, integer_zero_node, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0)); } @@ -11206,7 +11895,7 @@ finish_function (lineno, call_poplevel) exprstmt = build_method_call (build_indirect_ref - (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), + (build1 (NOP_EXPR, build_pointer_type (current_class_type), error_mark_node), NULL_PTR), ansi_opname[(int) DELETE_EXPR], @@ -11234,12 +11923,8 @@ finish_function (lineno, call_poplevel) /* Back to the top of destructor. */ /* Dont execute destructor code if `this' is NULL. */ - mark = get_last_insn (); - last_parm_insn = get_first_nonparm_insn (); - if (last_parm_insn == NULL_RTX) - last_parm_insn = mark; - else - last_parm_insn = previous_insn (last_parm_insn); + + start_sequence (); /* Make all virtual function table pointers in non-virtual base classes point to CURRENT_CLASS_TYPE's virtual function @@ -11253,8 +11938,18 @@ finish_function (lineno, call_poplevel) current_class_decl, integer_zero_node, 1); expand_start_cond (cond, 0); } - if (mark != get_last_insn ()) - reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); + + insns = get_insns (); + end_sequence (); + + last_parm_insn = get_first_nonparm_insn (); + if (last_parm_insn == NULL_RTX) + last_parm_insn = get_last_insn (); + else + last_parm_insn = previous_insn (last_parm_insn); + + emit_insns_after (insns, last_parm_insn); + if (! ok_to_optimize_dtor) expand_end_cond (); } @@ -11266,6 +11961,7 @@ finish_function (lineno, call_poplevel) if (DECL_CONSTRUCTOR_P (current_function_decl)) { + end_protect_partials (); expand_label (ctor_label); ctor_label = NULL_TREE; @@ -11284,7 +11980,7 @@ finish_function (lineno, call_poplevel) current_function_assigns_this = 0; current_function_just_assigned_this = 0; - base_init_insns = NULL_RTX; + base_init_expr = NULL_TREE; } else if (DECL_CONSTRUCTOR_P (fndecl)) { @@ -11307,11 +12003,7 @@ finish_function (lineno, call_poplevel) CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; - /* must keep the first insn safe. */ - head = get_insns (); - - /* this note will come up to the top with us. */ - mark = get_last_insn (); + start_sequence (); if (flag_this_is_variable > 0) { @@ -11328,8 +12020,14 @@ finish_function (lineno, call_poplevel) /* Emit insns from `emit_base_init' which sets up virtual function table pointer(s). */ - emit_insns (base_init_insns); - base_init_insns = NULL_RTX; + if (base_init_expr) + { + expand_expr_stmt (base_init_expr); + base_init_expr = NULL_TREE; + } + + insns = get_insns (); + end_sequence (); /* This is where the body of the constructor begins. If there were no insns in this function body, then the @@ -11339,12 +12037,13 @@ finish_function (lineno, call_poplevel) we don't hold on to it (across emit_base_init). */ last_parm_insn = get_first_nonparm_insn (); if (last_parm_insn == NULL_RTX) - last_parm_insn = mark; + last_parm_insn = get_last_insn (); else last_parm_insn = previous_insn (last_parm_insn); - if (mark != get_last_insn ()) - reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); + emit_insns_after (insns, last_parm_insn); + + end_protect_partials (); /* This is where the body of the constructor ends. */ expand_label (ctor_label); @@ -11352,7 +12051,8 @@ finish_function (lineno, call_poplevel) if (call_poplevel) { - expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0); + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); poplevel (decls != NULL_TREE, 1, 0); } @@ -11380,14 +12080,6 @@ finish_function (lineno, call_poplevel) if (flag_gc) expand_gc_prologue_and_epilogue (); - /* That's the end of the vtable decl's life. Need to mark it such - if doing stupid register allocation. - - Note that current_vtable_decl is really an INDIRECT_REF - on top of a VAR_DECL here. */ - if (obey_regdecls && current_vtable_decl) - use_variable (DECL_RTL (TREE_OPERAND (current_vtable_decl, 0))); - /* If this function is supposed to return a value, ensure that we do not fall into the cleanups by mistake. The end of our function will look like this: @@ -11442,6 +12134,19 @@ finish_function (lineno, call_poplevel) expand_label (no_return_label); } + /* Generate rtl for function exit. */ + expand_function_end (input_filename, lineno, 1); + + if (flag_handle_exceptions) + expand_exception_blocks (); + + /* This must come after expand_function_end because cleanups might + have declarations (from inline functions) that need to go into + this function's blocks. */ + if (current_binding_level->parm_flag != 1) + my_friendly_abort (122); + poplevel (1, 0, 1); + /* reset scope for C++: if we were in the scope of a class, then when we finish this function, we are not longer so. This cannot be done until we know for sure that no more @@ -11455,19 +12160,6 @@ finish_function (lineno, call_poplevel) else pop_memoized_context (1); - /* Generate rtl for function exit. */ - expand_function_end (input_filename, lineno, 1); - - if (flag_handle_exceptions) - expand_exception_blocks(); - - /* This must come after expand_function_end because cleanups might - have declarations (from inline functions) that need to go into - this function's blocks. */ - if (current_binding_level->parm_flag != 1) - my_friendly_abort (122); - poplevel (1, 0, 1); - /* Must mark the RESULT_DECL as being in this function. */ DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl); @@ -11482,43 +12174,16 @@ finish_function (lineno, call_poplevel) /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; - if (DECL_EXTERNAL (fndecl) - /* This function is just along for the ride. If we can make - it inline, that's great. Otherwise, just punt it. */ - && (DECL_INLINE (fndecl) == 0 - || flag_no_inline - || function_cannot_inline_p (fndecl) - /* ??? Compensate for Sun brain damage in dealing with - data segments of PIC code. */ - || (flag_pic - && (DECL_CONSTRUCTOR_P (fndecl) - || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) - && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))))) - - { - extern int rtl_dump_and_exit; - int old_rtl_dump_and_exit = rtl_dump_and_exit; - int inline_spec = DECL_INLINE (fndecl); - - /* This throws away the code for FNDECL. */ - rtl_dump_and_exit = 1; - /* This throws away the memory of the code for FNDECL. */ - if (flag_no_inline) - DECL_INLINE (fndecl) = 0; - rest_of_compilation (fndecl); - rtl_dump_and_exit = old_rtl_dump_and_exit; - DECL_INLINE (fndecl) = inline_spec; - } - else - { - /* Run the optimizers and output the assembler code for this - function. */ - rest_of_compilation (fndecl); - } + /* Run the optimizers and output the assembler code for this function. */ + rest_of_compilation (fndecl); - if (DECL_INLINE (fndecl) && !TREE_ASM_WRITTEN (fndecl) - && DECL_DEFER_OUTPUT (fndecl)) + if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) { + /* Set DECL_EXTERNAL so that assemble_external will be called as + necessary. We'll clear it again in finish_file. */ + if (! DECL_EXTERNAL (fndecl)) + DECL_NOT_REALLY_EXTERN (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 1; mark_inline_for_output (fndecl); } @@ -11554,7 +12219,8 @@ finish_function (lineno, call_poplevel) /* Free all the tree nodes making up this function. */ /* Switch back to allocating nodes permanently until we start another function. */ - permanent_allocation (1); + if (! nested) + permanent_allocation (1); if (flag_cadillac) cadillac_finish_function (fndecl); @@ -11570,9 +12236,21 @@ finish_function (lineno, call_poplevel) DECL_ARGUMENTS (fndecl) = NULL_TREE; } - /* Let the error reporting routines know that we're outside a function. */ - current_function_decl = NULL_TREE; + if (DECL_STATIC_CONSTRUCTOR (fndecl)) + static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors); + if (DECL_STATIC_DESTRUCTOR (fndecl)) + static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors); + + 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; + current_class_decl = NULL_TREE; } /* Create the FUNCTION_DECL for a function definition. @@ -11601,7 +12279,8 @@ tree start_method (declspecs, declarator, raises) tree declarator, declspecs, raises; { - tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises); + tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises, + NULL_TREE); /* Something too ugly to handle. */ if (fndecl == NULL_TREE) @@ -11633,11 +12312,16 @@ start_method (declspecs, declarator, rai return void_type_node; } + DECL_THIS_INLINE (fndecl) = 1; + if (flag_default_inline) DECL_INLINE (fndecl) = 1; if (processing_template_defn) - SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + { + SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + repo_template_used (fndecl); + } /* We read in the parameters on the maybepermanent_obstack, but we won't be getting back to them until after we @@ -11670,7 +12354,7 @@ start_method (declspecs, declarator, rai grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0); } - finish_decl (fndecl, NULL_TREE, NULL_TREE, 0); + cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0, 0); /* Make a place for the parms */ pushlevel (0); @@ -11767,44 +12451,43 @@ void hack_incomplete_structures (type) tree type; { - tree decl; + tree *list; - if (current_binding_level->n_incomplete == 0) + if (current_binding_level->incomplete == NULL_TREE) return; if (!type) /* Don't do this for class templates. */ return; - for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) - if (TREE_TYPE (decl) == type - || (TREE_TYPE (decl) - && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && TREE_TYPE (TREE_TYPE (decl)) == type)) - { - if (TREE_CODE (decl) == TYPE_DECL) - layout_type (TREE_TYPE (decl)); - else - { - int toplevel = global_binding_level == current_binding_level; - if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && TREE_TYPE (TREE_TYPE (decl)) == type) - layout_type (TREE_TYPE (decl)); - layout_decl (decl, 0); - rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); - if (! toplevel) - { - tree cleanup; - expand_decl (decl); - cleanup = maybe_build_cleanup (decl); - expand_decl_init (decl); - if (! expand_decl_cleanup (decl, cleanup)) - cp_error ("parser lost in parsing declaration of `%D'", - decl); - } - } - my_friendly_assert (current_binding_level->n_incomplete > 0, 164); - --current_binding_level->n_incomplete; - } + for (list = ¤t_binding_level->incomplete; *list; ) + { + tree decl = TREE_VALUE (*list); + if (decl && TREE_TYPE (decl) == type + || (TREE_TYPE (decl) + && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == type)) + { + int toplevel = toplevel_bindings_p (); + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == type) + layout_type (TREE_TYPE (decl)); + layout_decl (decl, 0); + rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); + if (! toplevel) + { + tree cleanup; + expand_decl (decl); + cleanup = maybe_build_cleanup (decl); + expand_decl_init (decl); + if (! cp_expand_decl_cleanup (decl, cleanup)) + cp_error ("parser lost in parsing declaration of `%D'", + decl); + } + *list = TREE_CHAIN (*list); + } + else + list = &TREE_CHAIN (*list); + } } /* Nonzero if presently building a cleanup. Needed because @@ -11850,11 +12533,6 @@ maybe_build_cleanup (decl) || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; - /* Use TYPE_MAIN_VARIANT so we don't get a warning about - calling delete on a `const' variable. */ - if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval)))) - rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval); - rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0); if (TYPE_USES_VIRTUAL_BASECLASSES (type) @@ -11936,7 +12614,7 @@ finish_stmt () zones before calling base constructors. */ if (cond_stack || loop_stack || case_stack) return; - emit_insns (base_init_insns); + expand_expr_stmt (base_init_expr); check_base_init (current_class_type); } current_function_assigns_this = 1; @@ -11960,13 +12638,20 @@ revert_static_member_fn (decl, fn, argty tree function = fn ? *fn : TREE_TYPE (*decl); tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function); + if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args)))) + cp_error ("static member function `%#D' declared const", *decl); + if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args)))) + cp_error ("static member function `%#D' declared volatile", *decl); + args = TREE_CHAIN (args); tmp = build_function_type (TREE_TYPE (function), args); tmp = build_type_variant (tmp, TYPE_READONLY (function), TYPE_VOLATILE (function)); - tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp, + tmp = build_exception_variant (tmp, TYPE_RAISES_EXCEPTIONS (function)); TREE_TYPE (*decl) = tmp; + if (DECL_ARGUMENTS (*decl)) + DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl)); DECL_STATIC_FUNCTION_P (*decl) = 1; if (fn) *fn = tmp; @@ -11980,3 +12665,214 @@ id_in_current_class (id) { return !!purpose_member (id, class_binding_level->class_shadowed); } + +struct cp_function +{ + int returns_value; + int returns_null; + int warn_about_return_type; + int assigns_this; + int just_assigned_this; + int parms_stored; + int temp_name_counter; + tree named_labels; + tree shadowed_labels; + tree ctor_label; + tree dtor_label; + tree protect_list; + tree base_init_list; + tree member_init_list; + tree base_init_expr; + tree class_decl; + tree C_C_D; + rtx result_rtx; + struct cp_function *next; + struct binding_level *binding_level; +}; + +struct cp_function *cp_function_chain; + +extern int temp_name_counter; + +/* Save and reinitialize the variables + used during compilation of a C++ function. */ + +void +push_cp_function_context (context) + tree context; +{ + struct cp_function *p + = (struct cp_function *) xmalloc (sizeof (struct cp_function)); + + push_function_context_to (context); + + p->next = cp_function_chain; + cp_function_chain = p; + + p->named_labels = named_labels; + p->shadowed_labels = shadowed_labels; + p->returns_value = current_function_returns_value; + p->returns_null = current_function_returns_null; + p->warn_about_return_type = warn_about_return_type; + p->binding_level = current_binding_level; + p->ctor_label = ctor_label; + p->dtor_label = dtor_label; + p->assigns_this = current_function_assigns_this; + p->just_assigned_this = current_function_just_assigned_this; + p->parms_stored = current_function_parms_stored; + p->result_rtx = original_result_rtx; + p->base_init_expr = base_init_expr; + p->protect_list = protect_list; + p->temp_name_counter = temp_name_counter; + p->base_init_list = current_base_init_list; + p->member_init_list = current_member_init_list; + p->class_decl = current_class_decl; + p->C_C_D = C_C_D; +} + +/* Restore the variables used during compilation of a C++ function. */ + +void +pop_cp_function_context (context) + tree context; +{ + struct cp_function *p = cp_function_chain; + tree link; + + /* Bring back all the labels that were shadowed. */ + for (link = shadowed_labels; link; link = TREE_CHAIN (link)) + if (DECL_NAME (TREE_VALUE (link)) != 0) + SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)), + TREE_VALUE (link)); + +#if 0 + if (DECL_SAVED_INSNS (current_function_decl) == 0) + { + /* Stop pointing to the local nodes about to be freed. */ + /* But DECL_INITIAL must remain nonzero so we know this + was an actual function definition. */ + DECL_INITIAL (current_function_decl) = error_mark_node; + DECL_ARGUMENTS (current_function_decl) = 0; + } +#endif + + pop_function_context_from (context); + + cp_function_chain = p->next; + + named_labels = p->named_labels; + shadowed_labels = p->shadowed_labels; + current_function_returns_value = p->returns_value; + current_function_returns_null = p->returns_null; + warn_about_return_type = p->warn_about_return_type; + current_binding_level = p->binding_level; + ctor_label = p->ctor_label; + dtor_label = p->dtor_label; + protect_list = p->protect_list; + current_function_assigns_this = p->assigns_this; + current_function_just_assigned_this = p->just_assigned_this; + current_function_parms_stored = p->parms_stored; + original_result_rtx = p->result_rtx; + base_init_expr = p->base_init_expr; + temp_name_counter = p->temp_name_counter; + current_base_init_list = p->base_init_list; + current_member_init_list = p->member_init_list; + current_class_decl = p->class_decl; + C_C_D = p->C_C_D; + + free (p); +} + +/* FSF LOCAL dje prefix attributes */ +/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two + lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE). + + The head of the declspec list is stored in DECLSPECS. + The head of the attribute list is stored in PREFIX_ATTRIBUTES. + + Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of + the list elements. We drop the containing TREE_LIST nodes and link the + resulting attributes together the way decl_attributes expects them. */ + +void +split_specs_attrs (specs_attrs, declspecs, prefix_attributes) + tree specs_attrs; + tree *declspecs, *prefix_attributes; +{ + tree t, s, a, next, specs, attrs; + + /* This can happen in c++ (eg: decl: typespec initdecls ';'). */ + if (specs_attrs != NULL_TREE + && TREE_CODE (specs_attrs) != TREE_LIST) + { + *declspecs = specs_attrs; + *prefix_attributes = NULL_TREE; + return; + } + + /* Remember to keep the lists in the same order, element-wise. */ + + specs = s = NULL_TREE; + attrs = a = NULL_TREE; + for (t = specs_attrs; t; t = next) + { + next = TREE_CHAIN (t); + /* Declspecs have a non-NULL TREE_VALUE. */ + if (TREE_VALUE (t) != NULL_TREE) + { + if (specs == NULL_TREE) + specs = s = t; + else + { + TREE_CHAIN (s) = t; + s = t; + } + } + else + { + if (attrs == NULL_TREE) + attrs = a = TREE_PURPOSE (t); + else + { + TREE_CHAIN (a) = TREE_PURPOSE (t); + a = TREE_PURPOSE (t); + } + } + } + + /* Terminate the lists. */ + if (s != NULL_TREE) + TREE_CHAIN (s) = NULL_TREE; + if (a != NULL_TREE) + TREE_CHAIN (a) = NULL_TREE; + + /* All done. */ + *declspecs = specs; + *prefix_attributes = attrs; +} + +/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes. + This function is used by the parser when a rule will accept attributes + in a particular position, but we don't want to support that just yet. + + A warning is issued for every ignored attribute. */ + +tree +strip_attrs (specs_attrs) + tree specs_attrs; +{ + tree specs, attrs; + + split_specs_attrs (specs_attrs, &specs, &attrs); + + while (attrs) + { + warning ("`%s' attribute ignored", + IDENTIFIER_POINTER (TREE_PURPOSE (attrs))); + attrs = TREE_CHAIN (attrs); + } + + return specs; +} +/* END FSF LOCAL */ +