diff options
Diffstat (limited to 'contrib/gcc/c-decl.c')
-rw-r--r-- | contrib/gcc/c-decl.c | 7155 |
1 files changed, 2935 insertions, 4220 deletions
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index 00b372e..af6d668 100644 --- a/contrib/gcc/c-decl.c +++ b/contrib/gcc/c-decl.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +16,10 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +/* $FreeBSD$ */ /* Process declarations and symbol lookup for C front end. Also constructs types; the standard scalar types at initialization, @@ -29,7 +31,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "config.h" #include "system.h" #include "coretypes.h" -#include "input.h" #include "tm.h" #include "intl.h" #include "tree.h" @@ -50,17 +51,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "timevar.h" #include "c-common.h" #include "c-pragma.h" -#include "langhooks.h" -#include "tree-mudflap.h" -#include "tree-gimple.h" -#include "diagnostic.h" -#include "tree-dump.h" #include "cgraph.h" #include "hashtab.h" #include "libfuncs.h" #include "except.h" #include "langhooks-def.h" -#include "pointer-set.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -73,14 +68,11 @@ enum decl_context /* Nonzero if we have seen an invalid cross reference to a struct, union, or enum, but not yet printed the message. */ -tree pending_invalid_xref; +tree pending_invalid_xref; /* File and line to appear in the eventual error message. */ location_t pending_invalid_xref_location; -/* True means we've initialized exception handling. */ -bool c_eh_initialized_p; - /* While defining an enum type, this is 1 plus the last enumerator constant value. Note that will do not have to save this or `enum_overflow' around nested function definition since such a definition could only @@ -93,46 +85,64 @@ static tree enum_next_value; static int enum_overflow; -/* The file and line that the prototype came from if this is an - old-style definition; used for diagnostics in - store_parm_decls_oldstyle. */ +/* Parsing a function declarator leaves a list of parameter names + or a chain of parameter decls here. */ -static location_t current_function_prototype_locus; +static tree last_function_parms; + +/* ... and a chain of structure and enum types declared in the + parmlist here. */ -/* Whether this prototype was built-in. */ +static tree last_function_parm_tags; -static bool current_function_prototype_built_in; +/* ... and a chain of all non-parameter declarations (such as + CONST_DECLs from enumerations) here. */ -/* The argument type information of this prototype. */ +static tree last_function_parm_others; -static tree current_function_prototype_arg_types; +/* After parsing the declarator that starts a function definition, + `start_function' puts the list of parameter names or chain of decls here + for `store_parm_decls' to find. */ -/* The argument information structure for the function currently being - defined. */ +static tree current_function_parms; -static struct c_arg_info *current_function_arg_info; +/* Similar, for last_function_parm_tags. */ -/* The obstack on which parser and related data structures, which are - not live beyond their top-level declaration or definition, are - allocated. */ -struct obstack parser_obstack; +static tree current_function_parm_tags; + +/* And for last_function_parm_others. */ + +static tree current_function_parm_others; + +/* Similar, for the file and line that the prototype came from if this is + an old-style definition. */ + +static location_t current_function_prototype_locus; /* The current statement tree. */ static GTY(()) struct stmt_tree_s c_stmt_tree; +/* The current scope statement stack. */ + +static GTY(()) tree c_scope_stmt_stack; + /* State saving variables. */ -tree c_break_label; -tree c_cont_label; +int c_in_iteration_stmt; +int c_in_case_stmt; + +/* A list of external DECLs that appeared at block scope when there was + some other global meaning for that identifier. */ +static GTY(()) tree truly_local_externals; + +/* All the builtins; this is a subset of the entries of global_scope. */ -/* Linked list of TRANSLATION_UNIT_DECLS for the translation units - included in this invocation. Note that the current translation - unit is not included in this list. */ +static GTY(()) tree first_builtin_decl; +static GTY(()) tree last_builtin_decl; -static GTY(()) tree all_translation_units; +/* A DECL for the current file-scope context. */ -/* A list of decls to be made automatically visible in each file scope. */ -static GTY(()) tree visible_builtins; +static GTY(()) tree current_file_decl; /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ @@ -157,115 +167,10 @@ static int warn_about_return_type; /* Nonzero when starting a function declared `extern inline'. */ static int current_extern_inline; - -/* Nonzero when the current toplevel function contains a declaration - of a nested function which is never defined. */ - -static bool undef_nested_function; - -/* True means global_bindings_p should return false even if the scope stack - says we are in file scope. */ -bool c_override_global_bindings_to_false; - -/* Each c_binding structure describes one binding of an identifier to - a decl. All the decls in a scope - irrespective of namespace - are - chained together by the ->prev field, which (as the name implies) - runs in reverse order. All the decls in a given namespace bound to - a given identifier are chained by the ->shadowed field, which runs - from inner to outer scopes. - - The ->decl field usually points to a DECL node, but there are two - exceptions. In the namespace of type tags, the bound entity is a - RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared - identifier is encountered, it is bound to error_mark_node to - suppress further errors about that identifier in the current - function. - - The ->type field stores the type of the declaration in this scope; - if NULL, the type is the type of the ->decl field. This is only of - relevance for objects with external or internal linkage which may - be redeclared in inner scopes, forming composite types that only - persist for the duration of those scopes. In the external scope, - this stores the composite of all the types declared for this - object, visible or not. The ->inner_comp field (used only at file - scope) stores whether an incomplete array type at file scope was - completed at an inner scope to an array size other than 1. - - The depth field is copied from the scope structure that holds this - decl. It is used to preserve the proper ordering of the ->shadowed - field (see bind()) and also for a handful of special-case checks. - Finally, the invisible bit is true for a decl which should be - ignored for purposes of normal name lookup, and the nested bit is - true for a decl that's been bound a second time in an inner scope; - in all such cases, the binding in the outer scope will have its - invisible bit true. */ - -struct c_binding GTY((chain_next ("%h.prev"))) -{ - tree decl; /* the decl bound */ - tree type; /* the type in this scope */ - tree id; /* the identifier it's bound to */ - struct c_binding *prev; /* the previous decl in this scope */ - struct c_binding *shadowed; /* the innermost decl shadowed by this one */ - unsigned int depth : 28; /* depth of this scope */ - BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */ - BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */ - BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */ - /* one free bit */ -}; -#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth) -#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth) -#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/) -#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/) - -#define I_SYMBOL_BINDING(node) \ - (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding) -#define I_SYMBOL_DECL(node) \ - (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0) - -#define I_TAG_BINDING(node) \ - (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding) -#define I_TAG_DECL(node) \ - (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0) - -#define I_LABEL_BINDING(node) \ - (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding) -#define I_LABEL_DECL(node) \ - (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0) - -/* Each C symbol points to three linked lists of c_binding structures. - These describe the values of the identifier in the three different - namespaces defined by the language. */ - -struct lang_identifier GTY(()) -{ - struct c_common_identifier common_id; - struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */ - struct c_binding *tag_binding; /* struct/union/enum tags */ - struct c_binding *label_binding; /* labels */ -}; - -/* Validate c-lang.c's assumptions. */ -extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate -[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1]; - -/* The resulting tree type. */ - -union lang_tree_node - GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *) TREE_CHAIN (&%h.generic)"))) -{ - union tree_node GTY ((tag ("0"), - desc ("tree_node_structure (&%h)"))) - generic; - struct lang_identifier GTY ((tag ("1"))) identifier; -}; - -/* Each c_scope structure describes the complete contents of one - scope. Four scopes are distinguished specially: the innermost or - current scope, the innermost function scope, the file scope (always - the second to outermost) and the outermost or external scope. +/* Each c_scope structure describes the complete contents of one scope. + Three scopes are distinguished specially: the innermost or current + scope, the innermost function scope, and the outermost or file scope. Most declarations are recorded in the current scope. @@ -275,39 +180,20 @@ union lang_tree_node hence the 'innermost' qualifier.) Explicitly declared labels (using the __label__ extension) appear in the current scope. - Being in the file scope (current_scope == file_scope) causes + Being in the global scope (current_scope == global_scope) causes special behavior in several places below. Also, under some conditions the Objective-C front end records declarations in the - file scope even though that isn't the current scope. - - All declarations with external linkage are recorded in the external - scope, even if they aren't visible there; this models the fact that - such declarations are visible to the entire program, and (with a - bit of cleverness, see pushdecl) allows diagnosis of some violations - of C99 6.2.2p7 and 6.2.7p2: + global scope even though that isn't the current scope. - If, within the same translation unit, the same identifier appears - with both internal and external linkage, the behavior is - undefined. + The order of the names, parms, and blocks lists matters, and they + are frequently appended to. To avoid having to walk all the way to + the end of the list on each insertion, or reverse the lists later, + we maintain a pointer to the last list entry for each of the lists. - All declarations that refer to the same object or function shall - have compatible type; otherwise, the behavior is undefined. + The order of the tags, shadowed, and shadowed_tags + lists does not matter, so we just prepend to these lists. */ - Initially only the built-in declarations, which describe compiler - intrinsic functions plus a subset of the standard library, are in - this scope. - - The order of the blocks list matters, and it is frequently appended - to. To avoid having to walk all the way to the end of the list on - each insertion, or reverse the list later, we maintain a pointer to - the last list entry. (FIXME: It should be feasible to use a reversed - list here.) - - The bindings list is strictly in reverse order of declarations; - pop_scope relies on this. */ - - -struct c_scope GTY((chain_next ("%h.outer"))) +struct c_scope GTY(()) { /* The scope containing this one. */ struct c_scope *outer; @@ -315,26 +201,39 @@ struct c_scope GTY((chain_next ("%h.outer"))) /* The next outermost function scope. */ struct c_scope *outer_function; - /* All bindings in this scope. */ - struct c_binding *bindings; + /* All variables, constants, functions, labels, and typedef names. */ + tree names; + tree names_last; + + /* All parameter declarations. Used only in the outermost scope of + a function. */ + tree parms; + tree parms_last; + + /* All structure, union, and enum type tags. */ + tree tags; + + /* For each scope, a list of shadowed outer-scope definitions + to be restored when this scope is popped. + Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and + whose TREE_VALUE is its old definition (a kind of ..._DECL node). */ + tree shadowed; + + /* For each scope, a list of shadowed outer-scope tag definitions + to be restored when this scope is popped. + Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and + whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */ + tree shadowed_tags; /* For each scope (except the global one), a chain of BLOCK nodes for all the scopes that were entered and exited one level down. */ tree blocks; tree blocks_last; - /* The depth of this scope. Used to keep the ->shadowed chain of - bindings sorted innermost to outermost. */ - unsigned int depth : 28; - /* True if we are currently filling this scope with parameter declarations. */ BOOL_BITFIELD parm_flag : 1; - /* True if we saw [*] in this scope. Used to give an error messages - if these appears in a function definition. */ - BOOL_BITFIELD had_vla_unspec : 1; - /* True if we already complained about forward parameter decls in this scope. This prevents double warnings on foo (int a; int b; ...) */ @@ -354,28 +253,20 @@ struct c_scope GTY((chain_next ("%h.outer"))) static GTY(()) struct c_scope *current_scope; +/* A chain of c_scope structures awaiting reuse. */ + +static GTY((deletable (""))) struct c_scope *scope_freelist; + /* The innermost function scope. Ordinary (not explicitly declared) labels, bindings to error_mark_node, and the lazily-created bindings of __func__ and its friends get this scope. */ static GTY(()) struct c_scope *current_function_scope; -/* The C file scope. This is reset for each input translation unit. */ - -static GTY(()) struct c_scope *file_scope; - -/* The outermost scope. This is used for all declarations with - external linkage, and only these, hence the name. */ +/* The outermost scope, corresponding to the C "file scope". This is + created when the compiler is started and exists through the entire run. */ -static GTY(()) struct c_scope *external_scope; - -/* A chain of c_scope structures awaiting reuse. */ - -static GTY((deletable)) struct c_scope *scope_freelist; - -/* A chain of c_binding structures awaiting reuse. */ - -static GTY((deletable)) struct c_binding *binding_freelist; +static GTY(()) struct c_scope *global_scope; /* Append VAR to LIST in scope SCOPE. */ #define SCOPE_LIST_APPEND(scope, list, decl) do { \ @@ -403,7 +294,7 @@ static GTY((deletable)) struct c_binding *binding_freelist; static bool keep_next_level_flag; -/* True means the next call to push_scope will be the outermost scope +/* True means the next call to pushlevel will be the outermost scope of a function body, so do not push a new scope, merely cease expecting parameter decls. */ @@ -411,42 +302,32 @@ static bool next_is_function_body; /* Functions called automatically at the beginning and end of execution. */ -static GTY(()) tree static_ctors; -static GTY(()) tree static_dtors; +tree static_ctors, static_dtors; /* Forward declarations. */ -static tree lookup_name_in_scope (tree, struct c_scope *); -static tree c_make_fname_decl (tree, int); -static tree grokdeclarator (const struct c_declarator *, - struct c_declspecs *, - enum decl_context, bool, tree *); -static tree grokparms (struct c_arg_info *, bool); -static void layout_array_type (tree); - -/* T is a statement. Add it to the statement-tree. This is the - C/ObjC version--C++ has a slightly different version of this - function. */ - -tree -add_stmt (tree t) -{ - enum tree_code code = TREE_CODE (t); - if (EXPR_P (t) && code != LABEL_EXPR) - { - if (!EXPR_HAS_LOCATION (t)) - SET_EXPR_LOCATION (t, input_location); - } - - if (code == LABEL_EXPR || code == CASE_LABEL_EXPR) - STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1; - - /* Add T to the statement-tree. Non-side-effect statements need to be - recorded during statement expressions. */ - append_to_statement_list_force (t, &cur_stmt_list); - - return t; -} +static struct c_scope *make_scope (void); +static void pop_scope (void); +static tree make_label (tree, location_t); +static void bind_label (tree, tree, struct c_scope *); +static void implicit_decl_warning (tree); +static tree lookup_tag (enum tree_code, tree, int); +static tree lookup_name_current_level (tree); +static tree grokdeclarator (tree, tree, enum decl_context, int, tree *); +static tree grokparms (tree, int); +static void layout_array_type (tree); +static void store_parm_decls_newstyle (void); +static void store_parm_decls_oldstyle (void); +static tree c_make_fname_decl (tree, int); +static void c_expand_body_1 (tree, int); +static tree any_external_decl (tree); +static void record_external_decl (tree); +static void warn_if_shadowing (tree, tree); +static void check_bitfield_type_and_width (tree *, tree *, const char *); +static void clone_underlying_type (tree); +static bool flexible_array_type_p (tree); +static hashval_t link_hash_hash (const void *); +static int link_hash_eq (const void *, const void *); /* States indicating how grokdeclarator() should handle declspecs marked with __attribute__((deprecated)). An object declared as @@ -463,93 +344,17 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; void c_print_identifier (FILE *file, tree node, int indent) { - print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4); - print_node (file, "tag", I_TAG_DECL (node), indent + 4); - print_node (file, "label", I_LABEL_DECL (node), indent + 4); + print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4); + print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4); + print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); if (C_IS_RESERVED_WORD (node)) { tree rid = ridpointers[C_RID_CODE (node)]; indent_to (file, indent + 4); - fprintf (file, "rid %p \"%s\"", + fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"", (void *) rid, IDENTIFIER_POINTER (rid)); } } - -/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL, - which may be any of several kinds of DECL or TYPE or error_mark_node, - in the scope SCOPE. */ -static void -bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested) -{ - struct c_binding *b, **here; - - if (binding_freelist) - { - b = binding_freelist; - binding_freelist = b->prev; - } - else - b = GGC_NEW (struct c_binding); - - b->shadowed = 0; - b->decl = decl; - b->id = name; - b->depth = scope->depth; - b->invisible = invisible; - b->nested = nested; - b->inner_comp = 0; - - b->type = 0; - - b->prev = scope->bindings; - scope->bindings = b; - - if (!name) - return; - - switch (TREE_CODE (decl)) - { - case LABEL_DECL: here = &I_LABEL_BINDING (name); break; - case ENUMERAL_TYPE: - case UNION_TYPE: - case RECORD_TYPE: here = &I_TAG_BINDING (name); break; - case VAR_DECL: - case FUNCTION_DECL: - case TYPE_DECL: - case CONST_DECL: - case PARM_DECL: - case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break; - - default: - gcc_unreachable (); - } - - /* Locate the appropriate place in the chain of shadowed decls - to insert this binding. Normally, scope == current_scope and - this does nothing. */ - while (*here && (*here)->depth > scope->depth) - here = &(*here)->shadowed; - - b->shadowed = *here; - *here = b; -} - -/* Clear the binding structure B, stick it on the binding_freelist, - and return the former value of b->prev. This is used by pop_scope - and get_parm_info to iterate destructively over all the bindings - from a given scope. */ -static struct c_binding * -free_binding_and_advance (struct c_binding *b) -{ - struct c_binding *prev = b->prev; - - memset (b, 0, sizeof (struct c_binding)); - b->prev = binding_freelist; - binding_freelist = b; - - return prev; -} - /* Hook called at end of compilation to assume 1 elt for a file-scope tentative array defn that wasn't complete before. */ @@ -562,22 +367,56 @@ c_finish_incomplete_decl (tree decl) tree type = TREE_TYPE (decl); if (type != error_mark_node && TREE_CODE (type) == ARRAY_TYPE - && !DECL_EXTERNAL (decl) + && ! DECL_EXTERNAL (decl) && TYPE_DOMAIN (type) == 0) { - warning (0, "array %q+D assumed to have one element", decl); + warning ("%Jarray '%D' assumed to have one element", decl, decl); - complete_array_type (&TREE_TYPE (decl), NULL_TREE, true); + complete_array_type (type, NULL_TREE, 1); layout_decl (decl, 0); } } } +/* Reuse or create a struct for this scope. */ + +static struct c_scope * +make_scope (void) +{ + struct c_scope *result; + if (scope_freelist) + { + result = scope_freelist; + scope_freelist = result->outer; + } + else + result = ggc_alloc_cleared (sizeof (struct c_scope)); + + return result; +} + +/* Remove the topmost scope from the stack and add it to the + free list, updating current_function_scope if necessary. */ + +static void +pop_scope (void) +{ + struct c_scope *scope = current_scope; + + current_scope = scope->outer; + if (scope->function_body) + current_function_scope = scope->outer_function; + + memset (scope, 0, sizeof (struct c_scope)); + scope->outer = scope_freelist; + scope_freelist = scope; +} + /* The Objective-C front-end often needs to determine the current scope. */ void * -objc_get_current_scope (void) +get_current_scope (void) { return current_scope; } @@ -589,27 +428,30 @@ void objc_mark_locals_volatile (void *enclosing_blk) { struct c_scope *scope; - struct c_binding *b; for (scope = current_scope; scope && scope != enclosing_blk; scope = scope->outer) { - for (b = scope->bindings; b; b = b->prev) - objc_volatilize_decl (b->decl); + tree decl; + for (decl = scope->names; decl; decl = TREE_CHAIN (decl)) + { + DECL_REGISTER (decl) = 0; + TREE_THIS_VOLATILE (decl) = 1; + } /* Do not climb up past the current function. */ if (scope->function_body) break; } } -/* Nonzero if we are currently in file scope. */ +/* Nonzero if we are currently in the global scope. */ int global_bindings_p (void) { - return current_scope == file_scope && !c_override_global_bindings_to_false; + return current_scope == global_scope; } void @@ -626,8 +468,19 @@ declare_parm_level (void) current_scope->parm_flag = true; } +/* Nonzero if currently making parm declarations. */ + +int +in_parm_level_p (void) +{ + return current_scope->parm_flag; +} + +/* Enter a new scope. The dummy parameter is for signature + compatibility with lang_hooks.decls.pushlevel. */ + void -push_scope (void) +pushlevel (int dummy ATTRIBUTE_UNUSED) { if (next_is_function_body) { @@ -652,58 +505,49 @@ push_scope (void) } else { - struct c_scope *scope; - if (scope_freelist) - { - scope = scope_freelist; - scope_freelist = scope->outer; - } - else - scope = GGC_CNEW (struct c_scope); + struct c_scope *scope = make_scope (); scope->keep = keep_next_level_flag; scope->outer = current_scope; - scope->depth = current_scope ? (current_scope->depth + 1) : 0; - - /* Check for scope depth overflow. Unlikely (2^28 == 268,435,456) but - possible. */ - if (current_scope && scope->depth == 0) - { - scope->depth--; - sorry ("GCC supports only %u nested scopes", scope->depth); - } - current_scope = scope; keep_next_level_flag = false; } } -/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT. */ +/* Exit a scope. Restore the state of the identifier-decl mappings + that were in effect when this scope was entered. -static void -set_type_context (tree type, tree context) -{ - for (type = TYPE_MAIN_VARIANT (type); type; - type = TYPE_NEXT_VARIANT (type)) - TYPE_CONTEXT (type) = context; -} + If KEEP is KEEP_YES (1), this scope had explicit declarations, so + create a BLOCK node to record its declarations and subblocks for + debugging output. If KEEP is KEEP_MAYBE, do so only if the names + or tags lists are nonempty. -/* Exit a scope. Restore the state of the identifier-decl mappings - that were in effect when this scope was entered. Return a BLOCK - node containing all the DECLs in this scope that are of interest - to debug info generation. */ + The second parameter is ignored; it is present only for + signature compatibility with lang_hooks.decls.poplevel. + + If FUNCTIONBODY is nonzero, this level is the body of a function, + even if current_scope->function_body is not set. This is used + by language-independent code that generates synthetic functions, + and cannot set current_scope->function_body. + + FIXME: Eliminate the need for all arguments. */ tree -pop_scope (void) +poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody) { struct c_scope *scope = current_scope; - tree block, context, p; - struct c_binding *b; + tree block; + tree decl; + tree p; + + /* The following line does not use |= due to a bug in HP's C compiler. */ + scope->function_body = scope->function_body | functionbody; - bool functionbody = scope->function_body; - bool keep = functionbody || scope->keep || scope->bindings; + if (keep == KEEP_MAYBE) + keep = (scope->names || scope->tags); - c_end_vm_scope (scope->depth); + keep |= scope->keep; + keep |= scope->function_body; /* If appropriate, create a BLOCK to record the decls for the life of this function. */ @@ -711,170 +555,128 @@ pop_scope (void) if (keep) { block = make_node (BLOCK); + BLOCK_VARS (block) = scope->names; BLOCK_SUBBLOCKS (block) = scope->blocks; TREE_USED (block) = 1; + } - /* In each subblock, record that this is its superior. */ - for (p = scope->blocks; p; p = TREE_CHAIN (p)) - BLOCK_SUPERCONTEXT (p) = block; + /* In each subblock, record that this is its superior. */ + for (p = scope->blocks; p; p = TREE_CHAIN (p)) + BLOCK_SUPERCONTEXT (p) = block; - BLOCK_VARS (block) = 0; - } + /* Clear out the variable bindings in this scope. - /* The TYPE_CONTEXTs for all of the tagged types belonging to this - scope must be set so that they point to the appropriate - construct, i.e. either to the current FUNCTION_DECL node, or - else to the BLOCK node we just constructed. + Propagate TREE_ADDRESSABLE from nested functions to their + containing functions. - Note that for tagged types whose scope is just the formal - parameter list for some function type specification, we can't - properly set their TYPE_CONTEXTs here, because we don't have a - pointer to the appropriate FUNCTION_TYPE node readily available - to us. For those cases, the TYPE_CONTEXTs of the relevant tagged - type nodes get set in `grokdeclarator' as soon as we have created - the FUNCTION_TYPE node which will represent the "scope" for these - "parameter list local" tagged types. */ - if (scope->function_body) - context = current_function_decl; - else if (scope == file_scope) - { - tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0); - TREE_CHAIN (file_decl) = all_translation_units; - all_translation_units = file_decl; - context = file_decl; - } - else - context = block; + Issue warnings for unused variables and labels, and errors for + undefined labels, if there are any. */ - /* Clear all bindings in this scope. */ - for (b = scope->bindings; b; b = free_binding_and_advance (b)) + for (p = scope->names; p; p = TREE_CHAIN (p)) { - p = b->decl; switch (TREE_CODE (p)) { case LABEL_DECL: - /* Warnings for unused labels, errors for undefined labels. */ if (TREE_USED (p) && !DECL_INITIAL (p)) { - error ("label %q+D used but not defined", p); + error ("%Jlabel `%D' used but not defined", p, p); DECL_INITIAL (p) = error_mark_node; } else if (!TREE_USED (p) && warn_unused_label) { if (DECL_INITIAL (p)) - warning (0, "label %q+D defined but not used", p); + warning ("%Jlabel `%D' defined but not used", p, p); else - warning (0, "label %q+D declared but not defined", p); + warning ("%Jlabel `%D' declared but not defined", p, p); } - /* Labels go in BLOCK_VARS. */ - TREE_CHAIN (p) = BLOCK_VARS (block); - BLOCK_VARS (block) = p; - gcc_assert (I_LABEL_BINDING (b->id) == b); - I_LABEL_BINDING (b->id) = b->shadowed; - break; - - case ENUMERAL_TYPE: - case UNION_TYPE: - case RECORD_TYPE: - set_type_context (p, context); - /* Types may not have tag-names, in which case the type - appears in the bindings list with b->id NULL. */ - if (b->id) - { - gcc_assert (I_TAG_BINDING (b->id) == b); - I_TAG_BINDING (b->id) = b->shadowed; - } + IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0; break; case FUNCTION_DECL: - /* Propagate TREE_ADDRESSABLE from nested functions to their - containing functions. */ - if (!TREE_ASM_WRITTEN (p) + if (! TREE_ASM_WRITTEN (p) && DECL_INITIAL (p) != 0 && TREE_ADDRESSABLE (p) && DECL_ABSTRACT_ORIGIN (p) != 0 && DECL_ABSTRACT_ORIGIN (p) != p) TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1; - if (!DECL_EXTERNAL (p) - && DECL_INITIAL (p) == 0) - { - error ("nested function %q+D declared but never defined", p); - undef_nested_function = true; - } - goto common_symbol; + goto normal; case VAR_DECL: - /* Warnings for unused variables. */ - if (!TREE_USED (p) - && !TREE_NO_WARNING (p) + /* Keep this in sync with stmt.c:warn_about_unused_variables. + No warnings when the global scope is popped because the + global scope isn't popped for the last translation unit, + so the warnings are done in c_write_global_declaration. */ + if (warn_unused_variable && scope != global_scope + && !TREE_USED (p) && !DECL_IN_SYSTEM_HEADER (p) && DECL_NAME (p) - && !DECL_ARTIFICIAL (p) - && scope != file_scope - && scope != external_scope) - warning (OPT_Wunused_variable, "unused variable %q+D", p); - - if (b->inner_comp) - { - error ("type of array %q+D completed incompatibly with" - " implicit initialization", p); - } - - /* Fall through. */ - case TYPE_DECL: - case CONST_DECL: - common_symbol: - /* All of these go in BLOCK_VARS, but only if this is the - binding in the home scope. */ - if (!b->nested) - { - TREE_CHAIN (p) = BLOCK_VARS (block); - BLOCK_VARS (block) = p; - } - /* If this is the file scope, and we are processing more - than one translation unit in this compilation, set - DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL. - This makes same_translation_unit_p work, and causes - static declarations to be given disambiguating suffixes. */ - if (scope == file_scope && num_in_fnames > 1) - { - DECL_CONTEXT (p) = context; - if (TREE_CODE (p) == TYPE_DECL) - set_type_context (TREE_TYPE (p), context); - } + && !DECL_ARTIFICIAL (p)) + warning ("%Junused variable `%D'", p, p); + /* fall through */ - /* Fall through. */ - /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have - already been put there by store_parm_decls. Unused- - parameter warnings are handled by function.c. - error_mark_node obviously does not go in BLOCK_VARS and - does not get unused-variable warnings. */ - case PARM_DECL: - case ERROR_MARK: - /* It is possible for a decl not to have a name. We get - here with b->id NULL in this case. */ - if (b->id) + default: + normal: + if (DECL_NAME (p)) { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - if (b->shadowed && b->shadowed->type) - TREE_TYPE (b->shadowed->decl) = b->shadowed->type; + if (DECL_EXTERNAL (p) && scope != global_scope) + /* External decls stay in the symbol-value slot but are + inaccessible. */ + C_DECL_INVISIBLE (p) = 1; + else + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0; } break; - - default: - gcc_unreachable (); } } + /* Clear out the parameter bindings in this scope, if any. + Unused-parameter warnings are handled by function.c. */ + for (p = scope->parms; p; p = TREE_CHAIN (p)) + if (DECL_NAME (p)) + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0; - /* Dispose of the block that we just made inside some higher level. */ - if ((scope->function_body || scope == file_scope) && context) + /* Clear out the tag-meanings declared in this scope. + + Set the TYPE_CONTEXTs for all of the tagged types belonging to + this scope so that they point to the appropriate construct, i.e. + either to the current FUNCTION_DECL node, or else to the BLOCK + node we just constructed. + + Note that for tagged types whose scope is just the formal + parameter list for some function type specification, we can't + properly set their TYPE_CONTEXTs here, because we don't have a + pointer to the appropriate FUNCTION_TYPE node readily available + to us. For those cases, the TYPE_CONTEXTs of the relevant tagged + type nodes get set in `grokdeclarator' as soon as we have created + the FUNCTION_TYPE node which will represent the "scope" for these + "parameter list local" tagged types. */ + + decl = scope->function_body ? current_function_decl : block; + for (p = scope->tags; p; p = TREE_CHAIN (p)) { - DECL_INITIAL (context) = block; - BLOCK_SUPERCONTEXT (block) = context; + if (TREE_PURPOSE (p)) + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0; + if (decl) + TYPE_CONTEXT (TREE_VALUE (p)) = decl; } + + /* Restore all name- and label-meanings from outer scopes that were + shadowed by this scope. */ + for (p = scope->shadowed; p; p = TREE_CHAIN (p)) + if (TREE_VALUE (p) && TREE_CODE (TREE_VALUE (p)) == LABEL_DECL) + IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p); + else + IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p); + + /* Restore all tag-meanings from outer scopes that were shadowed by + this scope. */ + for (p = scope->shadowed_tags; p; p = TREE_CHAIN (p)) + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p); + + /* Dispose of the block that we just made inside some higher level. */ + if (scope->function_body && current_function_decl) + DECL_INITIAL (current_function_decl) = block; else if (scope->outer) { if (block) @@ -887,62 +689,9 @@ pop_scope (void) } /* Pop the current scope, and free the structure for reuse. */ - current_scope = scope->outer; - if (scope->function_body) - current_function_scope = scope->outer_function; - - memset (scope, 0, sizeof (struct c_scope)); - scope->outer = scope_freelist; - scope_freelist = scope; - - return block; -} - -void -push_file_scope (void) -{ - tree decl; - - if (file_scope) - return; - - push_scope (); - file_scope = current_scope; - - start_fname_decls (); - - for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl)) - bind (DECL_NAME (decl), decl, file_scope, - /*invisible=*/false, /*nested=*/true); -} - -void -pop_file_scope (void) -{ - /* In case there were missing closebraces, get us back to the global - binding level. */ - while (current_scope != file_scope) - pop_scope (); - - /* __FUNCTION__ is defined at file scope (""). This - call may not be necessary as my tests indicate it - still works without it. */ - finish_fname_decls (); - - /* This is the point to write out a PCH if we're doing that. - In that case we do not want to do anything else. */ - if (pch_file) - { - c_common_write_pch (); - return; - } - - /* Pop off the file scope and close this translation unit. */ pop_scope (); - file_scope = 0; - maybe_apply_pending_pragma_weaks (); - cgraph_finalize_compilation_unit (); + return block; } /* Insert BLOCK at the end of the list of subblocks of the current @@ -955,6 +704,15 @@ insert_block (tree block) TREE_USED (block) = 1; SCOPE_LIST_APPEND (current_scope, blocks, block); } + +/* Set the BLOCK node for the innermost scope (the one we are + currently in). The RTL expansion machinery requires us to provide + this hook, but it is not useful in function-at-a-time mode. */ + +void +set_block (tree block ATTRIBUTE_UNUSED) +{ +} /* Push a definition or a declaration of struct, union or enum tag "name". "type" should be the type node. @@ -963,13 +721,24 @@ insert_block (tree block) Note that the definition may really be just a forward reference. In that case, the TYPE_SIZE will be zero. */ -static void +void pushtag (tree name, tree type) { + struct c_scope *b = current_scope; + /* Record the identifier as the type's name if it has none. */ - if (name && !TYPE_NAME (type)) - TYPE_NAME (type) = name; - bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false); + if (name) + { + if (TYPE_NAME (type) == 0) + TYPE_NAME (type) = name; + + if (IDENTIFIER_TAG_VALUE (name)) + b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name), + b->shadowed_tags); + IDENTIFIER_TAG_VALUE (name) = type; + } + + b->tags = tree_cons (name, type, b->tags); /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the tagged type we just added to the current scope. This fake @@ -981,7 +750,7 @@ pushtag (tree name, tree type) TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); /* An approximation for now, so we can tell this is a function-scope tag. - This will be updated in pop_scope. */ + This will be updated in poplevel. */ TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); } @@ -1009,10 +778,10 @@ match_builtin_function_types (tree newtype, tree oldtype) while (oldargs || newargs) { - if (!oldargs - || !newargs - || !TREE_VALUE (oldargs) - || !TREE_VALUE (newargs) + if (! oldargs + || ! newargs + || ! TREE_VALUE (oldargs) + || ! TREE_VALUE (newargs) || TYPE_MODE (TREE_VALUE (oldargs)) != TYPE_MODE (TREE_VALUE (newargs))) return 0; @@ -1025,9 +794,9 @@ match_builtin_function_types (tree newtype, tree oldtype) return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype)); } -/* Subroutine of diagnose_mismatched_decls. Check for function type +/* Subroutine of diagnose_mismathed_decls. Check for function type mismatch involving an empty arglist vs a nonempty one and give clearer - diagnostics. */ + diagnostics. */ static void diagnose_arglist_conflict (tree newdecl, tree olddecl, tree newtype, tree oldtype) @@ -1035,7 +804,7 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl, tree t; if (TREE_CODE (olddecl) != FUNCTION_DECL - || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype)) + || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT) || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0) || (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0))) @@ -1051,14 +820,14 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl, if (TREE_CHAIN (t) == 0 && TYPE_MAIN_VARIANT (type) != void_type_node) { - inform ("a parameter list with an ellipsis can%'t match " + inform ("a parameter list with an ellipsis can't match " "an empty parameter name list declaration"); break; } if (c_type_promotes_to (type) != type) { - inform ("an argument type that has a default promotion can%'t match " + inform ("an argument type that has a default promotion can't match " "an empty parameter name list declaration"); break; } @@ -1075,7 +844,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) tree newargs, oldargs; int i; -#define END_OF_ARGLIST(t) ((t) == void_type_node) + /* ??? Elsewhere TYPE_MAIN_VARIANT is not used in this context. */ +#define END_OF_ARGLIST(t) (TYPE_MAIN_VARIANT (t) == void_type_node) oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype); newargs = TYPE_ARG_TYPES (newtype); @@ -1086,12 +856,6 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) tree oldargtype = TREE_VALUE (oldargs); tree newargtype = TREE_VALUE (newargs); - if (oldargtype == error_mark_node || newargtype == error_mark_node) - return false; - - oldargtype = TYPE_MAIN_VARIANT (oldargtype); - newargtype = TYPE_MAIN_VARIANT (newargtype); - if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype)) break; @@ -1099,24 +863,23 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) agree on the number of arguments. */ if (END_OF_ARGLIST (oldargtype)) { - error ("prototype for %q+D declares more arguments " - "than previous old-style definition", newdecl); + error ("%Jprototype for '%D' declares more arguments " + "than previous old-style definition", newdecl, newdecl); return false; } else if (END_OF_ARGLIST (newargtype)) { - error ("prototype for %q+D declares fewer arguments " - "than previous old-style definition", newdecl); + error ("%Jprototype for '%D' declares fewer arguments " + "than previous old-style definition", newdecl, newdecl); return false; } /* Type for passing arg must be consistent with that declared for the arg. */ - else if (!comptypes (oldargtype, newargtype)) + else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT)) { - error ("prototype for %q+D declares argument %d" - " with incompatible type", - newdecl, i); + error ("%Jprototype for '%D' declares arg %d with incompatible type", + newdecl, newdecl, i); return false; } @@ -1127,8 +890,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) /* If we get here, no errors were found, but do issue a warning for this poor-style construct. */ - warning (0, "prototype for %q+D follows non-prototype definition", - newdecl); + warning ("%Jprototype for '%D' follows non-prototype definition", + newdecl, newdecl); return true; #undef END_OF_ARGLIST } @@ -1137,16 +900,16 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) first in a pair of mismatched declarations, using the diagnostic function DIAG. */ static void -locate_old_decl (tree decl, void (*diag)(const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2)) +locate_old_decl (tree decl, void (*diag)(const char *, ...)) { if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) ; else if (DECL_INITIAL (decl)) - diag (G_("previous definition of %q+D was here"), decl); + diag (N_("%Jprevious definition of '%D' was here"), decl, decl); else if (C_DECL_IMPLICIT (decl)) - diag (G_("previous implicit declaration of %q+D was here"), decl); + diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl); else - diag (G_("previous declaration of %q+D was here"), decl); + diag (N_("%Jprevious declaration of '%D' was here"), decl, decl); } /* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL. @@ -1164,10 +927,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, tree newtype, oldtype; bool pedwarned = false; bool warned = false; - bool retval = true; - -#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \ - && DECL_EXTERNAL (DECL)) /* If we have error_mark_node for either decl or type, just discard the previous decl - we're in an error cascade already. */ @@ -1182,19 +941,19 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */ if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) { - if (!(TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl) - && !C_DECL_DECLARED_BUILTIN (olddecl))) + if (TREE_CODE (olddecl) != FUNCTION_DECL + || !DECL_BUILT_IN (olddecl) || !C_DECL_INVISIBLE (olddecl)) { - error ("%q+D redeclared as different kind of symbol", newdecl); + error ("%J'%D' redeclared as different kind of symbol", + newdecl, newdecl); locate_old_decl (olddecl, error); } else if (TREE_PUBLIC (newdecl)) - warning (0, "built-in function %q+D declared as non-function", - newdecl); - else - warning (OPT_Wshadow, "declaration of %q+D shadows " - "a built-in function", newdecl); + warning ("%Jbuilt-in function '%D' declared as non-function", + newdecl, newdecl); + else if (warn_shadow) + warning ("%Jshadowing built-in function '%D'", + newdecl, newdecl); return false; } @@ -1202,34 +961,34 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, given scope. */ if (TREE_CODE (olddecl) == CONST_DECL) { - error ("redeclaration of enumerator %q+D", newdecl); + error ("%Jredeclaration of enumerator `%D'", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } - if (!comptypes (oldtype, newtype)) + if (!comptypes (oldtype, newtype, COMPARE_STRICT)) { if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl)) + && DECL_BUILT_IN (olddecl) && C_DECL_INVISIBLE (olddecl)) { /* Accept harmless mismatch in function types. This is for the ffs and fprintf builtins. */ tree trytype = match_builtin_function_types (newtype, oldtype); - if (trytype && comptypes (newtype, trytype)) + if (trytype && comptypes (newtype, trytype, COMPARE_STRICT)) *oldtypep = oldtype = trytype; else { /* If types don't match for a built-in, throw away the built-in. No point in calling locate_old_decl here, it - won't print anything. */ - warning (0, "conflicting types for built-in function %q+D", - newdecl); + won't print anything. */ + warning ("%Jconflicting types for built-in function '%D'", + newdecl, newdecl); return false; } } else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_IS_BUILTIN (olddecl)) + && DECL_SOURCE_LINE (olddecl) == 0) { /* A conflicting function declaration for a predeclared function that isn't actually built in. Objective C uses @@ -1245,32 +1004,17 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node - && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl)) + && C_FUNCTION_IMPLICIT_INT (newdecl)) { - pedwarn ("conflicting types for %q+D", newdecl); + pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl); /* Make sure we keep void as the return type. */ TREE_TYPE (newdecl) = *newtypep = newtype = oldtype; C_FUNCTION_IMPLICIT_INT (newdecl) = 0; pedwarned = true; } - /* Permit void foo (...) to match an earlier call to foo (...) with - no declared type (thus, implicitly int). */ - else if (TREE_CODE (newdecl) == FUNCTION_DECL - && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node - && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node - && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl)) - { - pedwarn ("conflicting types for %q+D", newdecl); - /* Make sure we keep void as the return type. */ - TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype; - pedwarned = true; - } else { - if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype)) - error ("conflicting type qualifiers for %q+D", newdecl); - else - error ("conflicting types for %q+D", newdecl); + error ("%Jconflicting types for '%D'", newdecl, newdecl); diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); locate_old_decl (olddecl, error); return false; @@ -1283,9 +1027,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (TREE_CODE (newdecl) == TYPE_DECL) { if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl)) - return true; /* Allow OLDDECL to continue in use. */ - - error ("redefinition of typedef %q+D", newdecl); + return true; /* allow OLDDECL to continue in use */ + + error ("%Jredefinition of typedef '%D'", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } @@ -1296,7 +1040,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, Multiple definitions are not allowed (6.9p3,5) but GCC permits two definitions if one is 'extern inline' and one is not. The non- extern-inline definition supersedes the extern-inline definition. */ - else if (TREE_CODE (newdecl) == FUNCTION_DECL) { /* If you declare a built-in function name as static, or @@ -1304,39 +1047,28 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, can't validate the argument list) the built-in definition is overridden, but optionally warn this was a bad choice of name. */ if (DECL_BUILT_IN (olddecl) - && !C_DECL_DECLARED_BUILTIN (olddecl) + && C_DECL_INVISIBLE (olddecl) && (!TREE_PUBLIC (newdecl) || (DECL_INITIAL (newdecl) && !TYPE_ARG_TYPES (TREE_TYPE (newdecl))))) { - warning (OPT_Wshadow, "declaration of %q+D shadows " - "a built-in function", newdecl); + if (warn_shadow) + warning ("%Jshadowing built-in function '%D'", newdecl, newdecl); /* Discard the old built-in function. */ return false; } - + if (DECL_INITIAL (newdecl)) { - if (DECL_INITIAL (olddecl)) + if (DECL_INITIAL (olddecl) + && !(DECL_DECLARED_INLINE_P (olddecl) + && DECL_EXTERNAL (olddecl) + && !(DECL_DECLARED_INLINE_P (newdecl) + && DECL_EXTERNAL (newdecl)))) { - /* If both decls are in the same TU and the new declaration - isn't overriding an extern inline reject the new decl. - When we handle c99 style inline rules we'll want to reject - the following: - - DECL_EXTERN_INLINE (olddecl) - && !DECL_EXTERN_INLINE (newdecl) - - if they're in the same translation unit. Until we implement - the full semantics we accept the construct. */ - if (!(DECL_EXTERN_INLINE (olddecl) - && !DECL_EXTERN_INLINE (newdecl)) - && same_translation_unit_p (newdecl, olddecl)) - { - error ("redefinition of %q+D", newdecl); - locate_old_decl (olddecl, error); - return false; - } + error ("%Jredefinition of '%D'", newdecl, newdecl); + locate_old_decl (olddecl, error); + return false; } } /* If we have a prototype after an old-style function definition, @@ -1349,67 +1081,47 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, locate_old_decl (olddecl, error); return false; } - /* A non-static declaration (even an "extern") followed by a - static declaration is undefined behavior per C99 6.2.2p3-5,7. - The same is true for a static forward declaration at block - scope followed by a non-static declaration/definition at file - scope. Static followed by non-static at the same scope is - not undefined behavior, and is the most convenient way to get - some effects (see e.g. what unwind-dw2-fde-glibc.c does to - the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but - we do diagnose it if -Wtraditional. */ + /* Mismatched non-static and static is considered poor style. + We only diagnose static then non-static if -Wtraditional, + because it is the most convenient way to get some effects + (see e.g. what unwind-dw2-fde-glibc.c does to the definition + of _Unwind_Find_FDE in unwind-dw2-fde.c). Revisit? */ if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl)) { - /* Two exceptions to the rule. If olddecl is an extern - inline, or a predeclared function that isn't actually - built in, newdecl silently overrides olddecl. The latter - occur only in Objective C; see also above. (FIXME: Make - Objective C use normal builtins.) */ - if (!DECL_IS_BUILTIN (olddecl) - && !DECL_EXTERN_INLINE (olddecl)) + /* A static function declaration for a predeclared function + that isn't actually built in, silently overrides the + default. Objective C uses these. See also above. + FIXME: Make Objective C use normal builtins. */ + if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_SOURCE_LINE (olddecl) == 0) + return false; + else { - error ("static declaration of %q+D follows " - "non-static declaration", newdecl); - locate_old_decl (olddecl, error); + warning ("%Jstatic declaration of '%D' follows " + "non-static declaration", newdecl, newdecl); + warned = true; } - return false; } - else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)) + else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl) + && warn_traditional) { - if (DECL_CONTEXT (olddecl)) - { - error ("non-static declaration of %q+D follows " - "static declaration", newdecl); - locate_old_decl (olddecl, error); - return false; - } - else if (warn_traditional) - { - warning (OPT_Wtraditional, "non-static declaration of %q+D " - "follows static declaration", newdecl); - warned = true; - } + warning ("%Jnon-static declaration of '%D' follows " + "static declaration", newdecl, newdecl); + warned = true; } } else if (TREE_CODE (newdecl) == VAR_DECL) { /* Only variables can be thread-local, and all declarations must agree on this property. */ - if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl)) - { - /* Nothing to check. Since OLDDECL is marked threadprivate - and NEWDECL does not have a thread-local attribute, we - will merge the threadprivate attribute into NEWDECL. */ - ; - } - else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)) + if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl)) { - if (DECL_THREAD_LOCAL_P (newdecl)) - error ("thread-local declaration of %q+D follows " - "non-thread-local declaration", newdecl); + if (DECL_THREAD_LOCAL (newdecl)) + error ("%Jthread-local declaration of '%D' follows " + "non-thread-local declaration", newdecl, newdecl); else - error ("non-thread-local declaration of %q+D follows " - "thread-local declaration", newdecl); + error ("%Jnon-thread-local declaration of '%D' follows " + "thread-local declaration", newdecl, newdecl); locate_old_decl (olddecl, error); return false; @@ -1418,46 +1130,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* Multiple initialized definitions are not allowed (6.9p3,5). */ if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl)) { - error ("redefinition of %q+D", newdecl); + error ("%Jredefinition of '%D'", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } - /* Objects declared at file scope: if the first declaration had - external linkage (even if it was an external reference) the - second must have external linkage as well, or the behavior is - undefined. If the first declaration had internal linkage, then - the second must too, or else be an external reference (in which - case the composite declaration still has internal linkage). - As for function declarations, we warn about the static-then- - extern case only for -Wtraditional. See generally 6.2.2p3-5,7. */ - if (DECL_FILE_SCOPE_P (newdecl) - && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl)) + /* Objects declared at file scope: if at least one is 'extern', + it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7). */ + if (DECL_FILE_SCOPE_P (newdecl)) { - if (DECL_EXTERNAL (newdecl)) - { - if (!DECL_FILE_SCOPE_P (olddecl)) - { - error ("extern declaration of %q+D follows " - "declaration with no linkage", newdecl); - locate_old_decl (olddecl, error); - return false; - } - else if (warn_traditional) - { - warning (OPT_Wtraditional, "non-static declaration of %q+D " - "follows static declaration", newdecl); - warned = true; - } - } - else + if (!DECL_EXTERNAL (newdecl) + && !DECL_EXTERNAL (olddecl) + && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl)) { if (TREE_PUBLIC (newdecl)) - error ("non-static declaration of %q+D follows " - "static declaration", newdecl); + error ("%Jnon-static declaration of '%D' follows " + "static declaration", newdecl, newdecl); else - error ("static declaration of %q+D follows " - "non-static declaration", newdecl); + error ("%Jstatic declaration of '%D' follows " + "non-static declaration", newdecl, newdecl); locate_old_decl (olddecl, error); return false; @@ -1465,37 +1156,32 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, } /* Two objects with the same name declared at the same block scope must both be external references (6.7p3). */ - else if (!DECL_FILE_SCOPE_P (newdecl)) + else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl) + && (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl))) { if (DECL_EXTERNAL (newdecl)) - { - /* Extern with initializer at block scope, which will - already have received an error. */ - } + error ("%Jextern declaration of '%D' follows " + "declaration with no linkage", newdecl, newdecl); else if (DECL_EXTERNAL (olddecl)) - { - error ("declaration of %q+D with no linkage follows " - "extern declaration", newdecl); - locate_old_decl (olddecl, error); - } + error ("%Jdeclaration of '%D' with no linkage follows " + "extern declaration", newdecl, newdecl); else - { - error ("redeclaration of %q+D with no linkage", newdecl); - locate_old_decl (olddecl, error); - } + error ("%Jredeclaration of '%D' with no linkage", + newdecl, newdecl); + locate_old_decl (olddecl, error); return false; } } /* warnings */ - /* All decls must agree on a visibility. */ - if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS) - && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl) + /* All decls must agree on a non-default visibility. */ + if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT + && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) { - warning (0, "redeclaration of %q+D with different visibility " - "(old visibility preserved)", newdecl); + warning ("%Jredeclaration of '%D' with different visibility " + "(old visibility preserved)", newdecl, newdecl); warned = true; } @@ -1505,56 +1191,70 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_DECLARED_INLINE_P (newdecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) { - warning (OPT_Wattributes, "inline declaration of %qD follows " - "declaration with attribute noinline", newdecl); + warning ("%Jinline declaration of '%D' follows " + "declaration with attribute noinline", newdecl, newdecl); warned = true; } else if (DECL_DECLARED_INLINE_P (olddecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) { - warning (OPT_Wattributes, "declaration of %q+D with attribute " - "noinline follows inline declaration ", newdecl); + warning ("%Jdeclaration of '%D' with attribute noinline follows " + "inline declaration ", newdecl, newdecl); warned = true; } /* Inline declaration after use or definition. ??? Should we still warn about this now we have unit-at-a-time - mode and can get it right? - Definitely don't complain if the decls are in different translation - units. */ - if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl) - && same_translation_unit_p (olddecl, newdecl)) + mode and can get it right? */ + if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)) { if (TREE_USED (olddecl)) { - warning (0, "%q+D declared inline after being called", olddecl); + warning ("%J'%D' declared inline after being called", + olddecl, olddecl); warned = true; } else if (DECL_INITIAL (olddecl)) { - warning (0, "%q+D declared inline after its definition", olddecl); + warning ("%J'%D' declared inline after its definition", + olddecl, olddecl); warned = true; } } } else /* PARM_DECL, VAR_DECL */ { - /* Redeclaration of a parameter is a constraint violation (this is - not explicitly stated, but follows from C99 6.7p3 [no more than - one declaration of the same identifier with no linkage in the - same scope, except type tags] and 6.2.2p6 [parameters have no - linkage]). We must check for a forward parameter declaration, - indicated by TREE_ASM_WRITTEN on the old declaration - this is - an extension, the mandatory diagnostic for which is handled by - mark_forward_parm_decls. */ - + /* Redeclaration of a PARM_DECL is invalid unless this is the + real position of a forward-declared parameter (GCC extension). */ if (TREE_CODE (newdecl) == PARM_DECL && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl))) { - error ("redefinition of parameter %q+D", newdecl); + error ("%Jredefinition of parameter '%D'", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } + + /* These bits are only type qualifiers when applied to objects. */ + if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)) + { + if (TREE_THIS_VOLATILE (newdecl)) + pedwarn ("%Jvolatile declaration of '%D' follows " + "non-volatile declaration", newdecl, newdecl); + else + pedwarn ("%Jnon-volatile declaration of '%D' follows " + "volatile declaration", newdecl, newdecl); + pedwarned = true; + } + if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)) + { + if (TREE_READONLY (newdecl)) + pedwarn ("%Jconst declaration of '%D' follows " + "non-const declaration", newdecl, newdecl); + else + pedwarn ("%Jnon-const declaration of '%D' follows " + "const declaration", newdecl, newdecl); + pedwarned = true; + } } /* Optional warning for completely redundant decls. */ @@ -1564,11 +1264,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, definition. */ && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)) - /* Don't warn about redundant redeclarations of builtins. */ + /* Don't warn about redundant redeclarations of builtins. */ && !(TREE_CODE (newdecl) == FUNCTION_DECL && !DECL_BUILT_IN (newdecl) && DECL_BUILT_IN (olddecl) - && !C_DECL_DECLARED_BUILTIN (olddecl)) + && C_DECL_INVISIBLE (olddecl)) /* Don't warn about an extern followed by a definition. */ && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl)) /* Don't warn about forward parameter decls. */ @@ -1578,18 +1278,15 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !(TREE_CODE (newdecl) == VAR_DECL && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))) { - warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D", - newdecl); + warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl); warned = true; } /* Report location of previous decl/defn in a consistent manner. */ if (warned || pedwarned) - locate_old_decl (olddecl, pedwarned ? pedwarn : warning0); - -#undef DECL_EXTERN_INLINE + locate_old_decl (olddecl, pedwarned ? pedwarn : warning); - return retval; + return true; } /* Subroutine of duplicate_decls. NEWDECL has been found to be @@ -1602,43 +1299,26 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) { int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0); - int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0); - int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0); - - /* For real parm decl following a forward decl, rechain the old decl - in its new location and clear TREE_ASM_WRITTEN (it's not a - forward decl anymore). */ + + /* For real parm decl following a forward decl, return 1 so old decl + will be reused. Only allow this to happen once. */ if (TREE_CODE (newdecl) == PARM_DECL - && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)) + && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl)) { - struct c_binding *b, **here; - - for (here = ¤t_scope->bindings; *here; here = &(*here)->prev) - if ((*here)->decl == olddecl) - goto found; - gcc_unreachable (); - - found: - b = *here; - *here = b->prev; - b->prev = current_scope->bindings; - current_scope->bindings = b; - TREE_ASM_WRITTEN (olddecl) = 0; + return; } DECL_ATTRIBUTES (newdecl) - = targetm.merge_decl_attributes (olddecl, newdecl); + = (*targetm.merge_decl_attributes) (olddecl, newdecl); /* Merge the data types specified in the two decls. */ TREE_TYPE (newdecl) = TREE_TYPE (olddecl) - = composite_type (newtype, oldtype); + = common_type (newtype, oldtype); /* Lay the type out, unless already done. */ - if (!comptypes (oldtype, TREE_TYPE (newdecl))) + if (oldtype != TREE_TYPE (newdecl)) { if (TREE_TYPE (newdecl) != error_mark_node) layout_type (TREE_TYPE (newdecl)); @@ -1661,93 +1341,76 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) } } + /* Keep the old rtl since we can safely use it. */ + COPY_DECL_RTL (olddecl, newdecl); /* Merge the type qualifiers. */ if (TREE_READONLY (newdecl)) TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) - TREE_THIS_VOLATILE (olddecl) = 1; - - /* Merge deprecatedness. */ - if (TREE_DEPRECATED (newdecl)) - TREE_DEPRECATED (olddecl) = 1; - - /* Keep source location of definition rather than declaration and of - prototype rather than non-prototype unless that prototype is - built-in. */ - if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) - || (old_is_prototype && !new_is_prototype - && !C_DECL_BUILTIN_PROTOTYPE (olddecl))) + { + TREE_THIS_VOLATILE (olddecl) = 1; + if (TREE_CODE (newdecl) == VAR_DECL) + make_var_volatile (newdecl); + } + + /* Keep source location of definition rather than declaration. */ + if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl); + /* Merge the unused-warning information. */ + if (DECL_IN_SYSTEM_HEADER (olddecl)) + DECL_IN_SYSTEM_HEADER (newdecl) = 1; + else if (DECL_IN_SYSTEM_HEADER (newdecl)) + DECL_IN_SYSTEM_HEADER (olddecl) = 1; + /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == 0) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - /* Merge the threadprivate attribute. */ - if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl)) - { - DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl); - C_DECL_THREADPRIVATE_P (newdecl) = 1; - } - - if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)) - { - /* Merge the unused-warning information. */ - if (DECL_IN_SYSTEM_HEADER (olddecl)) - DECL_IN_SYSTEM_HEADER (newdecl) = 1; - else if (DECL_IN_SYSTEM_HEADER (newdecl)) - DECL_IN_SYSTEM_HEADER (olddecl) = 1; - - /* Merge the section attribute. - We want to issue an error if the sections conflict but that - must be done later in decl_attributes since we are called - before attributes are assigned. */ - if (DECL_SECTION_NAME (newdecl) == NULL_TREE) - DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); + /* Merge the section attribute. + We want to issue an error if the sections conflict but that must be + done later in decl_attributes since we are called before attributes + are assigned. */ + if (DECL_SECTION_NAME (newdecl) == NULL_TREE) + DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); - /* Copy the assembler name. - Currently, it can only be defined in the prototype. */ - COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); + /* Copy the assembler name. + Currently, it can only be defined in the prototype. */ + COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); - /* Use visibility of whichever declaration had it specified */ - if (DECL_VISIBILITY_SPECIFIED (olddecl)) - { - DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); - DECL_VISIBILITY_SPECIFIED (newdecl) = 1; - } + /* If either declaration has a nondefault visibility, use it. */ + if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT) + DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); - DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); - DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); - DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) - |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); - TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); - TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); - DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); - DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl); - DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl); - } + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); + DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); + DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); + DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) + |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); + TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); + TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); + DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); + DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl); + } - /* Merge the storage class information. */ - merge_weak (newdecl, olddecl); + /* Merge the storage class information. */ + merge_weak (newdecl, 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_NAME (olddecl)) = 0; - } + /* 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_NAME (olddecl)) = 0; } - if (DECL_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); @@ -1755,7 +1418,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) /* An extern decl does not override previous storage class. */ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); - if (!DECL_EXTERNAL (newdecl)) + if (! DECL_EXTERNAL (newdecl)) { DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); DECL_COMMON (newdecl) = DECL_COMMON (olddecl); @@ -1771,13 +1434,13 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) { /* If we're redefining a function previously defined as extern inline, make sure we emit debug info for the inline before we - throw it away, in case it was inlined into a function that - hasn't been written out yet. */ + throw it away, in case it was inlined into a function that hasn't + been written out yet. */ if (new_is_definition && DECL_INITIAL (olddecl)) { if (TREE_USED (olddecl) /* In unit-at-a-time mode we never inline re-defined extern - inline functions. */ + inline functions. */ && !flag_unit_at_a_time && cgraph_function_possibly_inlined_p (olddecl)) (*debug_hooks->outlining_inline_function) (olddecl); @@ -1788,8 +1451,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) } else { - /* If either decl says `inline', this fn is inline, unless - its definition was passed already. */ + /* If either decl says `inline', this fn is inline, + unless its definition was passed already. */ if (DECL_DECLARED_INLINE_P (newdecl) || DECL_DECLARED_INLINE_P (olddecl)) DECL_DECLARED_INLINE_P (newdecl) = 1; @@ -1800,30 +1463,23 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) if (DECL_BUILT_IN (olddecl)) { - /* If redeclaring a builtin function, it stays built in. - But it gets tagged as having been declared. */ + /* If redeclaring a builtin function, it stays built in. */ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); - C_DECL_DECLARED_BUILTIN (newdecl) = 1; - if (new_is_prototype) - C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0; - else - C_DECL_BUILTIN_PROTOTYPE (newdecl) - = C_DECL_BUILTIN_PROTOTYPE (olddecl); } /* Also preserve various other info from the definition. */ - if (!new_is_definition) + if (! new_is_definition) { DECL_RESULT (newdecl) = DECL_RESULT (olddecl); DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); + DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); /* Set DECL_INLINE on the declaration if we've got a body from which to instantiate. */ - if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl)) + if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl)) { DECL_INLINE (newdecl) = 1; DECL_ABSTRACT_ORIGIN (newdecl) @@ -1835,43 +1491,22 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) /* If a previous declaration said inline, mark the definition as inlinable. */ if (DECL_DECLARED_INLINE_P (newdecl) - && !DECL_UNINLINABLE (newdecl)) + && ! DECL_UNINLINABLE (newdecl)) DECL_INLINE (newdecl) = 1; } } /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. - But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */ + But preserve OLDDECL's DECL_UID and C_DECL_INVISIBLE. */ { unsigned olddecl_uid = DECL_UID (olddecl); - tree olddecl_context = DECL_CONTEXT (olddecl); + unsigned olddecl_invisible = C_DECL_INVISIBLE (olddecl); memcpy ((char *) olddecl + sizeof (struct tree_common), (char *) newdecl + sizeof (struct tree_common), - sizeof (struct tree_decl_common) - sizeof (struct tree_common)); - switch (TREE_CODE (olddecl)) - { - case FIELD_DECL: - case VAR_DECL: - case PARM_DECL: - case LABEL_DECL: - case RESULT_DECL: - case CONST_DECL: - case TYPE_DECL: - case FUNCTION_DECL: - memcpy ((char *) olddecl + sizeof (struct tree_decl_common), - (char *) newdecl + sizeof (struct tree_decl_common), - tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common)); - break; - - default: - - memcpy ((char *) olddecl + sizeof (struct tree_decl_common), - (char *) newdecl + sizeof (struct tree_decl_common), - sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common)); - } + sizeof (struct tree_decl) - sizeof (struct tree_common)); DECL_UID (olddecl) = olddecl_uid; - DECL_CONTEXT (olddecl) = olddecl_context; + C_DECL_INVISIBLE (olddecl) = olddecl_invisible; } /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl @@ -1881,7 +1516,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) && (TREE_CODE (olddecl) == FUNCTION_DECL || (TREE_CODE (olddecl) == VAR_DECL && TREE_STATIC (olddecl)))) - make_decl_rtl (olddecl); + make_decl_rtl (olddecl, NULL); } /* Handle when a new declaration NEWDECL has the same name as an old @@ -1894,67 +1529,81 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) static bool duplicate_decls (tree newdecl, tree olddecl) { - tree newtype = NULL, oldtype = NULL; + tree newtype, oldtype; if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype)) - { - /* Avoid `unused variable' and other warnings warnings for OLDDECL. */ - TREE_NO_WARNING (olddecl) = 1; - return false; - } + return false; merge_decls (newdecl, olddecl, newtype, oldtype); return true; } - + -/* Check whether decl-node NEW_DECL shadows an existing declaration. */ +/* Return any external DECL associated with ID, whether or not it is + currently in scope. */ + +static tree +any_external_decl (tree id) +{ + tree decl = IDENTIFIER_SYMBOL_VALUE (id); + tree t; + + if (decl == 0 || TREE_CODE (decl) == ERROR_MARK) + return 0; + else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl)) + return decl; + + t = purpose_member (id, truly_local_externals); + if (t) + return TREE_VALUE (t); + + return 0; +} + +/* Record an external decl DECL. This only does something if a + shadowing decl already exists. */ static void -warn_if_shadowing (tree new_decl) +record_external_decl (tree decl) { - struct c_binding *b; + tree name = DECL_NAME (decl); + if (!IDENTIFIER_SYMBOL_VALUE (name)) + return; - /* Shadow warnings wanted? */ - if (!warn_shadow + truly_local_externals = tree_cons (name, decl, truly_local_externals); +} + +/* Check whether decl-node X shadows an existing declaration. + OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X, + which might be a NULL_TREE. */ +static void +warn_if_shadowing (tree x, tree old) +{ + /* Nothing to shadow? */ + if (old == 0 + /* Shadow warnings not wanted? */ + || !warn_shadow /* No shadow warnings for internally generated vars. */ - || DECL_IS_BUILTIN (new_decl) + || DECL_SOURCE_LINE (x) == 0 /* No shadow warnings for vars made for inlining. */ - || DECL_FROM_INLINE (new_decl)) + || DECL_FROM_INLINE (x) + /* Don't warn about the parm names in function declarator + within a function declarator. + It would be nice to avoid warning in any function + declarator in a declaration, as opposed to a definition, + but there is no way to tell it's not a definition. */ + || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag) + /* Shadow warnings only apply to local variables and parameters. */ + || (TREE_CODE (x) != PARM_DECL && DECL_FILE_SCOPE_P (x))) return; - /* Is anything being shadowed? Invisible decls do not count. */ - for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed) - if (b->decl && b->decl != new_decl && !b->invisible) - { - tree old_decl = b->decl; - - if (old_decl == error_mark_node) - { - warning (OPT_Wshadow, "declaration of %q+D shadows previous " - "non-variable", new_decl); - break; - } - else if (TREE_CODE (old_decl) == PARM_DECL) - warning (OPT_Wshadow, "declaration of %q+D shadows a parameter", - new_decl); - else if (DECL_FILE_SCOPE_P (old_decl)) - warning (OPT_Wshadow, "declaration of %q+D shadows a global " - "declaration", new_decl); - else if (TREE_CODE (old_decl) == FUNCTION_DECL - && DECL_BUILT_IN (old_decl)) - { - warning (OPT_Wshadow, "declaration of %q+D shadows " - "a built-in function", new_decl); - break; - } - else - warning (OPT_Wshadow, "declaration of %q+D shadows a previous local", - new_decl); - - warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl); + if (TREE_CODE (old) == PARM_DECL) + warning ("%Jdeclaration of '%D' shadows a parameter", x, x); + else if (DECL_FILE_SCOPE_P (old)) + warning ("%Jdeclaration of '%D' shadows a global declaration", x, x); + else + warning ("%Jdeclaration of '%D' shadows a previous local", x, x); - break; - } + warning ("%Jshadowed declaration is here", old); } @@ -1974,7 +1623,7 @@ warn_if_shadowing (tree new_decl) translation and get back the corresponding typedef name. For example, given: - typedef struct S MY_TYPE; + typedef struct S MY_TYPE; MY_TYPE object; Later parts of the compiler might only know that `object' was of @@ -2005,7 +1654,7 @@ warn_if_shadowing (tree new_decl) static void clone_underlying_type (tree x) { - if (DECL_IS_BUILTIN (x)) + if (DECL_SOURCE_LINE (x) == 0) { if (TYPE_NAME (TREE_TYPE (x)) == 0) TYPE_NAME (TREE_TYPE (x)) = x; @@ -2015,7 +1664,7 @@ clone_underlying_type (tree x) { tree tt = TREE_TYPE (x); DECL_ORIGINAL_TYPE (x) = tt; - tt = build_variant_type_copy (tt); + tt = build_type_copy (tt); TYPE_NAME (tt) = x; TREE_USED (tt) = TREE_USED (x); TREE_TYPE (x) = tt; @@ -2035,253 +1684,134 @@ pushdecl (tree x) { tree name = DECL_NAME (x); struct c_scope *scope = current_scope; - struct c_binding *b; - bool nested = false; + +#ifdef ENABLE_CHECKING + if (error_mark_node == 0) + /* Called too early. */ + abort (); +#endif /* Functions need the lang_decl data. */ - if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x)) - DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl); - - /* Must set DECL_CONTEXT for everything not at file scope or - DECL_FILE_SCOPE_P won't work. Local externs don't count - unless they have initializers (which generate code). */ - if (current_function_decl - && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL) - || DECL_INITIAL (x) || !DECL_EXTERNAL (x))) + if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x)) + DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_decl)); + + /* A local extern declaration for a function doesn't constitute nesting. + A local auto declaration does, since it's a forward decl + for a nested function coming later. */ + if (current_function_decl == NULL + || ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL) + && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))) + DECL_CONTEXT (x) = current_file_decl; + else DECL_CONTEXT (x) = current_function_decl; - /* If this is of variably modified type, prevent jumping into its - scope. */ - if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == TYPE_DECL) - && variably_modified_type_p (TREE_TYPE (x), NULL_TREE)) - c_begin_vm_scope (scope->depth); - - /* Anonymous decls are just inserted in the scope. */ - if (!name) - { - bind (name, x, scope, /*invisible=*/false, /*nested=*/false); - return x; - } - - /* First, see if there is another declaration with the same name in - the current scope. If there is, duplicate_decls may do all the - work for us. If duplicate_decls returns false, that indicates - two incompatible decls in the same scope; we are to silently - replace the old one (duplicate_decls has issued all appropriate - diagnostics). In particular, we should not consider possible - duplicates in the external scope, or shadowing. */ - b = I_SYMBOL_BINDING (name); - if (b && B_IN_SCOPE (b, scope)) - { - struct c_binding *b_ext, *b_use; - tree type = TREE_TYPE (x); - tree visdecl = b->decl; - tree vistype = TREE_TYPE (visdecl); - if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE - && COMPLETE_TYPE_P (TREE_TYPE (x))) - b->inner_comp = false; - b_use = b; - b_ext = b; - /* If this is an external linkage declaration, we should check - for compatibility with the type in the external scope before - setting the type at this scope based on the visible - information only. */ - if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl)) + if (name) + { + tree old; + + if (warn_nested_externs + && scope != global_scope + && DECL_EXTERNAL (x) + && !DECL_IN_SYSTEM_HEADER (x)) + warning ("nested extern declaration of `%s'", + IDENTIFIER_POINTER (name)); + + old = lookup_name_current_level (name); + if (old && duplicate_decls (x, old)) { - while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext)) - b_ext = b_ext->shadowed; - if (b_ext) + /* For PARM_DECLs, old may be a forward declaration. + If so, we want to remove it from its old location + (in the variables chain) and rechain it in the + location given by the new declaration. */ + if (TREE_CODE (x) == PARM_DECL) { - b_use = b_ext; - if (b_use->type) - TREE_TYPE (b_use->decl) = b_use->type; + tree *p; + for (p = &scope->names; *p; p = &TREE_CHAIN (*p)) + if (*p == old) + { + *p = TREE_CHAIN (old); + SCOPE_LIST_APPEND (scope, parms, old); + break; + } } + return old; } - if (duplicate_decls (x, b_use->decl)) + if (DECL_EXTERNAL (x) || scope == global_scope) { - if (b_use != b) + /* Find and check against a previous, not-in-scope, external + decl for this identifier. (C99 6.2.7p2: All declarations + that refer to the same object or function shall have + compatible type; otherwise, the behavior is undefined.) */ + tree ext = any_external_decl (name); + if (ext) { - /* Save the updated type in the external scope and - restore the proper type for this scope. */ - tree thistype; - if (comptypes (vistype, type)) - thistype = composite_type (vistype, type); - else - thistype = TREE_TYPE (b_use->decl); - b_use->type = TREE_TYPE (b_use->decl); - if (TREE_CODE (b_use->decl) == FUNCTION_DECL - && DECL_BUILT_IN (b_use->decl)) - thistype - = build_type_attribute_variant (thistype, - TYPE_ATTRIBUTES - (b_use->type)); - TREE_TYPE (b_use->decl) = thistype; + if (duplicate_decls (x, ext)) + x = copy_node (ext); } - return b_use->decl; - } - else - goto skip_external_and_shadow_checks; - } - - /* All declarations with external linkage, and all external - references, go in the external scope, no matter what scope is - current. However, the binding in that scope is ignored for - purposes of normal name lookup. A separate binding structure is - created in the requested scope; this governs the normal - visibility of the symbol. - - The binding in the externals scope is used exclusively for - detecting duplicate declarations of the same object, no matter - what scope they are in; this is what we do here. (C99 6.2.7p2: - All declarations that refer to the same object or function shall - have compatible type; otherwise, the behavior is undefined.) */ - if (DECL_EXTERNAL (x) || scope == file_scope) - { - tree type = TREE_TYPE (x); - tree vistype = 0; - tree visdecl = 0; - bool type_saved = false; - if (b && !B_IN_EXTERNAL_SCOPE (b) - && (TREE_CODE (b->decl) == FUNCTION_DECL - || TREE_CODE (b->decl) == VAR_DECL) - && DECL_FILE_SCOPE_P (b->decl)) - { - visdecl = b->decl; - vistype = TREE_TYPE (visdecl); + else + record_external_decl (x); } - if (scope != file_scope - && !DECL_IN_SYSTEM_HEADER (x)) - warning (OPT_Wnested_externs, "nested extern declaration of %qD", x); - while (b && !B_IN_EXTERNAL_SCOPE (b)) - { - /* If this decl might be modified, save its type. This is - done here rather than when the decl is first bound - because the type may change after first binding, through - being completed or through attributes being added. If we - encounter multiple such decls, only the first should have - its type saved; the others will already have had their - proper types saved and the types will not have changed as - their scopes will not have been re-entered. */ - if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved) - { - b->type = TREE_TYPE (b->decl); - type_saved = true; - } - if (B_IN_FILE_SCOPE (b) - && TREE_CODE (b->decl) == VAR_DECL - && TREE_STATIC (b->decl) - && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE - && !TYPE_DOMAIN (TREE_TYPE (b->decl)) - && TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) - && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) - { - /* Array type completed in inner scope, which should be - diagnosed if the completion does not have size 1 and - it does not get completed in the file scope. */ - b->inner_comp = true; - } - b = b->shadowed; - } + if (TREE_CODE (x) == TYPE_DECL) + clone_underlying_type (x); - /* If a matching external declaration has been found, set its - type to the composite of all the types of that declaration. - After the consistency checks, it will be reset to the - composite of the visible types only. */ - if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl)) - && b->type) - TREE_TYPE (b->decl) = b->type; - - /* The point of the same_translation_unit_p check here is, - we want to detect a duplicate decl for a construct like - foo() { extern bar(); } ... static bar(); but not if - they are in different translation units. In any case, - the static does not go in the externals scope. */ - if (b - && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl)) - && duplicate_decls (x, b->decl)) + /* If storing a local value, there may already be one + (inherited). If so, record it for restoration when this + scope ends. Take care not to do this if we are replacing an + older decl in the same scope (i.e. duplicate_decls returned + false, above). */ + if (scope != global_scope) { - tree thistype; - if (vistype) + tree inherited_decl = lookup_name (name); + if (inherited_decl && inherited_decl != old) { - if (comptypes (vistype, type)) - thistype = composite_type (vistype, type); - else - thistype = TREE_TYPE (b->decl); + warn_if_shadowing (x, inherited_decl); + scope->shadowed = tree_cons (name, inherited_decl, + scope->shadowed); } - else - thistype = type; - b->type = TREE_TYPE (b->decl); - if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl)) - thistype - = build_type_attribute_variant (thistype, - TYPE_ATTRIBUTES (b->type)); - TREE_TYPE (b->decl) = thistype; - bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true); - return b->decl; } - else if (TREE_PUBLIC (x)) + + /* Install the new declaration in the requested scope. */ + IDENTIFIER_SYMBOL_VALUE (name) = x; + C_DECL_INVISIBLE (x) = 0; + + /* If x's type is incomplete because it's based on a + structure or union which has not yet been fully declared, + attach it to that structure or union type, so we can go + back and complete the variable declaration later, if the + structure or union gets fully declared. + + If the input is erroneous, we can have error_mark in the type + slot (e.g. "f(void a, ...)") - that doesn't count as an + incomplete type. */ + if (TREE_TYPE (x) != error_mark_node + && !COMPLETE_TYPE_P (TREE_TYPE (x))) { - if (visdecl && !b && duplicate_decls (x, visdecl)) - { - /* An external declaration at block scope referring to a - visible entity with internal linkage. The composite - type will already be correct for this scope, so we - just need to fall through to make the declaration in - this scope. */ - nested = true; - x = visdecl; - } - else - { - bind (name, x, external_scope, /*invisible=*/true, - /*nested=*/false); - nested = true; - } + tree element = TREE_TYPE (x); + + while (TREE_CODE (element) == ARRAY_TYPE) + element = TREE_TYPE (element); + element = TYPE_MAIN_VARIANT (element); + + if ((TREE_CODE (element) == RECORD_TYPE + || TREE_CODE (element) == UNION_TYPE) + && (TREE_CODE (x) != TYPE_DECL + || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE) + && !COMPLETE_TYPE_P (element)) + C_TYPE_INCOMPLETE_VARS (element) + = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element)); } } - if (TREE_CODE (x) != PARM_DECL) - warn_if_shadowing (x); - - skip_external_and_shadow_checks: - if (TREE_CODE (x) == TYPE_DECL) - clone_underlying_type (x); - - bind (name, x, scope, /*invisible=*/false, nested); - - /* If x's type is incomplete because it's based on a - structure or union which has not yet been fully declared, - attach it to that structure or union type, so we can go - back and complete the variable declaration later, if the - structure or union gets fully declared. - - If the input is erroneous, we can have error_mark in the type - slot (e.g. "f(void a, ...)") - that doesn't count as an - incomplete type. */ - if (TREE_TYPE (x) != error_mark_node - && !COMPLETE_TYPE_P (TREE_TYPE (x))) - { - tree element = TREE_TYPE (x); - - while (TREE_CODE (element) == ARRAY_TYPE) - element = TREE_TYPE (element); - element = TYPE_MAIN_VARIANT (element); + if (TREE_CODE (x) == PARM_DECL) + SCOPE_LIST_APPEND (scope, parms, x); + else + SCOPE_LIST_APPEND (scope, names, x); - if ((TREE_CODE (element) == RECORD_TYPE - || TREE_CODE (element) == UNION_TYPE) - && (TREE_CODE (x) != TYPE_DECL - || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE) - && !COMPLETE_TYPE_P (element)) - C_TYPE_INCOMPLETE_VARS (element) - = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element)); - } return x; } -/* Record X as belonging to file scope. +/* Record X as belonging to the global scope (C99 "file scope"). This is used only internally by the Objective-C front end, and is limited to its needs. duplicate_decls is not called; if there is any preexisting decl for this identifier, it is an ICE. */ @@ -2290,117 +1820,50 @@ tree pushdecl_top_level (tree x) { tree name; - bool nested = false; - gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL); + + if (TREE_CODE (x) != VAR_DECL) + abort (); name = DECL_NAME (x); - gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name)); + if (IDENTIFIER_SYMBOL_VALUE (name)) + abort (); - if (TREE_PUBLIC (x)) - { - bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false); - nested = true; - } - if (file_scope) - bind (name, x, file_scope, /*invisible=*/false, nested); + DECL_CONTEXT (x) = current_file_decl; + IDENTIFIER_SYMBOL_VALUE (name) = x; + SCOPE_LIST_APPEND (global_scope, names, x); return x; } -static void -implicit_decl_warning (tree id, tree olddecl) -{ - void (*diag) (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2); - switch (mesg_implicit_function_declaration) - { - case 0: return; - case 1: diag = warning0; break; - case 2: diag = error; break; - default: gcc_unreachable (); - } - - diag (G_("implicit declaration of function %qE"), id); - if (olddecl) - locate_old_decl (olddecl, diag); -} - /* Generate an implicit declaration for identifier FUNCTIONID as a function of type int (). */ tree implicitly_declare (tree functionid) { - struct c_binding *b; - tree decl = 0; - tree asmspec_tree; - - for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed) - { - if (B_IN_SCOPE (b, external_scope)) - { - decl = b->decl; - break; - } - } + tree decl = any_external_decl (functionid); if (decl) { - if (decl == error_mark_node) - return decl; - - /* FIXME: Objective-C has weird not-really-builtin functions - which are supposed to be visible automatically. They wind up - in the external scope because they're pushed before the file - scope gets created. Catch this here and rebind them into the - file scope. */ - if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl)) - { - bind (functionid, decl, file_scope, - /*invisible=*/false, /*nested=*/true); - return decl; - } - else + /* Implicit declaration of a function already declared + (somehow) in a different scope, or as a built-in. + If this is the first time this has happened, warn; + then recycle the old declaration. */ + if (!C_DECL_IMPLICIT (decl)) { - tree newtype = default_function_type; - if (b->type) - TREE_TYPE (decl) = b->type; - /* Implicit declaration of a function already declared - (somehow) in a different scope, or as a built-in. - If this is the first time this has happened, warn; - then recycle the old declaration but with the new type. */ - if (!C_DECL_IMPLICIT (decl)) - { - implicit_decl_warning (functionid, decl); - C_DECL_IMPLICIT (decl) = 1; - } - if (DECL_BUILT_IN (decl)) - { - newtype = build_type_attribute_variant (newtype, - TYPE_ATTRIBUTES - (TREE_TYPE (decl))); - if (!comptypes (newtype, TREE_TYPE (decl))) - { - warning (0, "incompatible implicit declaration of built-in" - " function %qD", decl); - newtype = TREE_TYPE (decl); - } - } - else - { - if (!comptypes (newtype, TREE_TYPE (decl))) - { - error ("incompatible implicit declaration of function %qD", - decl); - locate_old_decl (decl, error); - } - } - b->type = TREE_TYPE (decl); - TREE_TYPE (decl) = newtype; - bind (functionid, decl, current_scope, - /*invisible=*/false, /*nested=*/true); - return decl; + implicit_decl_warning (DECL_NAME (decl)); + if (! DECL_FILE_SCOPE_P (decl)) + warning ("%Jprevious declaration of '%D'", decl, decl); + C_DECL_IMPLICIT (decl) = 1; } + /* If this function is global, then it must already be in the + global scope, so there's no need to push it again. */ + if (current_scope == global_scope) + return decl; + /* If this is a local declaration, make a copy; we can't have + the same DECL listed in two different scopes. */ + return pushdecl (copy_node (decl)); } /* Not seen before. */ @@ -2408,17 +1871,14 @@ implicitly_declare (tree functionid) DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; C_DECL_IMPLICIT (decl) = 1; - implicit_decl_warning (functionid, 0); - asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL); - if (asmspec_tree) - set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree)); + implicit_decl_warning (functionid); /* C89 says implicit declarations are in the innermost block. So we record the decl in the standard fashion. */ decl = pushdecl (decl); /* No need to call objc_check_decl here - it's a function type. */ - rest_of_decl_compilation (decl, 0, 0); + rest_of_decl_compilation (decl, NULL, 0, 0); /* Write a record describing this implicit function declaration to the prototypes file (if requested). */ @@ -2430,38 +1890,51 @@ implicitly_declare (tree functionid) return decl; } +static void +implicit_decl_warning (tree id) +{ + const char *name = IDENTIFIER_POINTER (id); + if (mesg_implicit_function_declaration == 2) + error ("implicit declaration of function `%s'", name); + else if (mesg_implicit_function_declaration == 1) + warning ("implicit declaration of function `%s'", name); +} + /* Issue an error message for a reference to an undeclared variable ID, including a reference to a builtin outside of function-call context. Establish a binding of the identifier to error_mark_node in an appropriate scope, which will suppress further errors for the - same identifier. The error message should be given location LOC. */ + same identifier. */ void -undeclared_variable (tree id, location_t loc) +undeclared_variable (tree id) { static bool already = false; struct c_scope *scope; if (current_function_decl == 0) { - error ("%H%qE undeclared here (not in a function)", &loc, id); + error ("`%s' undeclared here (not in a function)", + IDENTIFIER_POINTER (id)); scope = current_scope; } else { - error ("%H%qE undeclared (first use in this function)", &loc, id); + error ("`%s' undeclared (first use in this function)", + IDENTIFIER_POINTER (id)); - if (!already) + if (! already) { - error ("%H(Each undeclared identifier is reported only once", &loc); - error ("%Hfor each function it appears in.)", &loc); + error ("(Each undeclared identifier is reported only once"); + error ("for each function it appears in.)"); already = true; } - /* If we are parsing old-style parameter decls, current_function_decl - will be nonnull but current_function_scope will be null. */ - scope = current_function_scope ? current_function_scope : current_scope; + scope = current_function_scope; } - bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false); + + scope->shadowed = tree_cons (id, IDENTIFIER_SYMBOL_VALUE (id), + scope->shadowed); + IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node; } /* Subroutine of lookup_label, declare_label, define_label: construct a @@ -2479,6 +1952,20 @@ make_label (tree name, location_t location) return label; } +/* Another subroutine of lookup_label, declare_label, define_label: + set up the binding of name to LABEL_DECL in the given SCOPE. */ + +static void +bind_label (tree name, tree label, struct c_scope *scope) +{ + if (IDENTIFIER_LABEL_VALUE (name)) + scope->shadowed = tree_cons (name, IDENTIFIER_LABEL_VALUE (name), + scope->shadowed); + IDENTIFIER_LABEL_VALUE (name) = label; + + SCOPE_LIST_APPEND (scope, names, label); +} + /* Get the LABEL_DECL corresponding to identifier NAME as a label. Create one if none exists so far for the current function. This is called when a label is used in a goto expression or @@ -2491,14 +1978,15 @@ lookup_label (tree name) if (current_function_decl == 0) { - error ("label %qE referenced outside of any function", name); + error ("label %s referenced outside of any function", + IDENTIFIER_POINTER (name)); return 0; } /* Use a label already defined or ref'd with this name, but not if it is inherited from a containing function and wasn't declared using __label__. */ - label = I_LABEL_DECL (name); + label = IDENTIFIER_LABEL_VALUE (name); if (label && (DECL_CONTEXT (label) == current_function_decl || C_DECLARED_LABEL_FLAG (label))) { @@ -2514,8 +2002,7 @@ lookup_label (tree name) label = make_label (name, input_location); /* Ordinary labels go in the current function scope. */ - bind (name, label, current_function_scope, - /*invisible=*/false, /*nested=*/false); + bind_label (name, label, current_function_scope); return label; } @@ -2523,29 +2010,33 @@ lookup_label (tree name) any that may be inherited from containing functions or containing scopes. This is called for __label__ declarations. */ +/* Note that valid use, if the label being shadowed comes from another + scope in the same function, requires calling declare_nonlocal_label + right away. (Is this still true? -zw 2003-07-17) */ + tree declare_label (tree name) { - struct c_binding *b = I_LABEL_BINDING (name); - tree label; + tree label = IDENTIFIER_LABEL_VALUE (name); + tree dup; /* Check to make sure that the label hasn't already been declared at this scope */ - if (b && B_IN_CURRENT_SCOPE (b)) - { - error ("duplicate label declaration %qE", name); - locate_old_decl (b->decl, error); + for (dup = current_scope->names; dup; dup = TREE_CHAIN (dup)) + if (dup == label) + { + error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name)); + error ("%Jthis is a previous declaration", dup); - /* Just use the previous declaration. */ - return b->decl; - } + /* Just use the previous declaration. */ + return dup; + } label = make_label (name, input_location); C_DECLARED_LABEL_FLAG (label) = 1; /* Declared labels go in the current scope. */ - bind (name, label, current_scope, - /*invisible=*/false, /*nested=*/false); + bind_label (name, label, current_scope); return label; } @@ -2556,12 +2047,13 @@ declare_label (tree name) tree define_label (location_t location, tree name) { + tree label; + /* Find any preexisting label with this name. It is an error if that label has already been defined in this function, or if there is a containing function with a declared label with the same name. */ - tree label = I_LABEL_DECL (name); - struct c_label_list *nlist_se, *nlist_vm; + label = IDENTIFIER_LABEL_VALUE (name); if (label && ((DECL_CONTEXT (label) == current_function_decl @@ -2569,8 +2061,11 @@ define_label (location_t location, tree name) || (DECL_CONTEXT (label) != current_function_decl && C_DECLARED_LABEL_FLAG (label)))) { - error ("%Hduplicate label %qD", &location, label); - locate_old_decl (label, error); + error ("%Hduplicate label `%D'", &location, label); + if (DECL_INITIAL (label)) + error ("%J`%D' previously defined here", label, label); + else + error ("%J`%D' previously declared here", label, label); return 0; } else if (label && DECL_CONTEXT (label) == current_function_decl) @@ -2578,11 +2073,6 @@ define_label (location_t location, tree name) /* The label has been used or declared already in this function, but not defined. Update its location to point to this definition. */ - if (C_DECL_UNDEFINABLE_STMT_EXPR (label)) - error ("%Jjump into statement expression", label); - if (C_DECL_UNDEFINABLE_VM (label)) - error ("%Jjump into scope of identifier with variably modified type", - label); DECL_SOURCE_LOCATION (label) = location; } else @@ -2591,29 +2081,28 @@ define_label (location_t location, tree name) label = make_label (name, location); /* Ordinary labels go in the current function scope. */ - bind (name, label, current_function_scope, - /*invisible=*/false, /*nested=*/false); + bind_label (name, label, current_function_scope); } - if (!in_system_header && lookup_name (name)) - warning (OPT_Wtraditional, "%Htraditional C lacks a separate namespace " - "for labels, identifier %qE conflicts", &location, name); - - nlist_se = XOBNEW (&parser_obstack, struct c_label_list); - nlist_se->next = label_context_stack_se->labels_def; - nlist_se->label = label; - label_context_stack_se->labels_def = nlist_se; - - nlist_vm = XOBNEW (&parser_obstack, struct c_label_list); - nlist_vm->next = label_context_stack_vm->labels_def; - nlist_vm->label = label; - label_context_stack_vm->labels_def = nlist_vm; + if (warn_traditional && !in_system_header && lookup_name (name)) + warning ("%Htraditional C lacks a separate namespace for labels, " + "identifier `%s' conflicts", &location, + IDENTIFIER_POINTER (name)); /* Mark label as having been defined. */ DECL_INITIAL (label) = error_mark_node; return label; } +/* Return the list of declarations of the current scope. */ + +tree +getdecls (void) +{ + return current_scope->names; +} + + /* Given NAME, an IDENTIFIER_NODE, return the structure (or union or enum) definition for that name. If THISLEVEL_ONLY is nonzero, searches only the current_scope. @@ -2624,29 +2113,25 @@ define_label (location_t location, tree name) static tree lookup_tag (enum tree_code code, tree name, int thislevel_only) { - struct c_binding *b = I_TAG_BINDING (name); + tree tag = IDENTIFIER_TAG_VALUE (name); int thislevel = 0; - if (!b || !b->decl) + if (!tag) return 0; /* We only care about whether it's in this level if thislevel_only was set or it might be a type clash. */ - if (thislevel_only || TREE_CODE (b->decl) != code) - { - /* For our purposes, a tag in the external scope is the same as - a tag in the file scope. (Primarily relevant to Objective-C - and its builtin structure tags, which get pushed before the - file scope is created.) */ - if (B_IN_CURRENT_SCOPE (b) - || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b))) + if (thislevel_only || TREE_CODE (tag) != code) + { + if (current_scope == global_scope + || purpose_member (name, current_scope->tags)) thislevel = 1; } if (thislevel_only && !thislevel) return 0; - if (TREE_CODE (b->decl) != code) + if (TREE_CODE (tag) != code) { /* Definition isn't the kind we were looking for. */ pending_invalid_xref = name; @@ -2659,7 +2144,7 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only) if (thislevel) pending_xref_error (); } - return b->decl; + return tag; } /* Print an error message now @@ -2671,8 +2156,9 @@ void pending_xref_error (void) { if (pending_invalid_xref != 0) - error ("%H%qE defined as wrong kind of tag", - &pending_invalid_xref_location, pending_invalid_xref); + error ("%H`%s' defined as wrong kind of tag", + &pending_invalid_xref_location, + IDENTIFIER_POINTER (pending_invalid_xref)); pending_invalid_xref = 0; } @@ -2685,22 +2171,36 @@ pending_xref_error (void) tree lookup_name (tree name) { - struct c_binding *b = I_SYMBOL_BINDING (name); - if (b && !b->invisible) - return b->decl; - return 0; + tree decl = IDENTIFIER_SYMBOL_VALUE (name); + if (decl == 0 || decl == error_mark_node) + return decl; + if (C_DECL_INVISIBLE (decl)) + return 0; + return decl; } -/* Similar to `lookup_name' but look only at the indicated scope. */ +/* Similar to `lookup_name' but look only at the current scope. */ static tree -lookup_name_in_scope (tree name, struct c_scope *scope) +lookup_name_current_level (tree name) { - struct c_binding *b; + tree decl = IDENTIFIER_SYMBOL_VALUE (name); + + if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl)) + return 0; + + if (current_scope == global_scope) + return decl; + + /* Scan the current scope for a decl with name NAME. + For PARM_DECLs, we have to look at both ->parms and ->names, since + forward parameter declarations wind up on the ->names list. */ + if (TREE_CODE (decl) == PARM_DECL + && chain_member (decl, current_scope->parms)) + return decl; + if (chain_member (decl, current_scope->names)) + return decl; - for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed) - if (B_IN_SCOPE (b, scope)) - return b->decl; return 0; } @@ -2712,30 +2212,29 @@ lookup_name_in_scope (tree name, struct c_scope *scope) void c_init_decl_processing (void) { + tree endlink; + tree ptr_ftype_void, ptr_ftype_ptr; location_t save_loc = input_location; - /* Initialize reserved words for parser. */ + /* Adds some ggc roots, and reserved words for c-parse.in. */ c_parse_init (); current_function_decl = 0; - gcc_obstack_init (&parser_obstack); - - /* Make the externals scope. */ - push_scope (); - external_scope = current_scope; + /* Make the c_scope structure for global names. */ + pushlevel (0); + global_scope = current_scope; /* Declarations from c_common_nodes_and_builtins must not be associated with this input file, lest we get differences between using and not using preprocessed headers. */ -#ifdef USE_MAPPED_LOCATION - input_location = BUILTINS_LOCATION; -#else - input_location.file = "<built-in>"; + input_location.file = "<internal>"; input_location.line = 0; -#endif - build_common_tree_nodes (flag_signed_char, false); + /* Make the DECL for the toplevel file scope. */ + current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL); + + build_common_tree_nodes (flag_signed_char); c_common_nodes_and_builtins (); @@ -2748,12 +2247,21 @@ c_init_decl_processing (void) pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"), boolean_type_node)); + endlink = void_list_node; + ptr_ftype_void = build_function_type (ptr_type_node, endlink); + ptr_ftype_ptr + = build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)); + input_location = save_loc; - pedantic_lvalues = true; + pedantic_lvalues = pedantic; make_fname_decl = c_make_fname_decl; start_fname_decls (); + + first_builtin_decl = global_scope->names; + last_builtin_decl = global_scope->names_last; } /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the @@ -2770,9 +2278,9 @@ c_make_fname_decl (tree id, int type_dep) tree decl, type, init; size_t length = strlen (name); - type = build_array_type (char_type_node, - build_index_type (size_int (length))); - type = c_build_qualified_type (type, TYPE_QUAL_CONST); + type = build_array_type + (build_qualified_type (char_type_node, TYPE_QUAL_CONST), + build_index_type (size_int (length))); decl = build_decl (VAR_DECL, id, type); @@ -2781,26 +2289,16 @@ c_make_fname_decl (tree id, int type_dep) DECL_ARTIFICIAL (decl) = 1; init = build_string (length + 1, name); - free ((char *) name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; TREE_USED (decl) = 1; - if (current_function_decl - /* For invalid programs like this: - - void foo() - const char* p = __FUNCTION__; - - the __FUNCTION__ is believed to appear in K&R style function - parameter declarator. In that case we still don't have - function_scope. */ - && (!errorcount || current_function_scope)) + if (current_function_decl) { DECL_CONTEXT (decl) = current_function_decl; - bind (id, decl, current_function_scope, - /*invisible=*/false, /*nested=*/false); + IDENTIFIER_SYMBOL_VALUE (id) = decl; + SCOPE_LIST_APPEND (current_function_scope, names, decl); } finish_decl (decl, init, NULL_TREE); @@ -2819,32 +2317,23 @@ c_make_fname_decl (tree id, int type_dep) tree builtin_function (const char *name, tree type, int function_code, - enum built_in_class cl, const char *library_name, + enum built_in_class class, const char *library_name, tree attrs) { - tree id = get_identifier (name); - tree decl = build_decl (FUNCTION_DECL, id, type); - TREE_PUBLIC (decl) = 1; + tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); DECL_EXTERNAL (decl) = 1; - DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl); - DECL_BUILT_IN_CLASS (decl) = cl; - DECL_FUNCTION_CODE (decl) = function_code; - C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0); + TREE_PUBLIC (decl) = 1; if (library_name) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); + make_decl_rtl (decl, NULL); + pushdecl (decl); + DECL_BUILT_IN_CLASS (decl) = class; + DECL_FUNCTION_CODE (decl) = function_code; - /* Should never be called on a symbol with a preexisting meaning. */ - gcc_assert (!I_SYMBOL_BINDING (id)); - - bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false); - - /* Builtins in the implementation namespace are made visible without - needing to be explicitly declared. See push_file_scope. */ - if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1]))) - { - TREE_CHAIN (decl) = visible_builtins; - visible_builtins = decl; - } + /* Warn if a function in the namespace for users + is used without an occasion to consider it declared. */ + if (name[0] != '_' || name[1] != '_') + C_DECL_INVISIBLE (decl) = 1; /* Possibly apply some default attributes to this built-in function. */ if (attrs) @@ -2864,21 +2353,31 @@ builtin_function (const char *name, tree type, int function_code, Otherwise, it is an error. */ void -shadow_tag (const struct c_declspecs *declspecs) +shadow_tag (tree declspecs) { shadow_tag_warned (declspecs, 0); } -/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning, - but no pedwarn. */ void -shadow_tag_warned (const struct c_declspecs *declspecs, int warned) +shadow_tag_warned (tree declspecs, int warned) + + + /* 1 => we have done a pedwarn. 2 => we have done a warning, but + no pedwarn. */ { - bool found_tag = false; + int found_tag = 0; + tree link; + tree specs, attrs; - if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p) + pending_invalid_xref = 0; + + /* Remove the attributes from declspecs, since they will confuse the + following code. */ + split_specs_attrs (declspecs, &specs, &attrs); + + for (link = specs; link; link = TREE_CHAIN (link)) { - tree value = declspecs->type; + tree value = TREE_VALUE (link); enum tree_code code = TREE_CODE (value); if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) @@ -2888,7 +2387,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) tree name = TYPE_NAME (value); tree t; - found_tag = true; + found_tag++; if (name == 0) { @@ -2899,29 +2398,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; } } - else if (!declspecs->tag_defined_p - && declspecs->storage_class != csc_none) - { - if (warned != 1) - pedwarn ("empty declaration with storage class specifier " - "does not redeclare tag"); - warned = 1; - pending_xref_error (); - } - else if (!declspecs->tag_defined_p - && (declspecs->const_p - || declspecs->volatile_p - || declspecs->restrict_p)) - { - if (warned != 1) - pedwarn ("empty declaration with type qualifier " - "does not redeclare tag"); - warned = 1; - pending_xref_error (); - } else { - pending_invalid_xref = 0; t = lookup_tag (code, name, 1); if (t == 0) @@ -2933,210 +2411,102 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) } else { - if (warned != 1 && !in_system_header) + if (!warned && ! in_system_header) { - pedwarn ("useless type name in empty declaration"); - warned = 1; + warning ("useless keyword or type name in empty declaration"); + warned = 2; } } } - else if (warned != 1 && !in_system_header && declspecs->typedef_p) - { - pedwarn ("useless type name in empty declaration"); - warned = 1; - } - pending_invalid_xref = 0; - - if (declspecs->inline_p) - { - error ("%<inline%> in empty declaration"); - warned = 1; - } - - if (current_scope == file_scope && declspecs->storage_class == csc_auto) - { - error ("%<auto%> in file-scope empty declaration"); - warned = 1; - } - - if (current_scope == file_scope && declspecs->storage_class == csc_register) - { - error ("%<register%> in file-scope empty declaration"); - warned = 1; - } - - if (!warned && !in_system_header && declspecs->storage_class != csc_none) - { - warning (0, "useless storage class specifier in empty declaration"); - warned = 2; - } - - if (!warned && !in_system_header && declspecs->thread_p) - { - warning (0, "useless %<__thread%> in empty declaration"); - warned = 2; - } - - if (!warned && !in_system_header && (declspecs->const_p - || declspecs->volatile_p - || declspecs->restrict_p)) - { - warning (0, "useless type qualifier in empty declaration"); - warned = 2; - } + if (found_tag > 1) + error ("two types specified in one empty declaration"); if (warned != 1) { - if (!found_tag) + if (found_tag == 0) pedwarn ("empty declaration"); } } +/* Construct an array declarator. EXPR is the expression inside [], or + NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied + to the pointer to which a parameter array is converted). STATIC_P is + nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P + is nonzero is the array is [*], a VLA of unspecified length which is + nevertheless a complete type (not currently implemented by GCC), + zero otherwise. The declarator is constructed as an ARRAY_REF + (to be decoded by grokdeclarator), whose operand 0 is what's on the + left of the [] (filled by in set_array_declarator_type) and operand 1 + is the expression inside; whose TREE_TYPE is the type qualifiers and + which has TREE_STATIC set if "static" is used. */ -/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_* - bits. SPECS represents declaration specifiers that the grammar - only permits to contain type qualifiers and attributes. */ - -int -quals_from_declspecs (const struct c_declspecs *specs) -{ - int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0) - | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0) - | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)); - gcc_assert (!specs->type - && !specs->decl_attr - && specs->typespec_word == cts_none - && specs->storage_class == csc_none - && !specs->typedef_p - && !specs->explicit_signed_p - && !specs->deprecated_p - && !specs->long_p - && !specs->long_long_p - && !specs->short_p - && !specs->signed_p - && !specs->unsigned_p - && !specs->complex_p - && !specs->inline_p - && !specs->thread_p); - return quals; -} - -/* Construct an array declarator. EXPR is the expression inside [], - or NULL_TREE. QUALS are the type qualifiers inside the [] (to be - applied to the pointer to which a parameter array is converted). - STATIC_P is true if "static" is inside the [], false otherwise. - VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified - length which is nevertheless a complete type, false otherwise. The - field for the contained declarator is left to be filled in by - set_array_declarator_inner. */ - -struct c_declarator * -build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, - bool vla_unspec_p) +tree +build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p) { - struct c_declarator *declarator = XOBNEW (&parser_obstack, - struct c_declarator); - declarator->kind = cdk_array; - declarator->declarator = 0; - declarator->u.array.dimen = expr; - if (quals) - { - declarator->u.array.attrs = quals->attrs; - declarator->u.array.quals = quals_from_declspecs (quals); - } - else - { - declarator->u.array.attrs = NULL_TREE; - declarator->u.array.quals = 0; - } - declarator->u.array.static_p = static_p; - declarator->u.array.vla_unspec_p = vla_unspec_p; + tree decl; + decl = build_nt (ARRAY_REF, NULL_TREE, expr); + TREE_TYPE (decl) = quals; + TREE_STATIC (decl) = (static_p ? 1 : 0); if (pedantic && !flag_isoc99) { - if (static_p || quals != NULL) - pedwarn ("ISO C90 does not support %<static%> or type " - "qualifiers in parameter array declarators"); + if (static_p || quals != NULL_TREE) + pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators"); if (vla_unspec_p) - pedwarn ("ISO C90 does not support %<[*]%> array declarators"); + pedwarn ("ISO C90 does not support `[*]' array declarators"); } if (vla_unspec_p) - { - if (!current_scope->parm_flag) - { - /* C99 6.7.5.2p4 */ - error ("%<[*]%> not allowed in other than function prototype scope"); - declarator->u.array.vla_unspec_p = false; - return NULL; - } - current_scope->had_vla_unspec = true; - } - return declarator; + warning ("GCC does not yet properly implement `[*]' array declarators"); + return decl; } -/* Set the contained declarator of an array declarator. DECL is the - declarator, as constructed by build_array_declarator; INNER is what - appears on the left of the []. ABSTRACT_P is true if it is an - abstract declarator, false otherwise; this is used to reject static - and type qualifiers in abstract declarators, where they are not in - the C99 grammar (subject to possible change in DR#289). */ +/* Set the type of an array declarator. DECL is the declarator, as + constructed by build_array_declarator; TYPE is what appears on the left + of the [] and goes in operand 0. ABSTRACT_P is nonzero if it is an + abstract declarator, zero otherwise; this is used to reject static and + type qualifiers in abstract declarators, where they are not in the + C99 grammar. */ -struct c_declarator * -set_array_declarator_inner (struct c_declarator *decl, - struct c_declarator *inner, bool abstract_p) +tree +set_array_declarator_type (tree decl, tree type, int abstract_p) { - decl->declarator = inner; - if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED - || decl->u.array.attrs != NULL_TREE - || decl->u.array.static_p)) + TREE_OPERAND (decl, 0) = type; + if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl))) error ("static or type qualifiers in abstract declarator"); return decl; } - -/* INIT is a constructor that forms DECL's initializer. If the final - element initializes a flexible array field, add the size of that - initializer to DECL's size. */ - -static void -add_flexible_array_elts_to_size (tree decl, tree init) -{ - tree elt, type; - - if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))) - return; - - elt = VEC_last (constructor_elt, CONSTRUCTOR_ELTS (init))->value; - type = TREE_TYPE (elt); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) == NULL_TREE - && TYPE_DOMAIN (type) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) - { - complete_array_type (&type, elt, false); - DECL_SIZE (decl) - = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type)); - DECL_SIZE_UNIT (decl) - = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type)); - } -} /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree -groktypename (struct c_type_name *type_name) +groktypename (tree typename) { - tree type; - tree attrs = type_name->specs->attrs; + tree specs, attrs; - type_name->specs->attrs = NULL_TREE; + if (TREE_CODE (typename) != TREE_LIST) + return typename; - type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME, - false, NULL); + split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs); + + typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0, + NULL); /* Apply attributes. */ - decl_attributes (&type, attrs, 0); + decl_attributes (&typename, attrs, 0); + + return typename; +} - return type; +/* Return a PARM_DECL node for a given pair of specs and declarator. */ + +tree +groktypename_in_parm_context (tree typename) +{ + if (TREE_CODE (typename) != TREE_LIST) + return typename; + return grokdeclarator (TREE_VALUE (typename), + TREE_PURPOSE (typename), + PARM, 0, NULL); } /* Decode a declarator in an ordinary declaration or data definition. @@ -3155,8 +2525,7 @@ groktypename (struct c_type_name *type_name) grokfield and not through here. */ tree -start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, - bool initialized, tree attributes) +start_decl (tree declarator, tree declspecs, int initialized, tree attributes) { tree decl; tree tem; @@ -3168,43 +2537,44 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, NULL); - if (!decl) - return 0; deprecated_state = DEPRECATED_NORMAL; if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))) - warning (OPT_Wmain, "%q+D is usually a function", decl); + warning ("%J'%D' is usually a function", decl, decl); 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 `finish_decl' to ignore the initializer once it is parsed. */ switch (TREE_CODE (decl)) { case TYPE_DECL: - error ("typedef %qD is initialized (use __typeof__ instead)", decl); + error ("typedef `%s' is initialized (use __typeof__ instead)", + IDENTIFIER_POINTER (DECL_NAME (decl))); initialized = 0; break; case FUNCTION_DECL: - error ("function %qD is initialized like a variable", decl); + error ("function `%s' is initialized like a variable", + IDENTIFIER_POINTER (DECL_NAME (decl))); initialized = 0; break; case PARM_DECL: /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */ - error ("parameter %qD is initialized", decl); + error ("parameter `%s' is initialized", + IDENTIFIER_POINTER (DECL_NAME (decl))); initialized = 0; break; default: - /* Don't allow initializations for incomplete types except for - arrays which might be completed by the initialization. */ + /* Don't allow initializations for incomplete types + except for arrays which might be completed by the initialization. */ - /* This can happen if the array size is an undefined macro. - We already gave a warning, so we don't need another one. */ + /* This can happen if the array size is an undefined macro. We already + gave a warning, so we don't need another one. */ if (TREE_TYPE (decl) == error_mark_node) initialized = 0; else if (COMPLETE_TYPE_P (TREE_TYPE (decl))) @@ -3220,28 +2590,27 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, } else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) { - error ("variable %qD has initializer but incomplete type", decl); + error ("variable `%s' has initializer but incomplete type", + IDENTIFIER_POINTER (DECL_NAME (decl))); initialized = 0; } - else if (C_DECL_VARIABLE_SIZE (decl)) + else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) { - /* Although C99 is unclear about whether incomplete arrays - of VLAs themselves count as VLAs, it does not make - sense to permit them to be initialized given that - ordinary VLAs may not be initialized. */ - error ("variable-sized object may not be initialized"); + error ("elements of array `%s' have incomplete type", + IDENTIFIER_POINTER (DECL_NAME (decl))); initialized = 0; } } if (initialized) { - if (current_scope == file_scope) + DECL_EXTERNAL (decl) = 0; + if (current_scope == global_scope) TREE_STATIC (decl) = 1; - /* Tell 'pushdecl' this is an initialized decl + /* 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 `finish_decl' it may store the real initializer. */ DECL_INITIAL (decl) = error_mark_node; } @@ -3265,7 +2634,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, if (TREE_CODE (decl) == VAR_DECL && !initialized && TREE_PUBLIC (decl) - && !DECL_THREAD_LOCAL_P (decl) + && !DECL_THREAD_LOCAL (decl) && !flag_no_common) DECL_COMMON (decl) = 1; @@ -3275,17 +2644,17 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, if (TREE_CODE (decl) == FUNCTION_DECL && targetm.calls.promote_prototypes (TREE_TYPE (decl))) { - struct c_declarator *ce = declarator; + tree ce = declarator; - if (ce->kind == cdk_pointer) - ce = declarator->declarator; - if (ce->kind == cdk_function) + if (TREE_CODE (ce) == INDIRECT_REF) + ce = TREE_OPERAND (declarator, 0); + if (TREE_CODE (ce) == CALL_EXPR) { - tree args = ce->u.arg_info->parms; + tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1)); for (; args; args = TREE_CHAIN (args)) { tree type = TREE_TYPE (args); - if (type && INTEGRAL_TYPE_P (type) + if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) DECL_ARG_TYPE (args) = integer_type_node; } @@ -3296,39 +2665,30 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) - warning (OPT_Wattributes, "inline function %q+D given attribute noinline", - decl); + warning ("%Jinline function '%D' given attribute noinline", decl, decl); /* Add this decl to the current scope. TEM may equal DECL or it may be a previous decl of the same name. */ tem = pushdecl (decl); - if (initialized && DECL_EXTERNAL (tem)) + /* For a local variable, define the RTL now. */ + if (current_scope != global_scope + /* But not if this is a duplicate decl + and we preserved the rtl from the previous one + (which may or may not happen). */ + && !DECL_RTL_SET_P (tem) + && DECL_FILE_SCOPE_P (tem)) { - DECL_EXTERNAL (tem) = 0; - TREE_STATIC (tem) = 1; + if (TREE_TYPE (tem) != error_mark_node + && (COMPLETE_TYPE_P (TREE_TYPE (tem)) + || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE + && DECL_INITIAL (tem) != 0))) + expand_decl (tem); } return tem; } -/* Initialize EH if not initialized yet and exceptions are enabled. */ - -void -c_maybe_initialize_eh (void) -{ - if (!flag_exceptions || c_eh_initialized_p) - return; - - c_eh_initialized_p = true; - eh_personality_libfunc - = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcc_personality_sj0" - : "__gcc_personality_v0"); - default_init_unwind_resume_libfunc (); - using_eh_for_cleanups (); -} - /* Finish processing of a declaration; install its initial value. If the length of an array type is not known before, @@ -3337,13 +2697,12 @@ c_maybe_initialize_eh (void) void finish_decl (tree decl, tree init, tree asmspec_tree) { - tree type; + tree type = TREE_TYPE (decl); int was_incomplete = (DECL_SIZE (decl) == 0); const char *asmspec = 0; /* If a name was specified, get the string. */ - if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) - && DECL_FILE_SCOPE_P (decl)) + if (current_scope == global_scope) asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); @@ -3360,86 +2719,56 @@ finish_decl (tree decl, tree init, tree asmspec_tree) store_init_value (decl, init); if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == FIELD_DECL)) + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL)) objc_check_decl (decl); - type = TREE_TYPE (decl); - /* Deduce size of array from initialization, if not already known. */ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0 && TREE_CODE (decl) != TYPE_DECL) { - bool do_default + int do_default = (TREE_STATIC (decl) /* Even if pedantic, an external linkage array may have incomplete type at first. */ ? pedantic && !TREE_PUBLIC (decl) : !DECL_EXTERNAL (decl)); int failure - = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl), - do_default); + = complete_array_type (type, DECL_INITIAL (decl), do_default); /* Get the completed type made by complete_array_type. */ type = TREE_TYPE (decl); - switch (failure) - { - case 1: - error ("initializer fails to determine size of %q+D", decl); - break; + if (failure == 1) + error ("%Jinitializer fails to determine size of '%D'", decl, decl); - case 2: + else if (failure == 2) + { if (do_default) - error ("array size missing in %q+D", decl); + error ("%Jarray size missing in '%D'", decl, decl); /* If a `static' var's size isn't known, make it extern as well as static, so it does not get allocated. If it is not `static', then do not mark extern; finish_incomplete_decl will give it a default size and it will get allocated. */ - else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl)) + else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl)) DECL_EXTERNAL (decl) = 1; - break; - - case 3: - error ("zero or negative size array %q+D", decl); - break; - - case 0: - /* For global variables, update the copy of the type that - exists in the binding. */ - if (TREE_PUBLIC (decl)) - { - struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl)); - while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext)) - b_ext = b_ext->shadowed; - if (b_ext) - { - if (b_ext->type) - b_ext->type = composite_type (b_ext->type, type); - else - b_ext->type = type; - } - } - break; - - default: - gcc_unreachable (); } - if (DECL_INITIAL (decl)) - TREE_TYPE (DECL_INITIAL (decl)) = type; + /* TYPE_MAX_VALUE is always one less than the number of elements + in the array, because we start counting at zero. Therefore, + warn only if the value is less than zero. */ + else if (pedantic && TYPE_DOMAIN (type) != 0 + && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0) + error ("%Jzero or negative size array '%D'", decl, decl); layout_decl (decl, 0); } if (TREE_CODE (decl) == VAR_DECL) { - if (init && TREE_CODE (init) == CONSTRUCTOR) - add_flexible_array_elts_to_size (decl, init); - if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node && COMPLETE_TYPE_P (TREE_TYPE (decl))) layout_decl (decl, 0); @@ -3448,20 +2777,22 @@ finish_decl (tree decl, tree init, tree asmspec_tree) /* Don't give an error if we already gave one earlier. */ && TREE_TYPE (decl) != error_mark_node && (TREE_STATIC (decl) - /* A static variable with an incomplete type - is an error if it is initialized. - Also if it is not file scope. - Otherwise, let it through, but if it is not `extern' - then it may cause an error message later. */ - ? (DECL_INITIAL (decl) != 0 + ? + /* A static variable with an incomplete type + is an error if it is initialized. + Also if it is not file scope. + Otherwise, let it through, but if it is not `extern' + then it may cause an error message later. */ + (DECL_INITIAL (decl) != 0 || !DECL_FILE_SCOPE_P (decl)) - /* An automatic variable with an incomplete type - is an error. */ - : !DECL_EXTERNAL (decl))) - { - error ("storage size of %q+D isn%'t known", decl); - TREE_TYPE (decl) = error_mark_node; - } + : + /* An automatic variable with an incomplete type + is an error. */ + !DECL_EXTERNAL (decl))) + { + error ("%Jstorage size of '%D' isn't known", decl, decl); + TREE_TYPE (decl) = error_mark_node; + } if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != 0) @@ -3469,7 +2800,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) constant_expression_warning (DECL_SIZE (decl)); else - error ("storage size of %q+D isn%'t constant", decl); + error ("%Jstorage size of '%D' isn't constant", decl, decl); } if (TREE_USED (type)) @@ -3481,13 +2812,36 @@ finish_decl (tree decl, tree init, tree asmspec_tree) was a normal built-in. */ if (TREE_CODE (decl) == FUNCTION_DECL && asmspec) { + /* ASMSPEC is given, and not the name of a register. Mark the + name with a star so assemble_name won't munge it. */ + char *starred = alloca (strlen (asmspec) + 2); + starred[0] = '*'; + strcpy (starred + 1, asmspec); + if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) - set_builtin_user_assembler_name (decl, asmspec); - set_user_assembler_name (decl, asmspec); + { + tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)]; + SET_DECL_RTL (builtin, NULL_RTX); + SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred)); +#ifdef TARGET_MEM_FUNCTIONS + if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY) + init_block_move_fn (starred); + else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET) + init_block_clear_fn (starred); +#else + if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY) + init_block_move_fn (starred); + else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO) + init_block_clear_fn (starred); +#endif + } + SET_DECL_RTL (decl, NULL_RTX); + change_decl_assembler_name (decl, get_identifier (starred)); } /* If #pragma weak was used, mark the decl weak now. */ - maybe_apply_pragma_weak (decl); + if (current_scope == global_scope) + maybe_apply_pragma_weak (decl); /* Output the assembler code and/or RTL code for variables and functions, unless the type is an undefined structure or union. @@ -3495,31 +2849,10 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) { - /* Determine the ELF visibility. */ - if (TREE_PUBLIC (decl)) - c_determine_visibility (decl); - /* This is a no-op in c-lang.c or something real in objc-act.c. */ if (c_dialect_objc ()) objc_check_decl (decl); - if (asmspec) - { - /* If this is not a static variable, issue a warning. - It doesn't make any sense to give an ASMSPEC for an - ordinary, non-register local variable. Historically, - GCC has accepted -- but ignored -- the ASMSPEC in - this case. */ - if (!DECL_FILE_SCOPE_P (decl) - && TREE_CODE (decl) == VAR_DECL - && !C_DECL_REGISTER (decl) - && !TREE_STATIC (decl)) - warning (0, "ignoring asm-specifier for non-static local " - "variable %q+D", decl); - else - set_user_assembler_name (decl, asmspec); - } - if (DECL_FILE_SCOPE_P (decl)) { if (DECL_INITIAL (decl) == NULL_TREE @@ -3528,51 +2861,44 @@ finish_decl (tree decl, tree init, tree asmspec_tree) when a tentative file-scope definition is seen. But at end of compilation, do output code for them. */ DECL_DEFER_OUTPUT (decl) = 1; - rest_of_decl_compilation (decl, true, 0); + rest_of_decl_compilation (decl, asmspec, true, 0); } else { - /* In conjunction with an ASMSPEC, the `register' - keyword indicates that we should place the variable - in a particular register. */ - if (asmspec && C_DECL_REGISTER (decl)) + /* This is a local variable. If there is an ASMSPEC, the + user has requested that we handle it specially. */ + if (asmspec) { - DECL_HARD_REGISTER (decl) = 1; - /* This cannot be done for a structure with volatile - fields, on which DECL_REGISTER will have been - reset. */ - if (!DECL_REGISTER (decl)) - error ("cannot put object with volatile field into register"); + /* In conjunction with an ASMSPEC, the `register' + keyword indicates that we should place the variable + in a particular register. */ + if (DECL_REGISTER (decl)) + DECL_C_HARD_REGISTER (decl) = 1; + + /* If this is not a static variable, issue a warning. + It doesn't make any sense to give an ASMSPEC for an + ordinary, non-register local variable. Historically, + GCC has accepted -- but ignored -- the ASMSPEC in + this case. */ + if (TREE_CODE (decl) == VAR_DECL + && !DECL_REGISTER (decl) + && !TREE_STATIC (decl)) + warning ("%Jignoring asm-specifier for non-static local " + "variable '%D'", decl, decl); + else + change_decl_assembler_name (decl, get_identifier (asmspec)); } if (TREE_CODE (decl) != FUNCTION_DECL) - { - /* If we're building a variable sized type, and we might be - reachable other than via the top of the current binding - level, then create a new BIND_EXPR so that we deallocate - the object at the right time. */ - /* Note that DECL_SIZE can be null due to errors. */ - if (DECL_SIZE (decl) - && !TREE_CONSTANT (DECL_SIZE (decl)) - && STATEMENT_LIST_HAS_LABEL (cur_stmt_list)) - { - tree bind; - bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); - TREE_SIDE_EFFECTS (bind) = 1; - add_stmt (bind); - BIND_EXPR_BODY (bind) = push_stmt_list (); - } - add_stmt (build_stmt (DECL_EXPR, decl)); - } + add_decl_stmt (decl); } - if (!DECL_FILE_SCOPE_P (decl)) { /* Recompute the RTL of a local array now if it used to be an incomplete type. */ if (was_incomplete - && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) + && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) { /* If we used it already as memory, it must stay in memory. */ TREE_ADDRESSABLE (decl) = TREE_USED (decl); @@ -3584,22 +2910,16 @@ finish_decl (tree decl, tree init, tree asmspec_tree) } /* If this was marked 'used', be sure it will be output. */ - if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl))) - mark_decl_referenced (decl); + if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) + mark_referenced (DECL_ASSEMBLER_NAME (decl)); if (TREE_CODE (decl) == TYPE_DECL) - { - if (!DECL_FILE_SCOPE_P (decl) - && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) - add_stmt (build_stmt (DECL_EXPR, decl)); - - rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0); - } + rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0); /* At the end of a declaration, throw away any variable type sizes of types defined inside that declaration. There is no use computing them in the following function definition. */ - if (current_scope == file_scope) + if (current_scope == global_scope) get_pending_sizes (); /* Install a cleanup (aka destructor) if one was given. */ @@ -3608,6 +2928,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree) tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl)); if (attr) { + static bool eh_initialized_p; + tree cleanup_id = TREE_VALUE (TREE_VALUE (attr)); tree cleanup_decl = lookup_name (cleanup_id); tree cleanup; @@ -3619,52 +2941,67 @@ finish_decl (tree decl, tree init, tree asmspec_tree) /* Don't warn about decl unused; the cleanup uses it. */ TREE_USED (decl) = 1; - TREE_USED (cleanup_decl) = 1; /* Initialize EH, if we've been told to do so. */ - c_maybe_initialize_eh (); + if (flag_exceptions && !eh_initialized_p) + { + eh_initialized_p = true; + eh_personality_libfunc + = init_one_libfunc (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + using_eh_for_cleanups (); + } - push_cleanup (decl, cleanup, false); + add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); } } } -/* Given a parsed parameter declaration, decode it into a PARM_DECL. */ - -tree -grokparm (const struct c_parm *parm) -{ - tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, - NULL); - - decl_attributes (&decl, parm->attrs, 0); - - return decl; -} - /* Given a parsed parameter declaration, decode it into a PARM_DECL and push that on the current scope. */ void -push_parm_decl (const struct c_parm *parm) +push_parm_decl (tree parm) { tree decl; + int old_dont_save_pending_sizes_p = 0; - decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL); - decl_attributes (&decl, parm->attrs, 0); + /* Don't attempt to expand sizes while parsing this decl. + (We can get here with i_s_e 1 somehow from Objective-C.) */ + int save_immediate_size_expand = immediate_size_expand; + immediate_size_expand = 0; + + /* If this is a nested function, we do want to keep SAVE_EXPRs for + the argument sizes, regardless of the parent's setting. */ + if (cfun) + { + old_dont_save_pending_sizes_p = cfun->x_dont_save_pending_sizes_p; + cfun->x_dont_save_pending_sizes_p = 0; + } + + decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)), + TREE_PURPOSE (TREE_PURPOSE (parm)), + PARM, 0, NULL); + decl_attributes (&decl, TREE_VALUE (parm), 0); decl = pushdecl (decl); finish_decl (decl, NULL_TREE, NULL_TREE); + + if (cfun) + cfun->x_dont_save_pending_sizes_p = old_dont_save_pending_sizes_p; + immediate_size_expand = save_immediate_size_expand; } -/* Mark all the parameter declarations to date as forward decls. +/* Mark all the parameter declarations to date as forward decls, + shift them to the variables list, and reset the parameters list. Also diagnose use of this extension. */ void mark_forward_parm_decls (void) { - struct c_binding *b; + tree parm; if (pedantic && !current_scope->warned_forward_parm_decls) { @@ -3672,11 +3009,16 @@ mark_forward_parm_decls (void) current_scope->warned_forward_parm_decls = true; } - for (b = current_scope->bindings; b; b = b->prev) - if (TREE_CODE (b->decl) == PARM_DECL) - TREE_ASM_WRITTEN (b->decl) = 1; + for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm)) + TREE_ASM_WRITTEN (parm) = 1; + + SCOPE_LIST_CONCAT (current_scope, names, current_scope, parms); + current_scope->parms = 0; + current_scope->parms_last = 0; } +static GTY(()) int compound_literal_number; + /* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound literal, which may be an incomplete array type completed by the initializer; INIT is a CONSTRUCTOR that initializes the compound @@ -3687,58 +3029,123 @@ build_compound_literal (tree type, tree init) { /* We do not use start_decl here because we have a type, not a declarator; and do not use finish_decl because the decl should be stored inside - the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR. */ - tree decl; + the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */ + tree decl = build_decl (VAR_DECL, NULL_TREE, type); tree complit; tree stmt; - - if (type == error_mark_node) - return error_mark_node; - - decl = build_decl (VAR_DECL, NULL_TREE, type); DECL_EXTERNAL (decl) = 0; TREE_PUBLIC (decl) = 0; - TREE_STATIC (decl) = (current_scope == file_scope); + TREE_STATIC (decl) = (current_scope == global_scope); DECL_CONTEXT (decl) = current_function_decl; TREE_USED (decl) = 1; TREE_TYPE (decl) = type; - TREE_READONLY (decl) = TYPE_READONLY (type); + TREE_READONLY (decl) = TREE_READONLY (type); store_init_value (decl, init); if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) { - int failure = complete_array_type (&TREE_TYPE (decl), - DECL_INITIAL (decl), true); - gcc_assert (!failure); - - type = TREE_TYPE (decl); - TREE_TYPE (DECL_INITIAL (decl)) = type; + int failure = complete_array_type (type, DECL_INITIAL (decl), 1); + if (failure) + abort (); } + type = TREE_TYPE (decl); if (type == error_mark_node || !COMPLETE_TYPE_P (type)) return error_mark_node; - stmt = build_stmt (DECL_EXPR, decl); - complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt); + stmt = build_stmt (DECL_STMT, decl); + complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt); TREE_SIDE_EFFECTS (complit) = 1; layout_decl (decl, 0); if (TREE_STATIC (decl)) { - /* This decl needs a name for the assembler output. */ - set_compound_literal_name (decl); + /* This decl needs a name for the assembler output. We also need + a unique suffix to be added to the name. */ + char *name; + + ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", + compound_literal_number); + compound_literal_number++; + DECL_NAME (decl) = get_identifier (name); DECL_DEFER_OUTPUT (decl) = 1; DECL_COMDAT (decl) = 1; DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; pushdecl (decl); - rest_of_decl_compilation (decl, 1, 0); + rest_of_decl_compilation (decl, NULL, 1, 0); } return complit; } +/* Make TYPE a complete type based on INITIAL_VALUE. + Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered, + 2 if there was no information (in which case assume 1 if DO_DEFAULT). */ + +int +complete_array_type (tree type, tree initial_value, int do_default) +{ + tree maxindex = NULL_TREE; + int value = 0; + + if (initial_value) + { + /* Note MAXINDEX is really the maximum index, + one less than the size. */ + if (TREE_CODE (initial_value) == STRING_CST) + { + 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) + { + tree elts = CONSTRUCTOR_ELTS (initial_value); + maxindex = build_int_2 (-1, -1); + for (; elts; elts = TREE_CHAIN (elts)) + { + if (TREE_PURPOSE (elts)) + maxindex = TREE_PURPOSE (elts); + else + maxindex = fold (build (PLUS_EXPR, integer_type_node, + maxindex, integer_one_node)); + } + maxindex = copy_node (maxindex); + } + else + { + /* Make an error message unless that happened already. */ + if (initial_value != error_mark_node) + value = 1; + + /* Prevent further error messages. */ + maxindex = build_int_2 (0, 0); + } + } + + if (!maxindex) + { + if (do_default) + maxindex = build_int_2 (0, 0); + value = 2; + } + + if (maxindex) + { + TYPE_DOMAIN (type) = build_index_type (maxindex); + if (!TREE_TYPE (maxindex)) + TREE_TYPE (maxindex) = TYPE_DOMAIN (type); + } + + /* Lay out the type now that we can get the real answer. */ + + layout_type (type); + + return value; +} + /* Determine whether TYPE is a structure with a flexible array member, or a union containing such a structure (possibly recursively). */ @@ -3782,12 +3189,14 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) unsigned HOST_WIDE_INT w; const char *name = orig_name ? orig_name: _("<anonymous>"); + /* Necessary? */ + STRIP_NOPS (*width); + /* Detect and ignore out of range field width and process valid field widths. */ - if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)) - || TREE_CODE (*width) != INTEGER_CST) + if (TREE_CODE (*width) != INTEGER_CST) { - error ("bit-field %qs width not an integer constant", name); + error ("bit-field `%s' width not an integer constant", name); *width = integer_one_node; } else @@ -3795,12 +3204,12 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) constant_expression_warning (*width); if (tree_int_cst_sgn (*width) < 0) { - error ("negative width in bit-field %qs", name); + error ("negative width in bit-field `%s'", name); *width = integer_one_node; } else if (integer_zerop (*width) && orig_name) { - error ("zero width for bit-field %qs", name); + error ("zero width for bit-field `%s'", name); *width = integer_one_node; } } @@ -3810,17 +3219,16 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) && TREE_CODE (*type) != BOOLEAN_TYPE && TREE_CODE (*type) != ENUMERAL_TYPE) { - error ("bit-field %qs has invalid type", name); + error ("bit-field `%s' has invalid type", name); *type = unsigned_type_node; } type_mv = TYPE_MAIN_VARIANT (*type); if (pedantic - && !in_system_header && type_mv != integer_type_node && type_mv != unsigned_type_node && type_mv != boolean_type_node) - pedwarn ("type of bit-field %qs is a GCC extension", name); + pedwarn ("type of bit-field `%s' is a GCC extension", name); if (type_mv == boolean_type_node) max_width = CHAR_TYPE_SIZE; @@ -3829,23 +3237,18 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) if (0 < compare_tree_int (*width, max_width)) { - error ("width of %qs exceeds its type", name); + error ("width of `%s' exceeds its type", name); w = max_width; - *width = build_int_cst (NULL_TREE, w); + *width = build_int_2 (w, 0); } else w = tree_low_cst (*width, 1); - if (TREE_CODE (*type) == ENUMERAL_TYPE) - { - struct lang_type *lt = TYPE_LANG_SPECIFIC (*type); - if (!lt - || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type)) - || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type))) - warning (0, "%qs is narrower than values of its type", name); - } + if (TREE_CODE (*type) == ENUMERAL_TYPE + && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type)) + || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type)))) + warning ("`%s' is narrower than values of its type", name); } - /* Given declspecs and a declarator, determine the name and type of the object declared @@ -3853,7 +3256,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) (In one case we can return a ..._TYPE node instead. For invalid input we sometimes return 0.) - DECLSPECS is a c_declspecs structure for the declaration specifiers. + DECLSPECS is a chain of tree_list nodes whose value fields + are the storage classes and type specifiers. DECL_CONTEXT says which syntactic context this declaration is in: NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL. @@ -3865,7 +3269,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) 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. - INITIALIZED is true if the decl has an initializer. + INITIALIZED is 1 if the decl has an initializer. WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node representing the width of the bit-field. @@ -3877,63 +3281,64 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) and `extern' are interpreted. */ static tree -grokdeclarator (const struct c_declarator *declarator, - struct c_declspecs *declspecs, - enum decl_context decl_context, bool initialized, tree *width) +grokdeclarator (tree declarator, tree declspecs, + enum decl_context decl_context, int initialized, tree *width) { - tree type = declspecs->type; - bool threadp = declspecs->thread_p; - enum c_storage_class storage_class = declspecs->storage_class; + int specbits = 0; + tree spec; + tree type = NULL_TREE; + int longlong = 0; int constp; int restrictp; int volatilep; int type_quals = TYPE_UNQUALIFIED; + int inlinep; + int explicit_int = 0; + int explicit_char = 0; + int defaulted_int = 0; + tree typedef_decl = 0; const char *name, *orig_name; tree typedef_type = 0; - bool funcdef_flag = false; - bool funcdef_syntax = false; + int funcdef_flag = 0; + enum tree_code innermost_code = ERROR_MARK; int size_varies = 0; - tree decl_attr = declspecs->decl_attr; - int array_ptr_quals = TYPE_UNQUALIFIED; - tree array_ptr_attrs = NULL_TREE; + tree decl_attr = NULL_TREE; + tree array_ptr_quals = NULL_TREE; int array_parm_static = 0; - bool array_parm_vla_unspec_p = false; tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; - struct c_arg_info *arg_info = 0; if (decl_context == FUNCDEF) - funcdef_flag = true, decl_context = NORMAL; + funcdef_flag = 1, decl_context = NORMAL; /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ { - const struct c_declarator *decl = declarator; + tree decl = declarator; name = 0; while (decl) - switch (decl->kind) + switch (TREE_CODE (decl)) { - case cdk_function: - case cdk_array: - case cdk_pointer: - funcdef_syntax = (decl->kind == cdk_function); - decl = decl->declarator; + case ARRAY_REF: + case INDIRECT_REF: + case CALL_EXPR: + innermost_code = TREE_CODE (decl); + decl = TREE_OPERAND (decl, 0); break; - case cdk_attrs: - decl = decl->declarator; + case TREE_LIST: + decl = TREE_VALUE (decl); break; - case cdk_id: - if (decl->u.id) - name = IDENTIFIER_POINTER (decl->u.id); + case IDENTIFIER_NODE: + name = IDENTIFIER_POINTER (decl); decl = 0; break; default: - gcc_unreachable (); + abort (); } orig_name = name; if (name == 0) @@ -3943,49 +3348,302 @@ grokdeclarator (const struct c_declarator *declarator, /* A function definition's declarator must have the form of a function declarator. */ - if (funcdef_flag && !funcdef_syntax) + if (funcdef_flag && innermost_code != CALL_EXPR) return 0; /* If this looks like a function definition, make it one, even if it occurs where parms are expected. Then store_parm_decls will reject it and not use it as a parm. */ - if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag) + if (decl_context == NORMAL && !funcdef_flag + && current_scope->parm_flag) decl_context = PARM; - if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS) - warn_deprecated_use (declspecs->type); + /* Look through the decl specs and record which ones appear. + Some typespecs are defined as built-in typenames. + Others, the ones that are modifiers of other types, + are represented by bits in SPECBITS: set the bits for + the modifiers that appear. Storage class keywords are also in SPECBITS. + + If there is a typedef name or a type, store the type in TYPE. + This includes builtin typedefs such as `int'. - if ((decl_context == NORMAL || decl_context == FIELD) - && current_scope == file_scope - && variably_modified_type_p (type, NULL_TREE)) + Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char' + and did not come from a user typedef. + + Set LONGLONG if `long' is mentioned twice. */ + + for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) { - error ("variably modified %qs at file scope", name); - type = integer_type_node; + tree id = TREE_VALUE (spec); + + /* If the entire declaration is itself tagged as deprecated then + suppress reports of deprecated items. */ + if (id && TREE_DEPRECATED (id)) + { + if (deprecated_state != DEPRECATED_SUPPRESS) + warn_deprecated_use (id); + } + + if (id == ridpointers[(int) RID_INT]) + explicit_int = 1; + if (id == ridpointers[(int) RID_CHAR]) + explicit_char = 1; + + if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id)) + { + enum rid i = C_RID_CODE (id); + if ((int) i <= (int) RID_LAST_MODIFIER) + { + if (i == RID_LONG && (specbits & (1 << (int) RID_LONG))) + { + if (longlong) + error ("`long long long' is too long for GCC"); + else + { + if (pedantic && !flag_isoc99 && ! in_system_header + && warn_long_long) + pedwarn ("ISO C90 does not support `long long'"); + longlong = 1; + } + } + else if (specbits & (1 << (int) i)) + { + if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT) + { + if (pedantic && !flag_isoc99) + pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + else + error ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + + /* Diagnose "__thread extern". Recall that this list + is in the reverse order seen in the text. */ + if (i == RID_THREAD + && (specbits & (1 << (int) RID_EXTERN + | 1 << (int) RID_STATIC))) + { + if (specbits & 1 << (int) RID_EXTERN) + error ("`__thread' before `extern'"); + else + error ("`__thread' before `static'"); + } + + specbits |= 1 << (int) i; + goto found; + } + } + if (type) + error ("two or more data types in declaration of `%s'", name); + /* Actual typedefs come to us as TYPE_DECL nodes. */ + else if (TREE_CODE (id) == TYPE_DECL) + { + if (TREE_TYPE (id) == error_mark_node) + ; /* Allow the type to default to int to avoid cascading errors. */ + else + { + type = TREE_TYPE (id); + decl_attr = DECL_ATTRIBUTES (id); + typedef_decl = id; + } + } + /* Built-in types come as identifiers. */ + else if (TREE_CODE (id) == IDENTIFIER_NODE) + { + tree t = lookup_name (id); + if (TREE_TYPE (t) == error_mark_node) + ; + else if (!t || TREE_CODE (t) != TYPE_DECL) + error ("`%s' fails to be a typedef or built in type", + IDENTIFIER_POINTER (id)); + else + { + type = TREE_TYPE (t); + typedef_decl = t; + } + } + else if (TREE_CODE (id) != ERROR_MARK) + type = id; + + found: + ; } typedef_type = type; - size_varies = C_TYPE_VARIABLE_SIZE (type); + if (type) + size_varies = C_TYPE_VARIABLE_SIZE (type); - /* Diagnose defaulting to "int". */ + /* No type at all: default to `int', and set DEFAULTED_INT + because it was not a user-defined typedef. */ - if (declspecs->default_int_p && !in_system_header) + if (type == 0) { - /* Issue a warning if this is an ISO C 99 program or if - -Wreturn-type and this is a function, or if -Wimplicit; - prefer the former warning since it is more explicit. */ - if ((warn_implicit_int || warn_return_type || flag_isoc99) - && funcdef_flag) - warn_about_return_type = 1; - else if (warn_implicit_int || flag_isoc99) - pedwarn_c99 ("type defaults to %<int%> in declaration of %qs", name); + if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_SIGNED) + | (1 << (int) RID_UNSIGNED) + | (1 << (int) RID_COMPLEX)))) + /* Don't warn about typedef foo = bar. */ + && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized) + && ! in_system_header) + { + /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type + and this is a function, or if -Wimplicit; prefer the former + warning since it is more explicit. */ + if ((warn_implicit_int || warn_return_type || flag_isoc99) + && funcdef_flag) + warn_about_return_type = 1; + else if (warn_implicit_int || flag_isoc99) + pedwarn_c99 ("type defaults to `int' in declaration of `%s'", + name); + } + + defaulted_int = 1; + type = integer_type_node; } - /* Adjust the type if a bit-field is being declared, - -funsigned-bitfields applied and the type is not explicitly - "signed". */ - if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p - && TREE_CODE (type) == INTEGER_TYPE) - type = c_common_unsigned_type (type); + /* Now process the modifiers that were specified + and check for invalid combinations. */ + + /* Long double is a special combination. */ + + if ((specbits & 1 << (int) RID_LONG) && ! longlong + && TYPE_MAIN_VARIANT (type) == double_type_node) + { + specbits &= ~(1 << (int) RID_LONG); + type = long_double_type_node; + } + + /* Check all other uses of type modifiers. */ + + if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED))) + { + int ok = 0; + + if ((specbits & 1 << (int) RID_LONG) + && (specbits & 1 << (int) RID_SHORT)) + error ("both long and short specified for `%s'", name); + else if (((specbits & 1 << (int) RID_LONG) + || (specbits & 1 << (int) RID_SHORT)) + && explicit_char) + error ("long or short specified with char for `%s'", name); + else if (((specbits & 1 << (int) RID_LONG) + || (specbits & 1 << (int) RID_SHORT)) + && TREE_CODE (type) == REAL_TYPE) + { + static int already = 0; + + error ("long or short specified with floating type for `%s'", name); + if (! already && ! pedantic) + { + error ("the only valid combination is `long double'"); + already = 1; + } + } + else if ((specbits & 1 << (int) RID_SIGNED) + && (specbits & 1 << (int) RID_UNSIGNED)) + error ("both signed and unsigned specified for `%s'", name); + else if (TREE_CODE (type) != INTEGER_TYPE) + error ("long, short, signed or unsigned invalid for `%s'", name); + else + { + ok = 1; + if (!explicit_int && !defaulted_int && !explicit_char) + { + error ("long, short, signed or unsigned used invalidly for `%s'", + name); + ok = 0; + } + } + + /* Discard the type modifiers if they are invalid. */ + if (! ok) + { + specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)); + longlong = 0; + } + } + + if ((specbits & (1 << (int) RID_COMPLEX)) + && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) + { + error ("complex invalid for `%s'", name); + specbits &= ~(1 << (int) RID_COMPLEX); + } + + /* Decide whether an integer type is signed or not. + Optionally treat bit-fields as signed by default. */ + if (specbits & 1 << (int) RID_UNSIGNED + || (bitfield && ! flag_signed_bitfields + && (explicit_int || defaulted_int || explicit_char + /* A typedef for plain `int' without `signed' + can be controlled just like plain `int'. */ + || ! (typedef_decl != 0 + && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) + && TREE_CODE (type) != ENUMERAL_TYPE + && !(specbits & 1 << (int) RID_SIGNED))) + { + if (longlong) + type = long_long_unsigned_type_node; + else if (specbits & 1 << (int) RID_LONG) + type = long_unsigned_type_node; + else if (specbits & 1 << (int) RID_SHORT) + type = short_unsigned_type_node; + else if (type == char_type_node) + type = unsigned_char_type_node; + else if (typedef_decl) + type = c_common_unsigned_type (type); + else + type = unsigned_type_node; + } + else if ((specbits & 1 << (int) RID_SIGNED) + && type == char_type_node) + type = signed_char_type_node; + else if (longlong) + type = long_long_integer_type_node; + else if (specbits & 1 << (int) RID_LONG) + type = long_integer_type_node; + else if (specbits & 1 << (int) RID_SHORT) + type = short_integer_type_node; + + if (specbits & 1 << (int) RID_COMPLEX) + { + if (pedantic && !flag_isoc99) + pedwarn ("ISO C90 does not support complex types"); + /* If we just have "complex", it is equivalent to + "complex double", but if any modifiers at all are specified it is + the complex form of TYPE. E.g, "complex short" is + "complex short int". */ + + if (defaulted_int && ! longlong + && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_SIGNED) + | (1 << (int) RID_UNSIGNED)))) + { + if (pedantic) + pedwarn ("ISO C does not support plain `complex' meaning `double complex'"); + type = complex_double_type_node; + } + else if (type == integer_type_node) + { + if (pedantic) + pedwarn ("ISO C does not support complex integer types"); + type = complex_integer_type_node; + } + else if (type == float_type_node) + type = complex_float_type_node; + else if (type == double_type_node) + type = complex_double_type_node; + else if (type == long_double_type_node) + type = complex_long_double_type_node; + else + { + if (pedantic) + pedwarn ("ISO C does not support complex integer types"); + type = build_complex_type (type); + } + } /* Figure out the type qualifiers for the declaration. There are two ways a declaration can become qualified. One is something @@ -3999,132 +3657,141 @@ grokdeclarator (const struct c_declarator *declarator, duplicate qualifiers should be diagnosed in this case, but it seems most appropriate to do so). */ element_type = strip_array_types (type); - constp = declspecs->const_p + TYPE_READONLY (element_type); - restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type); - volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type); + constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (element_type); + restrictp + = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type); + volatilep + = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type); + inlinep = !! (specbits & (1 << (int) RID_INLINE)); if (pedantic && !flag_isoc99) { if (constp > 1) - pedwarn ("duplicate %<const%>"); + pedwarn ("duplicate `const'"); if (restrictp > 1) - pedwarn ("duplicate %<restrict%>"); + pedwarn ("duplicate `restrict'"); if (volatilep > 1) - pedwarn ("duplicate %<volatile%>"); + pedwarn ("duplicate `volatile'"); } - if (!flag_gen_aux_info && (TYPE_QUALS (element_type))) + if (! flag_gen_aux_info && (TYPE_QUALS (type))) type = TYPE_MAIN_VARIANT (type); type_quals = ((constp ? TYPE_QUAL_CONST : 0) | (restrictp ? TYPE_QUAL_RESTRICT : 0) | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - /* Warn about storage classes that are invalid for certain - kinds of declarations (parameters, typenames, etc.). */ - - if (funcdef_flag - && (threadp - || storage_class == csc_auto - || storage_class == csc_register - || storage_class == csc_typedef)) - { - if (storage_class == csc_auto - && (pedantic || current_scope == file_scope)) - pedwarn ("function definition declared %<auto%>"); - if (storage_class == csc_register) - error ("function definition declared %<register%>"); - if (storage_class == csc_typedef) - error ("function definition declared %<typedef%>"); - if (threadp) - error ("function definition declared %<__thread%>"); - threadp = false; - if (storage_class == csc_auto - || storage_class == csc_register - || storage_class == csc_typedef) - storage_class = csc_none; - } - else if (decl_context != NORMAL && (storage_class != csc_none || threadp)) - { - if (decl_context == PARM && storage_class == csc_register) - ; - else - { - switch (decl_context) - { - case FIELD: - error ("storage class specified for structure field %qs", - name); - break; - case PARM: - error ("storage class specified for parameter %qs", name); - break; - default: - error ("storage class specified for typename"); - break; - } - storage_class = csc_none; - threadp = false; - } - } - else if (storage_class == csc_extern - && initialized - && !funcdef_flag) - { - /* 'extern' with initialization is invalid if not at file scope. */ - if (current_scope == file_scope) - { - /* It is fine to have 'extern const' when compiling at C - and C++ intersection. */ - if (!(warn_cxx_compat && constp)) - warning (0, "%qs initialized and declared %<extern%>", name); - } - else - error ("%qs has both %<extern%> and initializer", name); - } - else if (current_scope == file_scope) - { - if (storage_class == csc_auto) - error ("file-scope declaration of %qs specifies %<auto%>", name); - if (pedantic && storage_class == csc_register) - pedwarn ("file-scope declaration of %qs specifies %<register%>", name); - } - else - { - if (storage_class == csc_extern && funcdef_flag) - error ("nested function %qs declared %<extern%>", name); - else if (threadp && storage_class == csc_none) - { - error ("function-scope %qs implicitly auto and declared " - "%<__thread%>", - name); - threadp = false; - } - } + /* Warn if two storage classes are given. Default to `auto'. */ + + { + int nclasses = 0; + + if (specbits & 1 << (int) RID_AUTO) nclasses++; + if (specbits & 1 << (int) RID_STATIC) nclasses++; + if (specbits & 1 << (int) RID_EXTERN) nclasses++; + if (specbits & 1 << (int) RID_REGISTER) nclasses++; + if (specbits & 1 << (int) RID_TYPEDEF) nclasses++; + + /* "static __thread" and "extern __thread" are allowed. */ + if ((specbits & (1 << (int) RID_THREAD + | 1 << (int) RID_STATIC + | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD)) + nclasses++; + + /* Warn about storage classes that are invalid for certain + kinds of declarations (parameters, typenames, etc.). */ + + if (nclasses > 1) + error ("multiple storage classes in declaration of `%s'", name); + else if (funcdef_flag + && (specbits + & ((1 << (int) RID_REGISTER) + | (1 << (int) RID_AUTO) + | (1 << (int) RID_TYPEDEF) + | (1 << (int) RID_THREAD)))) + { + if (specbits & 1 << (int) RID_AUTO + && (pedantic || current_scope == global_scope)) + pedwarn ("function definition declared `auto'"); + if (specbits & 1 << (int) RID_REGISTER) + error ("function definition declared `register'"); + if (specbits & 1 << (int) RID_TYPEDEF) + error ("function definition declared `typedef'"); + if (specbits & 1 << (int) RID_THREAD) + error ("function definition declared `__thread'"); + specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) + | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD)); + } + else if (decl_context != NORMAL && nclasses > 0) + { + if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER) + ; + else + { + switch (decl_context) + { + case FIELD: + error ("storage class specified for structure field `%s'", + name); + break; + case PARM: + error ("storage class specified for parameter `%s'", name); + break; + default: + error ("storage class specified for typename"); + break; + } + specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) + | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC) + | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD)); + } + } + else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag) + { + /* `extern' with initialization is invalid if not at file scope. */ + if (current_scope == global_scope) + warning ("`%s' initialized and declared `extern'", name); + else + error ("`%s' has both `extern' and initializer", name); + } + else if (current_scope == global_scope) + { + if (specbits & 1 << (int) RID_AUTO) + error ("file-scope declaration of `%s' specifies `auto'", name); + } + else + { + if (specbits & 1 << (int) RID_EXTERN && funcdef_flag) + error ("nested function `%s' declared `extern'", name); + else if ((specbits & (1 << (int) RID_THREAD + | 1 << (int) RID_EXTERN + | 1 << (int) RID_STATIC)) + == (1 << (int) RID_THREAD)) + { + error ("function-scope `%s' implicitly auto and declared `__thread'", + name); + specbits &= ~(1 << (int) RID_THREAD); + } + } + } /* Now figure out the structure of the declarator proper. Descend through it, creating more complex types, until we reach - the declared identifier (or NULL_TREE, in an absolute declarator). - At each stage we maintain an unqualified version of the type - together with any qualifiers that should be applied to it with - c_build_qualified_type; this way, array types including - multidimensional array types are first built up in unqualified - form and then the qualified form is created with - TYPE_MAIN_VARIANT pointing to the unqualified form. */ + the declared identifier (or NULL_TREE, in an absolute declarator). */ - while (declarator && declarator->kind != cdk_id) + while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE) { if (type == error_mark_node) { - declarator = declarator->declarator; + declarator = TREE_OPERAND (declarator, 0); continue; } - /* Each level of DECLARATOR is either a cdk_array (for ...[..]), - a cdk_pointer (for *...), - a cdk_function (for ...(...)), - a cdk_attrs (for nested attributes), - or a cdk_id (for the name being declared - or the place in an absolute declarator + /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]), + an INDIRECT_REF (for *...), + a CALL_EXPR (for ...(...)), + a TREE_LIST (for nested attributes), + an identifier (for the name being declared) + or a null pointer (for the place in an absolute declarator where the name was omitted). - For the last case, we have just exited the loop. + For the last two cases, we have just exited the loop. At this point, TYPE is the type of elements of an array, or for a function to return, or for a pointer to point to. @@ -4132,410 +3799,360 @@ grokdeclarator (const struct c_declarator *declarator, array or function or pointer, and DECLARATOR has had its outermost layer removed. */ - if (array_ptr_quals != TYPE_UNQUALIFIED - || array_ptr_attrs != NULL_TREE - || array_parm_static) + if (array_ptr_quals != NULL_TREE || array_parm_static) { /* Only the innermost declarator (making a parameter be of array type which is converted to pointer type) may have static or type qualifiers. */ error ("static or type qualifiers in non-parameter array declarator"); - array_ptr_quals = TYPE_UNQUALIFIED; - array_ptr_attrs = NULL_TREE; + array_ptr_quals = NULL_TREE; array_parm_static = 0; } - switch (declarator->kind) + if (TREE_CODE (declarator) == TREE_LIST) { - case cdk_attrs: - { - /* A declarator with embedded attributes. */ - tree attrs = declarator->u.attrs; - const struct c_declarator *inner_decl; - int attr_flags = 0; - declarator = declarator->declarator; - inner_decl = declarator; - while (inner_decl->kind == cdk_attrs) - inner_decl = inner_decl->declarator; - if (inner_decl->kind == cdk_id) - attr_flags |= (int) ATTR_FLAG_DECL_NEXT; - else if (inner_decl->kind == cdk_function) - attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; - else if (inner_decl->kind == cdk_array) - attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; - returned_attrs = decl_attributes (&type, - chainon (returned_attrs, attrs), - attr_flags); - break; - } - case cdk_array: - { - tree itype = NULL_TREE; - tree size = declarator->u.array.dimen; - /* The index is a signed object `sizetype' bits wide. */ - tree index_type = c_common_signed_type (sizetype); + /* We encode a declarator with embedded attributes using + a TREE_LIST. */ + tree attrs = TREE_PURPOSE (declarator); + tree inner_decl; + int attr_flags = 0; + declarator = TREE_VALUE (declarator); + inner_decl = declarator; + while (inner_decl != NULL_TREE + && TREE_CODE (inner_decl) == TREE_LIST) + inner_decl = TREE_VALUE (inner_decl); + if (inner_decl == NULL_TREE + || TREE_CODE (inner_decl) == IDENTIFIER_NODE) + attr_flags |= (int) ATTR_FLAG_DECL_NEXT; + else if (TREE_CODE (inner_decl) == CALL_EXPR) + attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; + else if (TREE_CODE (inner_decl) == ARRAY_REF) + attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; + returned_attrs = decl_attributes (&type, + chainon (returned_attrs, attrs), + attr_flags); + } + else if (TREE_CODE (declarator) == ARRAY_REF) + { + tree itype = NULL_TREE; + tree size = TREE_OPERAND (declarator, 1); + /* The index is a signed object `sizetype' bits wide. */ + tree index_type = c_common_signed_type (sizetype); - array_ptr_quals = declarator->u.array.quals; - array_ptr_attrs = declarator->u.array.attrs; - array_parm_static = declarator->u.array.static_p; - array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; + array_ptr_quals = TREE_TYPE (declarator); + array_parm_static = TREE_STATIC (declarator); - declarator = declarator->declarator; + declarator = TREE_OPERAND (declarator, 0); - /* Check for some types that there cannot be arrays of. */ + /* Check for some types that there cannot be arrays of. */ - if (VOID_TYPE_P (type)) - { - error ("declaration of %qs as array of voids", name); - type = error_mark_node; - } + if (VOID_TYPE_P (type)) + { + error ("declaration of `%s' as array of voids", name); + type = error_mark_node; + } - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("declaration of %qs as array of functions", name); - type = error_mark_node; - } + if (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("declaration of `%s' as array of functions", name); + type = error_mark_node; + } - if (pedantic && !in_system_header && flexible_array_type_p (type)) - pedwarn ("invalid use of structure with flexible array member"); + if (pedantic && !in_system_header && flexible_array_type_p (type)) + pedwarn ("invalid use of structure with flexible array member"); - if (size == error_mark_node) - type = error_mark_node; + if (size == error_mark_node) + type = error_mark_node; - if (type == error_mark_node) - continue; + if (type == error_mark_node) + continue; - /* If size was specified, set ITYPE to a range-type for - that size. Otherwise, ITYPE remains null. finish_decl - may figure it out from an initial value. */ + /* If size was specified, set ITYPE to a range-type for that size. + Otherwise, ITYPE remains null. finish_decl may figure it out + from an initial value. */ - if (size) - { - /* Strip NON_LVALUE_EXPRs since we aren't using as an - lvalue. */ - STRIP_TYPE_NOPS (size); + if (size) + { + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + STRIP_TYPE_NOPS (size); - if (!INTEGRAL_TYPE_P (TREE_TYPE (size))) - { - error ("size of array %qs has non-integer type", name); - size = integer_one_node; - } + if (! INTEGRAL_TYPE_P (TREE_TYPE (size))) + { + error ("size of array `%s' has non-integer type", name); + size = integer_one_node; + } - if (pedantic && integer_zerop (size)) - pedwarn ("ISO C forbids zero-size array %qs", name); + if (pedantic && integer_zerop (size)) + pedwarn ("ISO C forbids zero-size array `%s'", name); - if (TREE_CODE (size) == INTEGER_CST) - { - constant_expression_warning (size); - if (tree_int_cst_sgn (size) < 0) - { - error ("size of array %qs is negative", name); - size = integer_one_node; - } - } - else if ((decl_context == NORMAL || decl_context == FIELD) - && current_scope == file_scope) - { - error ("variably modified %qs at file scope", name); - size = integer_one_node; - } - else - { - /* Make sure the array size remains visibly - nonconstant even if it is (eg) a const variable - with known value. */ - size_varies = 1; + if (TREE_CODE (size) == INTEGER_CST) + { + constant_expression_warning (size); + if (tree_int_cst_sgn (size) < 0) + { + error ("size of array `%s' is negative", name); + size = integer_one_node; + } + } + else + { + /* Make sure the array size remains visibly nonconstant + even if it is (eg) a const variable with known value. */ + size_varies = 1; - if (!flag_isoc99 && pedantic) - { - if (TREE_CONSTANT (size)) - pedwarn ("ISO C90 forbids array %qs whose size " - "can%'t be evaluated", - name); - else - pedwarn ("ISO C90 forbids variable-size array %qs", - name); - } - } + if (!flag_isoc99 && pedantic) + { + if (TREE_CONSTANT (size)) + pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated", + name); + else + pedwarn ("ISO C90 forbids variable-size array `%s'", + name); + } + } - if (integer_zerop (size)) - { - /* A zero-length array cannot be represented with - an unsigned index type, which is what we'll - get with build_index_type. Create an - open-ended range instead. */ - itype = build_range_type (sizetype, size, NULL_TREE); - } - else - { - /* Arrange for the SAVE_EXPR on the inside of the - MINUS_EXPR, which allows the -1 to get folded - with the +1 that happens when building TYPE_SIZE. */ - if (size_varies) - size = variable_size (size); - - /* Compute the maximum valid index, that is, size - - 1. Do the calculation in index_type, so that - if it is a variable the computations will be - done in the proper mode. */ - itype = fold_build2 (MINUS_EXPR, index_type, - convert (index_type, size), - convert (index_type, - size_one_node)); - - /* If that overflowed, the array is too big. ??? - While a size of INT_MAX+1 technically shouldn't - cause an overflow (because we subtract 1), the - overflow is recorded during the conversion to - index_type, before the subtraction. Handling - this case seems like an unnecessary - complication. */ - if (TREE_CODE (itype) == INTEGER_CST - && TREE_OVERFLOW (itype)) - { - error ("size of array %qs is too large", name); - type = error_mark_node; - continue; - } + if (integer_zerop (size)) + { + /* A zero-length array cannot be represented with an + unsigned index type, which is what we'll get with + build_index_type. Create an open-ended range instead. */ + itype = build_range_type (sizetype, size, NULL_TREE); + } + else + { + /* Compute the maximum valid index, that is, size - 1. + Do the calculation in index_type, so that if it is + a variable the computations will be done in the + proper mode. */ + itype = fold (build (MINUS_EXPR, index_type, + convert (index_type, size), + convert (index_type, size_one_node))); + + /* If that overflowed, the array is too big. + ??? While a size of INT_MAX+1 technically shouldn't + cause an overflow (because we subtract 1), the overflow + is recorded during the conversion to index_type, before + the subtraction. Handling this case seems like an + unnecessary complication. */ + if (TREE_OVERFLOW (itype)) + { + error ("size of array `%s' is too large", name); + type = error_mark_node; + continue; + } - itype = build_index_type (itype); - } - } - else if (decl_context == FIELD) - { - if (pedantic && !flag_isoc99 && !in_system_header) - pedwarn ("ISO C90 does not support flexible array members"); + if (size_varies) + { + /* We must be able to distinguish the + SAVE_EXPR_CONTEXT for the variably-sized type + so that we can set it correctly in + set_save_expr_context. The convention is + that all SAVE_EXPRs that need to be reset + have NULL_TREE for their SAVE_EXPR_CONTEXT. */ + tree cfd = current_function_decl; + if (decl_context == PARM) + current_function_decl = NULL_TREE; + itype = variable_size (itype); + if (decl_context == PARM) + current_function_decl = cfd; + } + itype = build_index_type (itype); + } + } + else if (decl_context == FIELD) + { + if (pedantic && !flag_isoc99 && !in_system_header) + pedwarn ("ISO C90 does not support flexible array members"); - /* ISO C99 Flexible array members are effectively - identical to GCC's zero-length array extension. */ - itype = build_range_type (sizetype, size_zero_node, NULL_TREE); - } - else if (decl_context == PARM) - { - if (array_parm_vla_unspec_p) - { - if (! orig_name) - { - /* C99 6.7.5.2p4 */ - error ("%<[*]%> not allowed in other than a declaration"); - } + /* ISO C99 Flexible array members are effectively identical + to GCC's zero-length array extension. */ + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + } - itype = build_range_type (sizetype, size_zero_node, NULL_TREE); - size_varies = 1; - } - } - else if (decl_context == TYPENAME) - { - if (array_parm_vla_unspec_p) - { - /* The error is printed elsewhere. We use this to - avoid messing up with incomplete array types of - the same type, that would otherwise be modified - below. */ - itype = build_range_type (sizetype, size_zero_node, - NULL_TREE); - } - } + /* If pedantic, complain about arrays of incomplete types. */ - /* Complain about arrays of incomplete types. */ - if (!COMPLETE_TYPE_P (type)) - { - error ("array type has incomplete element type"); - type = error_mark_node; - } - else - /* When itype is NULL, a shared incomplete array type is - returned for all array of a given type. Elsewhere we - make sure we don't complete that type before copying - it, but here we want to make sure we don't ever - modify the shared type, so we gcc_assert (itype) - below. */ - type = build_array_type (type, itype); - - if (type != error_mark_node) - { - if (size_varies) - { - /* It is ok to modify type here even if itype is - NULL: if size_varies, we're in a - multi-dimensional array and the inner type has - variable size, so the enclosing shared array type - must too. */ - if (size && TREE_CODE (size) == INTEGER_CST) - type - = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); - C_TYPE_VARIABLE_SIZE (type) = 1; - } + if (pedantic && !COMPLETE_TYPE_P (type)) + pedwarn ("array type has incomplete element type"); - /* The GCC extension for zero-length arrays differs from - ISO flexible array members in that sizeof yields - zero. */ - if (size && integer_zerop (size)) - { - gcc_assert (itype); - TYPE_SIZE (type) = bitsize_zero_node; - TYPE_SIZE_UNIT (type) = size_zero_node; - } - if (array_parm_vla_unspec_p) - { - gcc_assert (itype); - /* The type is complete. C99 6.7.5.2p4 */ - TYPE_SIZE (type) = bitsize_zero_node; - TYPE_SIZE_UNIT (type) = size_zero_node; - } - } + /* Build the array type itself, then merge any constancy or + volatility into the target type. We must do it in this order + to ensure that the TYPE_MAIN_VARIANT field of the array type + is set correctly. */ - if (decl_context != PARM - && (array_ptr_quals != TYPE_UNQUALIFIED - || array_ptr_attrs != NULL_TREE - || array_parm_static)) - { - error ("static or type qualifiers in non-parameter array declarator"); - array_ptr_quals = TYPE_UNQUALIFIED; - array_ptr_attrs = NULL_TREE; - array_parm_static = 0; - } - break; - } - case cdk_function: - { - /* Say it's a definition only for the declarator closest - to the identifier, apart possibly from some - attributes. */ - bool really_funcdef = false; - tree arg_types; - if (funcdef_flag) - { - const struct c_declarator *t = declarator->declarator; - while (t->kind == cdk_attrs) - t = t->declarator; - really_funcdef = (t->kind == cdk_id); - } + type = build_array_type (type, itype); + if (type_quals) + type = c_build_qualified_type (type, type_quals); - /* Declaring a function type. Make sure we have a valid - type for the function to return. */ - if (type == error_mark_node) - continue; + if (size_varies) + C_TYPE_VARIABLE_SIZE (type) = 1; - size_varies = 0; + /* The GCC extension for zero-length arrays differs from + ISO flexible array members in that sizeof yields zero. */ + if (size && integer_zerop (size)) + { + layout_type (type); + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + } + if (decl_context != PARM + && (array_ptr_quals != NULL_TREE || array_parm_static)) + { + error ("static or type qualifiers in non-parameter array declarator"); + array_ptr_quals = NULL_TREE; + array_parm_static = 0; + } + } + else if (TREE_CODE (declarator) == CALL_EXPR) + { + /* Say it's a definition only for the declarator closest to + the identifier, apart possibly from some attributes. */ + bool really_funcdef = false; + tree arg_types; + if (funcdef_flag) + { + tree t = TREE_OPERAND (declarator, 0); + while (TREE_CODE (t) == TREE_LIST) + t = TREE_VALUE (t); + really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE); + } - /* Warn about some types functions can't return. */ - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("%qs declared as function returning a function", name); - type = integer_type_node; - } - if (TREE_CODE (type) == ARRAY_TYPE) - { - error ("%qs declared as function returning an array", name); - type = integer_type_node; - } + /* Declaring a function type. + Make sure we have a valid type for the function to return. */ + if (type == error_mark_node) + continue; - /* Construct the function type and go to the next - inner layer of declarator. */ - arg_info = declarator->u.arg_info; - arg_types = grokparms (arg_info, really_funcdef); - if (really_funcdef) - put_pending_sizes (arg_info->pending_sizes); + size_varies = 0; - /* Type qualifiers before the return type of the function - qualify the return type, not the function type. */ - if (type_quals) - { - /* Type qualifiers on a function return type are - normally permitted by the standard but have no - effect, so give a warning at -Wreturn-type. - Qualifiers on a void return type are banned on - function definitions in ISO C; GCC used to used - them for noreturn functions. */ - if (VOID_TYPE_P (type) && really_funcdef) - pedwarn ("function definition has qualified void return type"); - else - warning (OPT_Wreturn_type, - "type qualifiers ignored on function return type"); + /* Warn about some types functions can't return. */ - type = c_build_qualified_type (type, type_quals); - } - type_quals = TYPE_UNQUALIFIED; + if (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("`%s' declared as function returning a function", name); + type = integer_type_node; + } + if (TREE_CODE (type) == ARRAY_TYPE) + { + error ("`%s' declared as function returning an array", name); + type = integer_type_node; + } - type = build_function_type (type, arg_types); - declarator = declarator->declarator; + /* Construct the function type and go to the next + inner layer of declarator. */ - /* Set the TYPE_CONTEXTs for each tagged type which is local to - the formal parameter list of this FUNCTION_TYPE to point to - the FUNCTION_TYPE node itself. */ + arg_types = grokparms (TREE_OPERAND (declarator, 1), + really_funcdef); + /* Type qualifiers before the return type of the function + qualify the return type, not the function type. */ + if (type_quals) { - tree link; + /* Type qualifiers on a function return type are normally + permitted by the standard but have no effect, so give a + warning at -Wextra. Qualifiers on a void return type have + meaning as a GNU extension, and are banned on function + definitions in ISO C. FIXME: strictly we shouldn't + pedwarn for qualified void return types except on function + definitions, but not doing so could lead to the undesirable + state of a "volatile void" function return type not being + warned about, and a use of the function being compiled + with GNU semantics, with no diagnostics under -pedantic. */ + if (VOID_TYPE_P (type) && pedantic && !in_system_header) + pedwarn ("ISO C forbids qualified void function return type"); + else if (extra_warnings + && !(VOID_TYPE_P (type) + && type_quals == TYPE_QUAL_VOLATILE)) + warning ("type qualifiers ignored on function return type"); - for (link = arg_info->tags; - link; - link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = type; + type = c_build_qualified_type (type, type_quals); } - break; - } - case cdk_pointer: + type_quals = TYPE_UNQUALIFIED; + + type = build_function_type (type, arg_types); + declarator = TREE_OPERAND (declarator, 0); + + /* Set the TYPE_CONTEXTs for each tagged type which is local to + the formal parameter list of this FUNCTION_TYPE to point to + the FUNCTION_TYPE node itself. */ + { - /* Merge any constancy or volatility into the target type - for the pointer. */ + tree link; - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && type_quals) - pedwarn ("ISO C forbids qualified function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - size_varies = 0; + for (link = last_function_parm_tags; + link; + link = TREE_CHAIN (link)) + TYPE_CONTEXT (TREE_VALUE (link)) = type; + } + } + else if (TREE_CODE (declarator) == INDIRECT_REF) + { + /* Merge any constancy or volatility into the target type + for the pointer. */ - /* When the pointed-to type involves components of variable size, - care must be taken to ensure that the size evaluation code is - emitted early enough to dominate all the possible later uses - and late enough for the variables on which it depends to have - been assigned. - - This is expected to happen automatically when the pointed-to - type has a name/declaration of it's own, but special attention - is required if the type is anonymous. - - We handle the NORMAL and FIELD contexts here by attaching an - artificial TYPE_DECL to such pointed-to type. This forces the - sizes evaluation at a safe point and ensures it is not deferred - until e.g. within a deeper conditional context. - - We expect nothing to be needed here for PARM or TYPENAME. - Pushing a TYPE_DECL at this point for TYPENAME would actually - be incorrect, as we might be in the middle of an expression - with side effects on the pointed-to type size "arguments" prior - to the pointer declaration point and the fake TYPE_DECL in the - enclosing context would force the size evaluation prior to the - side effects. */ - - if (!TYPE_NAME (type) - && (decl_context == NORMAL || decl_context == FIELD) - && variably_modified_type_p (type, NULL_TREE)) - { - tree decl = build_decl (TYPE_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (decl) = 1; - pushdecl (decl); - finish_decl (decl, NULL_TREE, NULL_TREE); - TYPE_NAME (type) = decl; - } + if (pedantic && TREE_CODE (type) == FUNCTION_TYPE + && type_quals) + pedwarn ("ISO C forbids qualified function types"); + if (type_quals) + type = c_build_qualified_type (type, type_quals); + type_quals = TYPE_UNQUALIFIED; + size_varies = 0; - type = build_pointer_type (type); + type = build_pointer_type (type); - /* Process type qualifiers (such as const or volatile) - that were given inside the `*'. */ - type_quals = declarator->u.pointer_quals; + /* Process a list of type modifier keywords + (such as const or volatile) that were given inside the `*'. */ - declarator = declarator->declarator; - break; - } - default: - gcc_unreachable (); + if (TREE_TYPE (declarator)) + { + tree typemodlist; + int erred = 0; + + constp = 0; + volatilep = 0; + restrictp = 0; + for (typemodlist = TREE_TYPE (declarator); typemodlist; + typemodlist = TREE_CHAIN (typemodlist)) + { + tree qualifier = TREE_VALUE (typemodlist); + + if (C_IS_RESERVED_WORD (qualifier)) + { + if (C_RID_CODE (qualifier) == RID_CONST) + constp++; + else if (C_RID_CODE (qualifier) == RID_VOLATILE) + volatilep++; + else if (C_RID_CODE (qualifier) == RID_RESTRICT) + restrictp++; + else + erred++; + } + else + erred++; + } + + if (erred) + error ("invalid type modifier within pointer declarator"); + if (pedantic && !flag_isoc99) + { + if (constp > 1) + pedwarn ("duplicate `const'"); + if (volatilep > 1) + pedwarn ("duplicate `volatile'"); + if (restrictp > 1) + pedwarn ("duplicate `restrict'"); + } + + type_quals = ((constp ? TYPE_QUAL_CONST : 0) + | (restrictp ? TYPE_QUAL_RESTRICT : 0) + | (volatilep ? TYPE_QUAL_VOLATILE : 0)); + } + + declarator = TREE_OPERAND (declarator, 0); } + else + abort (); + } - /* Now TYPE has the actual type, apart from any qualifiers in - TYPE_QUALS. */ + /* Now TYPE has the actual type. */ /* Check the type and width of a bit-field. */ if (bitfield) @@ -4545,10 +4162,9 @@ grokdeclarator (const struct c_declarator *declarator, if (TREE_CODE (type) == ARRAY_TYPE && COMPLETE_TYPE_P (type) - && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST - && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) + && TREE_OVERFLOW (TYPE_SIZE (type))) { - error ("size of array %qs is too large", name); + error ("size of array `%s' is too large", name); /* If we proceed with the array type as it is, we'll eventually crash in tree_low_cst(). */ type = error_mark_node; @@ -4556,32 +4172,46 @@ grokdeclarator (const struct c_declarator *declarator, /* If this is declaring a typedef name, return a TYPE_DECL. */ - if (storage_class == csc_typedef) + if (specbits & (1 << (int) RID_TYPEDEF)) { tree decl; + /* Note that the grammar rejects storage classes + in typenames, fields or parameters */ if (pedantic && TREE_CODE (type) == FUNCTION_TYPE && type_quals) pedwarn ("ISO C forbids qualified function types"); if (type_quals) type = c_build_qualified_type (type, type_quals); - decl = build_decl (TYPE_DECL, declarator->u.id, type); - if (declspecs->explicit_signed_p) + decl = build_decl (TYPE_DECL, declarator, type); + if ((specbits & (1 << (int) RID_SIGNED)) + || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; decl_attributes (&decl, returned_attrs, 0); - if (declspecs->inline_p) - pedwarn ("typedef %q+D declared %<inline%>", decl); return decl; } + /* Detect the case of an array type of unspecified size + which came, as such, direct from a typedef name. + We must copy the type, so that each identifier gets + a distinct type, so that each identifier's size can be + controlled separately by its own initializer. */ + + if (type != 0 && typedef_type != 0 + && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0 + && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)) + { + type = build_array_type (TREE_TYPE (type), 0); + if (size_varies) + C_TYPE_VARIABLE_SIZE (type) = 1; + } + /* If this is a type name (such as, in a cast or sizeof), compute the type and return it now. */ if (decl_context == TYPENAME) { - /* Note that the grammar rejects storage classes in typenames - and fields. */ - gcc_assert (storage_class == csc_none && !threadp - && !declspecs->inline_p); + /* Note that the grammar rejects storage classes + in typenames, fields or parameters */ if (pedantic && TREE_CODE (type) == FUNCTION_TYPE && type_quals) pedwarn ("ISO C forbids const or volatile function types"); @@ -4591,13 +4221,6 @@ grokdeclarator (const struct c_declarator *declarator, return type; } - if (pedantic && decl_context == FIELD - && variably_modified_type_p (type, NULL_TREE)) - { - /* C99 6.7.2.1p8 */ - pedwarn ("a member of a structure or union cannot have a variably modified type"); - } - /* Aside from typedefs and type names (handle above), `void' at top level (not within pointer) is allowed only in public variables. @@ -4605,13 +4228,13 @@ grokdeclarator (const struct c_declarator *declarator, a better error message can be made later. */ if (VOID_TYPE_P (type) && decl_context != PARM - && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) - && (storage_class == csc_extern - || (current_scope == file_scope - && !(storage_class == csc_static - || storage_class == csc_register))))) + && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) + && ((specbits & (1 << (int) RID_EXTERN)) + || (current_scope == global_scope + && !(specbits + & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))))))) { - error ("variable or field %qs declared void", name); + error ("variable or field `%s' declared void", name); type = integer_type_node; } @@ -4636,13 +4259,45 @@ grokdeclarator (const struct c_declarator *declarator, if (type_quals) type = c_build_qualified_type (type, type_quals); type = build_pointer_type (type); - type_quals = array_ptr_quals; + type_quals = TYPE_UNQUALIFIED; + if (array_ptr_quals) + { + tree new_ptr_quals, new_ptr_attrs; + int erred = 0; + split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs); + /* We don't yet implement attributes in this context. */ + if (new_ptr_attrs != NULL_TREE) + warning ("attributes in parameter array declarator ignored"); + + constp = 0; + volatilep = 0; + restrictp = 0; + for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals)) + { + tree qualifier = TREE_VALUE (new_ptr_quals); - /* We don't yet implement attributes in this context. */ - if (array_ptr_attrs != NULL_TREE) - warning (OPT_Wattributes, - "attributes in parameter array declarator ignored"); + if (C_IS_RESERVED_WORD (qualifier)) + { + if (C_RID_CODE (qualifier) == RID_CONST) + constp++; + else if (C_RID_CODE (qualifier) == RID_VOLATILE) + volatilep++; + else if (C_RID_CODE (qualifier) == RID_RESTRICT) + restrictp++; + else + erred++; + } + else + erred++; + } + + if (erred) + error ("invalid type modifier within array declarator"); + type_quals = ((constp ? TYPE_QUAL_CONST : 0) + | (restrictp ? TYPE_QUAL_RESTRICT : 0) + | (volatilep ? TYPE_QUAL_VOLATILE : 0)); + } size_varies = 0; } else if (TREE_CODE (type) == FUNCTION_TYPE) @@ -4659,7 +4314,7 @@ grokdeclarator (const struct c_declarator *declarator, type_as_written = type; - decl = build_decl (PARM_DECL, declarator->u.id, type); + decl = build_decl (PARM_DECL, declarator, type); if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; @@ -4674,31 +4329,29 @@ grokdeclarator (const struct c_declarator *declarator, promoted_type = c_type_promotes_to (type); DECL_ARG_TYPE (decl) = promoted_type; - if (declspecs->inline_p) - pedwarn ("parameter %q+D declared %<inline%>", decl); + DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; } else if (decl_context == FIELD) { - /* Note that the grammar rejects storage classes in typenames - and fields. */ - gcc_assert (storage_class == csc_none && !threadp - && !declspecs->inline_p); - /* Structure field. It may not be a function. */ if (TREE_CODE (type) == FUNCTION_TYPE) { - error ("field %qs declared as a function", name); + error ("field `%s' declared as a function", name); type = build_pointer_type (type); } else if (TREE_CODE (type) != ERROR_MARK - && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type)) + && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type)) { - error ("field %qs has incomplete type", name); + error ("field `%s' has incomplete type", name); type = error_mark_node; } - type = c_build_qualified_type (type, type_quals); - decl = build_decl (FIELD_DECL, declarator->u.id, type); + /* Move type qualifiers down to element of an array. */ + if (TREE_CODE (type) == ARRAY_TYPE && type_quals) + type = build_array_type (c_build_qualified_type (TREE_TYPE (type), + type_quals), + TYPE_DOMAIN (type)); + decl = build_decl (FIELD_DECL, declarator, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (size_varies) @@ -4706,75 +4359,60 @@ grokdeclarator (const struct c_declarator *declarator, } else if (TREE_CODE (type) == FUNCTION_TYPE) { - if (storage_class == csc_register || threadp) - { - error ("invalid storage class for function %qs", name); - } - else if (current_scope != file_scope) - { - /* Function declaration not at file scope. Storage - classes other than `extern' are not allowed, C99 - 6.7.1p5, and `extern' makes no difference. However, - GCC allows 'auto', perhaps with 'inline', to support - nested functions. */ - if (storage_class == csc_auto) - { - if (pedantic) - pedwarn ("invalid storage class for function %qs", name); - } - else if (storage_class == csc_static) - { - error ("invalid storage class for function %qs", name); - if (funcdef_flag) - storage_class = declspecs->storage_class = csc_none; - else - return 0; - } - } - - decl = build_decl (FUNCTION_DECL, declarator->u.id, type); + /* Every function declaration is "external" + except for those which are inside a function body + in which `auto' is used. + That is a case not specified by ANSI C, + and we use it for forward declarations for nested functions. */ + int extern_ref = (!(specbits & (1 << (int) RID_AUTO)) + || current_scope == global_scope); + + if (specbits & (1 << (int) RID_AUTO) + && (pedantic || current_scope == global_scope)) + pedwarn ("invalid storage class for function `%s'", name); + if (specbits & (1 << (int) RID_REGISTER)) + error ("invalid storage class for function `%s'", name); + if (specbits & (1 << (int) RID_THREAD)) + error ("invalid storage class for function `%s'", name); + /* Function declaration not at file scope. + Storage classes other than `extern' are not allowed + and `extern' makes no difference. */ + if (current_scope != global_scope + && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE))) + && pedantic) + pedwarn ("invalid storage class for function `%s'", name); + + decl = build_decl (FUNCTION_DECL, declarator, type); decl = build_decl_attribute_variant (decl, decl_attr); - DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl); + DECL_LANG_SPECIFIC (decl) + = ggc_alloc_cleared (sizeof (struct lang_decl)); - if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl)) + if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl)) pedwarn ("ISO C forbids qualified function types"); - /* GNU C interprets a volatile-qualified function type to indicate + /* GNU C interprets a `volatile void' return type to indicate that the function does not return. */ if ((type_quals & TYPE_QUAL_VOLATILE) && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) - warning (0, "%<noreturn%> function returns non-void value"); - - /* Every function declaration is an external reference - (DECL_EXTERNAL) except for those which are not at file - scope and are explicitly declared "auto". This is - forbidden by standard C (C99 6.7.1p5) and is interpreted by - GCC to signify a forward declaration of a nested function. */ - if (storage_class == csc_auto && current_scope != file_scope) - DECL_EXTERNAL (decl) = 0; - else - DECL_EXTERNAL (decl) = 1; + warning ("`noreturn' function returns non-void value"); + if (extern_ref) + DECL_EXTERNAL (decl) = 1; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) - = !(storage_class == csc_static || storage_class == csc_auto); - - /* For a function definition, record the argument information - block where store_parm_decls will look for it. */ - if (funcdef_flag) - current_function_arg_info = arg_info; + = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO))); - if (declspecs->default_int_p) + if (defaulted_int) C_FUNCTION_IMPLICIT_INT (decl) = 1; /* Record presence of `inline', if it is reasonable. */ - if (flag_hosted && MAIN_NAME_P (declarator->u.id)) + if (MAIN_NAME_P (declarator)) { - if (declspecs->inline_p) - pedwarn ("cannot inline function %<main%>"); + if (inlinep) + warning ("cannot inline function `main'"); } - else if (declspecs->inline_p) + else if (inlinep) { /* Record that the function is declared `inline'. */ DECL_DECLARED_INLINE_P (decl) = 1; @@ -4786,7 +4424,7 @@ grokdeclarator (const struct c_declarator *declarator, if (initialized) { DECL_INLINE (decl) = 1; - if (storage_class == csc_extern) + if (specbits & (1 << (int) RID_EXTERN)) current_extern_inline = 1; } } @@ -4800,62 +4438,66 @@ grokdeclarator (const struct c_declarator *declarator, { /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - int extern_ref = !initialized && storage_class == csc_extern; + int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); - type = c_build_qualified_type (type, type_quals); + /* Move type qualifiers down to element of an array. */ + if (TREE_CODE (type) == ARRAY_TYPE && type_quals) + { + int saved_align = TYPE_ALIGN(type); + type = build_array_type (c_build_qualified_type (TREE_TYPE (type), + type_quals), + TYPE_DOMAIN (type)); + TYPE_ALIGN (type) = saved_align; + } + else if (type_quals) + type = c_build_qualified_type (type, type_quals); - /* C99 6.2.2p7: It is invalid (compile-time undefined - behavior) to create an 'extern' declaration for a + /* It is invalid to create an `extern' declaration for a variable if there is a global declaration that is - 'static' and the global declaration is not visible. - (If the static declaration _is_ currently visible, - the 'extern' declaration is taken to refer to that decl.) */ - if (extern_ref && current_scope != file_scope) + `static' and the global declaration is not visible. */ + if (extern_ref && current_scope != global_scope) { - tree global_decl = identifier_global_value (declarator->u.id); - tree visible_decl = lookup_name (declarator->u.id); + tree global_decl; + global_decl = identifier_global_value (declarator); if (global_decl - && global_decl != visible_decl && TREE_CODE (global_decl) == VAR_DECL + && lookup_name (declarator) != global_decl && !TREE_PUBLIC (global_decl)) - error ("variable previously declared %<static%> redeclared " - "%<extern%>"); + error ("variable previously declared `static' redeclared " + "`extern'"); } - decl = build_decl (VAR_DECL, declarator->u.id, type); - DECL_SOURCE_LOCATION (decl) = declarator->id_loc; + decl = build_decl (VAR_DECL, declarator, type); if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; - if (declspecs->inline_p) - pedwarn ("variable %q+D declared %<inline%>", decl); + if (inlinep) + pedwarn ("%Jvariable '%D' declared `inline'", decl, decl); - /* At file scope, an initialized extern declaration may follow - a static declaration. In that case, DECL_EXTERNAL will be - reset later in start_decl. */ - DECL_EXTERNAL (decl) = (storage_class == csc_extern); + DECL_EXTERNAL (decl) = extern_ref; /* At file scope, the presence of a `static' or `register' storage class specifier, or the absence of all storage class specifiers makes this declaration a definition (perhaps tentative). Also, - the absence of `static' makes it public. */ - if (current_scope == file_scope) + the absence of both `static' and `register' makes it public. */ + if (current_scope == global_scope) { - TREE_PUBLIC (decl) = storage_class != csc_static; + TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) + | (1 << (int) RID_REGISTER))); TREE_STATIC (decl) = !extern_ref; } /* Not at file scope, only `static' makes a static definition. */ else { - TREE_STATIC (decl) = (storage_class == csc_static); + TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; TREE_PUBLIC (decl) = extern_ref; } - if (threadp) + if (specbits & 1 << (int) RID_THREAD) { if (targetm.have_tls) - DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + DECL_THREAD_LOCAL (decl) = 1; else /* A mere warning is sure to result in improper semantics at runtime. Don't bother to allow this to compile. */ @@ -4863,46 +4505,27 @@ grokdeclarator (const struct c_declarator *declarator, } } - if (storage_class == csc_extern - && variably_modified_type_p (type, NULL_TREE)) - { - /* C99 6.7.5.2p2 */ - error ("object with variably modified type must have no linkage"); - } - /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ - if (storage_class == csc_register) - { - C_DECL_REGISTER (decl) = 1; - DECL_REGISTER (decl) = 1; - } + if (specbits & (1 << (int) RID_REGISTER)) + DECL_REGISTER (decl) = 1; /* Record constancy and volatility. */ c_apply_type_quals_to_decl (type_quals, decl); /* If a type has volatile components, it should be stored in memory. Otherwise, the fact that those components are volatile - will be ignored, and would even crash the compiler. - Of course, this only makes sense on VAR,PARM, and RESULT decl's. */ - if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)) - && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL - || TREE_CODE (decl) == RESULT_DECL)) - { - /* It is not an error for a structure with volatile fields to - be declared register, but reset DECL_REGISTER since it - cannot actually go in a register. */ - int was_reg = C_DECL_REGISTER (decl); - C_DECL_REGISTER (decl) = 0; - DECL_REGISTER (decl) = 0; - c_mark_addressable (decl); - C_DECL_REGISTER (decl) = was_reg; - } + will be ignored, and would even crash the compiler. */ + if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))) + c_mark_addressable (decl); +#ifdef ENABLE_CHECKING /* This is the earliest point at which we might know the assembler name of a variable. Thus, if it's known before this, die horribly. */ - gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)); + if (DECL_ASSEMBLER_NAME_SET_P (decl)) + abort (); +#endif decl_attributes (&decl, returned_attrs, 0); @@ -4911,295 +4534,218 @@ grokdeclarator (const struct c_declarator *declarator, } /* Decode the parameter-list info for a function type or function definition. - The argument is the value returned by `get_parm_info' (or made in c-parse.c + The argument is the value returned by `get_parm_info' (or made in parse.y if there is an identifier list instead of a parameter decl list). These two functions are separate because when a function returns or receives functions then each is called multiple times but the order of calls is different. The last call to `grokparms' is always the one that contains the formal parameter names of a function definition. + Store in `last_function_parms' a chain of the decls of parms. + Also store in `last_function_parm_tags' a chain of the struct, union, + and enum tags declared among the parms. + Return a list of arg types to use in the FUNCTION_TYPE for this function. - FUNCDEF_FLAG is true for a function definition, false for + FUNCDEF_FLAG is nonzero for a function definition, 0 for a mere declaration. A nonempty identifier-list gets an error message - when FUNCDEF_FLAG is false. */ + when FUNCDEF_FLAG is zero. */ static tree -grokparms (struct c_arg_info *arg_info, bool funcdef_flag) +grokparms (tree parms_info, int funcdef_flag) { - tree arg_types = arg_info->types; - - if (funcdef_flag && arg_info->had_vla_unspec) - { - /* A function definition isn't function prototype scope C99 6.2.1p4. */ - /* C99 6.7.5.2p4 */ - error ("%<[*]%> not allowed in other than function prototype scope"); - } + tree first_parm = TREE_CHAIN (parms_info); - if (arg_types == 0 && !funcdef_flag && !in_system_header) - warning (OPT_Wstrict_prototypes, - "function declaration isn%'t a prototype"); + last_function_parms = TREE_PURPOSE (parms_info); + last_function_parm_tags = TREE_VALUE (parms_info); + last_function_parm_others = TREE_TYPE (parms_info); - if (arg_types == error_mark_node) - return 0; /* don't set TYPE_ARG_TYPES in this case */ + if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag + && !in_system_header) + warning ("function declaration isn't a prototype"); - else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE) + if (first_parm != 0 + && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE) { - if (!funcdef_flag) + if (! funcdef_flag) pedwarn ("parameter names (without types) in function declaration"); - arg_info->parms = arg_info->types; - arg_info->types = 0; + last_function_parms = first_parm; return 0; } else { - tree parm, type, typelt; - unsigned int parmno; - - /* If there is a parameter of incomplete type in a definition, - this is an error. In a declaration this is valid, and a - struct or union type may be completed later, before any calls - or definition of the function. In the case where the tag was - first declared within the parameter list, a warning has - already been given. If a parameter has void type, then - however the function cannot be defined or called, so - warn. */ + tree parm; + tree typelt; + /* If the arg types are incomplete in a declaration, + they must include undefined tags. + These tags can never be defined in the scope of the declaration, + so the types can never be completed, + and no call can be compiled successfully. */ - for (parm = arg_info->parms, typelt = arg_types, parmno = 1; + for (parm = last_function_parms, typelt = first_parm; parm; - parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++) - { - type = TREE_VALUE (typelt); - if (type == error_mark_node) - continue; - - if (!COMPLETE_TYPE_P (type)) - { - if (funcdef_flag) - { - if (DECL_NAME (parm)) - error ("parameter %u (%q+D) has incomplete type", - parmno, parm); - else - error ("%Jparameter %u has incomplete type", - parm, parmno); - - TREE_VALUE (typelt) = error_mark_node; - TREE_TYPE (parm) = error_mark_node; - } - else if (VOID_TYPE_P (type)) - { - if (DECL_NAME (parm)) - warning (0, "parameter %u (%q+D) has void type", - parmno, parm); - else - warning (0, "%Jparameter %u has void type", - parm, parmno); - } - } + parm = TREE_CHAIN (parm)) + /* Skip over any enumeration constants declared here. */ + if (TREE_CODE (parm) == PARM_DECL) + { + /* Barf if the parameter itself has an incomplete type. */ + tree type = TREE_VALUE (typelt); + if (type == error_mark_node) + continue; + if (!COMPLETE_TYPE_P (type)) + { + if (funcdef_flag && DECL_NAME (parm) != 0) + error ("parameter `%s' has incomplete type", + IDENTIFIER_POINTER (DECL_NAME (parm))); + else + warning ("parameter has incomplete type"); + if (funcdef_flag) + { + TREE_VALUE (typelt) = error_mark_node; + TREE_TYPE (parm) = error_mark_node; + } + } + typelt = TREE_CHAIN (typelt); + } - if (DECL_NAME (parm) && TREE_USED (parm)) - warn_if_shadowing (parm); - } - return arg_types; + return first_parm; } } -/* Take apart the current scope and return a c_arg_info structure with - info on a parameter list just parsed. - - This structure is later fed to 'grokparms' and 'store_parm_decls'. +/* Return a tree_list node with info on a parameter list just parsed. + The TREE_PURPOSE is a list of decls of those parms. + The TREE_VALUE is a list of structure, union and enum tags defined. + The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE. + The TREE_TYPE is a list of non-parameter decls which appeared with the + parameters. + This tree_list node is later fed to `grokparms'. - ELLIPSIS being true means the argument list ended in '...' so don't - append a sentinel (void_list_node) to the end of the type-list. */ + VOID_AT_END nonzero means append `void' to the end of the type-list. + Zero means the parmlist ended with an ellipsis so don't append `void'. */ -struct c_arg_info * -get_parm_info (bool ellipsis) +tree +get_parm_info (int void_at_end) { - struct c_binding *b = current_scope->bindings; - struct c_arg_info *arg_info = XOBNEW (&parser_obstack, - struct c_arg_info); - tree parms = 0; - tree tags = 0; - tree types = 0; - tree others = 0; - + tree decl, type, list; + tree types = 0; + tree *last_type = &types; + tree tags = current_scope->tags; + tree parms = current_scope->parms; + tree others = current_scope->names; static bool explained_incomplete_types = false; bool gave_void_only_once_err = false; - arg_info->parms = 0; - arg_info->tags = 0; - arg_info->types = 0; - arg_info->others = 0; - arg_info->pending_sizes = 0; - arg_info->had_vla_unspec = current_scope->had_vla_unspec; - - /* The bindings in this scope must not get put into a block. - We will take care of deleting the binding nodes. */ - current_scope->bindings = 0; - - /* This function is only called if there was *something* on the - parameter list. */ - gcc_assert (b); - - /* A parameter list consisting solely of 'void' indicates that the - function takes no arguments. But if the 'void' is qualified - (by 'const' or 'volatile'), or has a storage class specifier - ('register'), then the behavior is undefined; issue an error. - Typedefs for 'void' are OK (see DR#157). */ - if (b->prev == 0 /* one binding */ - && TREE_CODE (b->decl) == PARM_DECL /* which is a parameter */ - && !DECL_NAME (b->decl) /* anonymous */ - && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */ + /* Just "void" (and no ellipsis) is special. There are really no parms. + But if the "void" is qualified (by "const" or "volatile"), or has a + storage class specifier ("register"), then the behavior is undefined; + issue an error. Typedefs for "void" are OK (see DR#157). */ + if (void_at_end && parms != 0 + && TREE_CHAIN (parms) == 0 + && VOID_TYPE_P (TREE_TYPE (parms)) + && !DECL_NAME (parms)) { - if (TREE_THIS_VOLATILE (b->decl) - || TREE_READONLY (b->decl) - || C_DECL_REGISTER (b->decl)) - error ("%<void%> as only parameter may not be qualified"); - - /* There cannot be an ellipsis. */ - if (ellipsis) - error ("%<void%> must be the only parameter"); + if (TREE_THIS_VOLATILE (parms) + || TREE_READONLY (parms) + || DECL_REGISTER (parms)) + error ("\"void\" as only parameter may not be qualified"); - arg_info->types = void_list_node; - return arg_info; + return tree_cons (0, 0, tree_cons (0, void_type_node, 0)); } - if (!ellipsis) - types = void_list_node; - - /* Break up the bindings list into parms, tags, types, and others; - apply sanity checks; purge the name-to-decl bindings. */ - while (b) + /* Sanity check all of the parameter declarations. */ + for (decl = parms; decl; decl = TREE_CHAIN (decl)) { - tree decl = b->decl; - tree type = TREE_TYPE (decl); - const char *keyword; + if (TREE_CODE (decl) != PARM_DECL) + abort (); + if (TREE_ASM_WRITTEN (decl)) + abort (); - switch (TREE_CODE (decl)) - { - case PARM_DECL: - if (b->id) - { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - } + /* Since there is a prototype, args are passed in their + declared types. The back end may override this. */ + type = TREE_TYPE (decl); + DECL_ARG_TYPE (decl) = type; - /* Check for forward decls that never got their actual decl. */ - if (TREE_ASM_WRITTEN (decl)) - error ("parameter %q+D has just a forward declaration", decl); - /* Check for (..., void, ...) and issue an error. */ - else if (VOID_TYPE_P (type) && !DECL_NAME (decl)) - { - if (!gave_void_only_once_err) - { - error ("%<void%> must be the only parameter"); - gave_void_only_once_err = true; - } - } - else - { - /* Valid parameter, add it to the list. */ - TREE_CHAIN (decl) = parms; - parms = decl; - - /* Since there is a prototype, args are passed in their - declared types. The back end may override this later. */ - DECL_ARG_TYPE (decl) = type; - types = tree_cons (0, type, types); - } - break; + /* Check for (..., void, ...) and issue an error. */ + if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err) + { + error ("\"void\" must be the only parameter"); + gave_void_only_once_err = true; + } - case ENUMERAL_TYPE: keyword = "enum"; goto tag; - case UNION_TYPE: keyword = "union"; goto tag; - case RECORD_TYPE: keyword = "struct"; goto tag; - tag: - /* Types may not have tag-names, in which case the type - appears in the bindings list with b->id NULL. */ - if (b->id) - { - gcc_assert (I_TAG_BINDING (b->id) == b); - I_TAG_BINDING (b->id) = b->shadowed; - } + type = build_tree_list (0, type); + *last_type = type; + last_type = &TREE_CHAIN (type); + } - /* Warn about any struct, union or enum tags defined in a - parameter list. The scope of such types is limited to - the parameter list, which is rarely if ever desirable - (it's impossible to call such a function with type- - correct arguments). An anonymous union parm type is - meaningful as a GNU extension, so don't warn for that. */ - if (TREE_CODE (decl) != UNION_TYPE || b->id != 0) - { - if (b->id) - /* The %s will be one of 'struct', 'union', or 'enum'. */ - warning (0, "%<%s %E%> declared inside parameter list", - keyword, b->id); - else - /* The %s will be one of 'struct', 'union', or 'enum'. */ - warning (0, "anonymous %s declared inside parameter list", - keyword); + /* Check the list of non-parameter decls for any forward parm decls + that never got real decls. */ + for (decl = others; decl; decl = TREE_CHAIN (decl)) + if (TREE_CODE (decl) == PARM_DECL) + { + if (!TREE_ASM_WRITTEN (decl)) + abort (); - if (!explained_incomplete_types) - { - warning (0, "its scope is only this definition or declaration," - " which is probably not what you want"); - explained_incomplete_types = true; - } - } + error ("%Jparameter \"%D\" has just a forward declaration", + decl, decl); + } - tags = tree_cons (b->id, decl, tags); - break; + /* Warn about any struct, union or enum tags defined within this + list. The scope of such types is limited to this declaration, + which is rarely if ever desirable (it's impossible to call such + a function with type-correct arguments). */ + for (decl = tags; decl; decl = TREE_CHAIN (decl)) + { + enum tree_code code = TREE_CODE (TREE_VALUE (decl)); + const char *keyword; + /* An anonymous union parm type is meaningful as a GNU extension. + So don't warn for that. */ + if (code == UNION_TYPE && TREE_PURPOSE (decl) == 0 && !pedantic) + continue; - case CONST_DECL: - case TYPE_DECL: - case FUNCTION_DECL: - /* CONST_DECLs appear here when we have an embedded enum, - and TYPE_DECLs appear here when we have an embedded struct - or union. No warnings for this - we already warned about the - type itself. FUNCTION_DECLs appear when there is an implicit - function declaration in the parameter list. */ - - TREE_CHAIN (decl) = others; - others = decl; - /* fall through */ + /* The keyword should not be translated. */ + switch (code) + { + case RECORD_TYPE: keyword = "struct"; break; + case UNION_TYPE: keyword = "union"; break; + case ENUMERAL_TYPE: keyword = "enum"; break; + default: abort (); + } - case ERROR_MARK: - /* error_mark_node appears here when we have an undeclared - variable. Just throw it away. */ - if (b->id) - { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - } - break; + if (TREE_PURPOSE (decl)) + /* The first %s will be one of 'struct', 'union', or 'enum'. */ + warning ("\"%s %s\" declared inside parameter list", + keyword, IDENTIFIER_POINTER (TREE_PURPOSE (decl))); + else + /* The %s will be one of 'struct', 'union', or 'enum'. */ + warning ("anonymous %s declared inside parameter list", keyword); - /* Other things that might be encountered. */ - case LABEL_DECL: - case VAR_DECL: - default: - gcc_unreachable (); + if (! explained_incomplete_types) + { + warning ("its scope is only this definition or declaration," + " which is probably not what you want"); + explained_incomplete_types = true; } + } + - b = free_binding_and_advance (b); + if (void_at_end) + { + type = build_tree_list (0, void_type_node); + *last_type = type; } - arg_info->parms = parms; - arg_info->tags = tags; - arg_info->types = types; - arg_info->others = others; - arg_info->pending_sizes = get_pending_sizes (); - return arg_info; + list = tree_cons (parms, tags, types); + TREE_TYPE (list) = others; + return list; } /* Get the struct, enum or union (CODE says which) with tag NAME. - Define the tag as a forward-reference if it is not defined. - Return a c_typespec structure for the type specifier. */ + Define the tag as a forward-reference if it is not defined. */ -struct c_typespec -parser_xref_tag (enum tree_code code, tree name) +tree +xref_tag (enum tree_code code, tree name) { - struct c_typespec ret; /* If a cross reference is requested, look up the type already defined for this tag and return it. */ @@ -5215,12 +4761,8 @@ parser_xref_tag (enum tree_code code, tree name) this would not work properly if we return the reference found. (For example, with "struct foo" in an outer scope, "union foo;" must shadow that tag with a new one of union type.) */ - ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref); if (ref && TREE_CODE (ref) == code) - { - ret.spec = ref; - return ret; - } + return ref; /* If no such tag is yet defined, create a forward-reference node and record it as the "definition". @@ -5235,7 +4777,7 @@ parser_xref_tag (enum tree_code code, tree name) TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); TYPE_USER_ALIGN (ref) = 0; - TYPE_UNSIGNED (ref) = 1; + TREE_UNSIGNED (ref) = 1; TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node); TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node); TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node); @@ -5243,18 +4785,7 @@ parser_xref_tag (enum tree_code code, tree name) pushtag (name, ref); - ret.spec = ref; - return ret; -} - -/* Get the struct, enum or union (CODE says which) with tag NAME. - Define the tag as a forward-reference if it is not defined. - Return a tree for the type. */ - -tree -xref_tag (enum tree_code code, tree name) -{ - return parser_xref_tag (code, name).spec; + return ref; } /* Make sure that the tag NAME is defined *in the current scope* @@ -5274,18 +4805,20 @@ start_struct (enum tree_code code, tree name) if (ref && TREE_CODE (ref) == code) { if (TYPE_SIZE (ref)) - { + { if (code == UNION_TYPE) - error ("redefinition of %<union %E%>", name); - else - error ("redefinition of %<struct %E%>", name); + error ("redefinition of `union %s'", IDENTIFIER_POINTER (name)); + else + error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name)); } else if (C_TYPE_BEING_DEFINED (ref)) { if (code == UNION_TYPE) - error ("nested redefinition of %<union %E%>", name); - else - error ("nested redefinition of %<struct %E%>", name); + error ("nested redefinition of `union %s'", + IDENTIFIER_POINTER (name)); + else + error ("nested redefinition of `struct %s'", + IDENTIFIER_POINTER (name)); } } else @@ -5301,7 +4834,7 @@ start_struct (enum tree_code code, tree name) return ref; } -/* Process the specs, declarator and width (NULL if omitted) +/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) of a structure component, returning a FIELD_DECL node. WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node. @@ -5310,13 +4843,11 @@ start_struct (enum tree_code code, tree name) are ultimately passed to `build_struct' to make the RECORD_TYPE node. */ tree -grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs, - tree width) +grokfield (tree declarator, tree declspecs, tree width) { tree value; - if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE - && width == NULL_TREE) + if (declarator == NULL_TREE && width == NULL_TREE) { /* This is an unnamed decl. @@ -5337,33 +4868,30 @@ grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs, took this from Plan 9 or if it was an accident of implementation that took root before someone noticed the bug... */ - tree type = declspecs->type; - bool type_ok = (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE); - bool ok = false; + tree type = TREE_VALUE (declspecs); - if (type_ok - && (flag_ms_extensions || !declspecs->typedef_p)) + if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) { if (flag_ms_extensions) - ok = true; + ; /* ok */ else if (flag_iso) - ok = false; + goto warn_unnamed_field; else if (TYPE_NAME (type) == NULL) - ok = true; + ; /* ok */ else - ok = false; + goto warn_unnamed_field; } - if (!ok) + else { - pedwarn ("declaration does not declare anything"); + warn_unnamed_field: + warning ("declaration does not declare anything"); return NULL_TREE; } - if (pedantic) - pedwarn ("ISO C doesn%'t support unnamed structs/unions"); } - value = grokdeclarator (declarator, declspecs, FIELD, false, + value = grokdeclarator (declarator, declspecs, FIELD, 0, width ? &width : NULL); finish_decl (value, NULL_TREE, NULL_TREE); @@ -5403,7 +4931,7 @@ detect_field_duplicates (tree fieldlist) for (y = fieldlist; y != x; y = TREE_CHAIN (y)) if (DECL_NAME (y) == DECL_NAME (x)) { - error ("duplicate member %q+D", x); + error ("%Jduplicate member '%D'", x, x); DECL_NAME (x) = NULL_TREE; } } @@ -5419,7 +4947,7 @@ detect_field_duplicates (tree fieldlist) slot = htab_find_slot (htab, y, INSERT); if (*slot) { - error ("duplicate member %q+D", x); + error ("%Jduplicate member '%D'", x, x); DECL_NAME (x) = NULL_TREE; } *slot = y; @@ -5437,7 +4965,7 @@ tree finish_struct (tree t, tree fieldlist, tree attributes) { tree x; - bool toplevel = file_scope == current_scope; + int toplevel = global_scope == current_scope; int saw_named_field; /* If this type was previously laid out as a forward reference, @@ -5447,6 +4975,19 @@ finish_struct (tree t, tree fieldlist, tree attributes) decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); + /* Nameless union parm types are useful as GCC extension. */ + if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic) + /* Otherwise, warn about any struct or union def. in parmlist. */ + if (in_parm_level_p ()) + { + if (pedantic) + pedwarn ("%s defined inside parms", + TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure")); + else + warning ("%s defined inside parms", + TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure")); + } + if (pedantic) { for (x = fieldlist; x; x = TREE_CHAIN (x)) @@ -5454,41 +4995,21 @@ finish_struct (tree t, tree fieldlist, tree attributes) break; if (x == 0) - { - if (TREE_CODE (t) == UNION_TYPE) - { - if (fieldlist) - pedwarn ("union has no named members"); - else - pedwarn ("union has no members"); - } - else - { - if (fieldlist) - pedwarn ("struct has no named members"); - else - pedwarn ("struct has no members"); - } - } + pedwarn ("%s has no %s", + TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"), + fieldlist ? _("named members") : _("members")); } /* Install struct as DECL_CONTEXT of each field decl. - Also process specified field sizes, found in the DECL_INITIAL, - storing 0 there after the type has been changed to precision equal - to its width, rather than the precision of the specified standard - type. (Correct layout requires the original type to have been preserved - until now.) */ + Also process specified field sizes,m which is found in the DECL_INITIAL. + Store 0 there, except for ": 0" fields (so we can find them + and delete them, below). */ saw_named_field = 0; for (x = fieldlist; x; x = TREE_CHAIN (x)) { - if (TREE_TYPE (x) == error_mark_node) - continue; - DECL_CONTEXT (x) = t; - - if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT) - DECL_PACKED (x) = 1; + DECL_PACKED (x) |= TYPE_PACKED (t); /* If any field is const, the structure type is pseudo-const. */ if (TREE_READONLY (x)) @@ -5521,6 +5042,8 @@ finish_struct (tree t, tree fieldlist, tree attributes) SET_DECL_C_BIT_FIELD (x); } + DECL_INITIAL (x) = 0; + /* Detect flexible array member in an invalid context. */ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE @@ -5537,7 +5060,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) error ("%Jflexible array member not at end of struct", x); TREE_TYPE (x) = error_mark_node; } - else if (!saw_named_field) + else if (! saw_named_field) { error ("%Jflexible array member in otherwise empty struct", x); TREE_TYPE (x) = error_mark_node; @@ -5561,24 +5084,12 @@ finish_struct (tree t, tree fieldlist, tree attributes) layout_type (t); - /* Give bit-fields their proper types. */ + /* Delete all zero-width bit-fields from the fieldlist. */ { tree *fieldlistp = &fieldlist; while (*fieldlistp) - if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp) - && TREE_TYPE (*fieldlistp) != error_mark_node) - { - unsigned HOST_WIDE_INT width - = tree_low_cst (DECL_INITIAL (*fieldlistp), 1); - tree type = TREE_TYPE (*fieldlistp); - if (width != TYPE_PRECISION (type)) - { - TREE_TYPE (*fieldlistp) - = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type)); - DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp)); - } - DECL_INITIAL (*fieldlistp) = 0; - } + if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)) + *fieldlistp = TREE_CHAIN (*fieldlistp); else fieldlistp = &TREE_CHAIN (*fieldlistp); } @@ -5596,46 +5107,45 @@ finish_struct (tree t, tree fieldlist, tree attributes) for (x = fieldlist; x; x = TREE_CHAIN (x)) { - if (len > 15 || DECL_NAME (x) == NULL) - break; - len += 1; + if (len > 15 || DECL_NAME (x) == NULL) + break; + len += 1; } if (len > 15) { - tree *field_array; - struct lang_type *space; - struct sorted_fields_type *space2; + tree *field_array; + struct lang_type *space; + struct sorted_fields_type *space2; - len += list_length (x); + len += list_length (x); - /* Use the same allocation policy here that make_node uses, to - ensure that this lives as long as the rest of the struct decl. - All decls in an inline function need to be saved. */ + /* Use the same allocation policy here that make_node uses, to + ensure that this lives as long as the rest of the struct decl. + All decls in an inline function need to be saved. */ - space = GGC_CNEW (struct lang_type); - space2 = GGC_NEWVAR (struct sorted_fields_type, - sizeof (struct sorted_fields_type) + len * sizeof (tree)); + space = ggc_alloc (sizeof (struct lang_type)); + space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree)); - len = 0; + len = 0; space->s = space2; field_array = &space2->elts[0]; - for (x = fieldlist; x; x = TREE_CHAIN (x)) - { - field_array[len++] = x; - - /* If there is anonymous struct or union, break out of the loop. */ - if (DECL_NAME (x) == NULL) - break; - } - /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ - if (x == NULL) - { - TYPE_LANG_SPECIFIC (t) = space; - TYPE_LANG_SPECIFIC (t)->s->len = len; - field_array = TYPE_LANG_SPECIFIC (t)->s->elts; - qsort (field_array, len, sizeof (tree), field_decl_cmp); - } + for (x = fieldlist; x; x = TREE_CHAIN (x)) + { + field_array[len++] = x; + + /* If there is anonymous struct or union, break out of the loop. */ + if (DECL_NAME (x) == NULL) + break; + } + /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ + if (x == NULL) + { + TYPE_LANG_SPECIFIC (t) = space; + TYPE_LANG_SPECIFIC (t)->s->len = len; + field_array = TYPE_LANG_SPECIFIC (t)->s->elts; + qsort (field_array, len, sizeof (tree), field_decl_cmp); + } } } @@ -5643,6 +5153,8 @@ finish_struct (tree t, tree fieldlist, tree attributes) { TYPE_FIELDS (x) = TYPE_FIELDS (t); TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); + TYPE_ALIGN (x) = TYPE_ALIGN (t); + TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t); C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t); C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t); C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t); @@ -5655,7 +5167,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))) { TYPE_TRANSPARENT_UNION (t) = 0; - warning (0, "union cannot be made transparent"); + warning ("union cannot be made transparent"); } /* If this structure or union completes the type of any previous @@ -5672,8 +5184,8 @@ finish_struct (tree t, tree fieldlist, tree attributes) layout_decl (decl, 0); if (c_dialect_objc ()) objc_check_decl (decl); - rest_of_decl_compilation (decl, toplevel, 0); - if (!toplevel) + rest_of_decl_compilation (decl, NULL, toplevel, 0); + if (! toplevel) expand_decl (decl); } } @@ -5682,12 +5194,6 @@ finish_struct (tree t, tree fieldlist, tree attributes) /* Finish debugging output for this type. */ rest_of_type_compilation (t, toplevel); - /* If we're inside a function proper, i.e. not file-scope and not still - parsing parameters, then arrange for the size of a variable sized type - to be bound now. */ - if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE)) - add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t))); - return t; } @@ -5726,14 +5232,14 @@ start_enum (tree name) } if (C_TYPE_BEING_DEFINED (enumtype)) - error ("nested redefinition of %<enum %E%>", name); + error ("nested redefinition of `enum %s'", IDENTIFIER_POINTER (name)); C_TYPE_BEING_DEFINED (enumtype) = 1; if (TYPE_VALUES (enumtype) != 0) { /* This enum is a named one that has been declared already. */ - error ("redeclaration of %<enum %E%>", name); + error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name)); /* Completely replace its old definition. The old enumerators remain defined, however. */ @@ -5759,10 +5265,12 @@ tree finish_enum (tree enumtype, tree values, tree attributes) { tree pair, tem; - tree minnode = 0, maxnode = 0; + tree minnode = 0, maxnode = 0, enum_value_type; int precision, unsign; - bool toplevel = (file_scope == current_scope); - struct lang_type *lt; + int toplevel = (global_scope == current_scope); + + if (in_parm_level_p ()) + warning ("enum defined inside parms"); decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); @@ -5790,22 +5298,28 @@ finish_enum (tree enumtype, tree values, tree attributes) unsign = (tree_int_cst_sgn (minnode) >= 0); precision = MAX (min_precision (minnode, unsign), min_precision (maxnode, unsign)); - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) { - tem = c_common_type_for_size (precision, unsign); - if (tem == NULL) + tree narrowest = c_common_type_for_size (precision, unsign); + if (narrowest == 0) { - warning (0, "enumeration values exceed range of largest integer"); - tem = long_long_integer_type_node; + warning ("enumeration values exceed range of largest integer"); + narrowest = long_long_integer_type_node; } + + precision = TYPE_PRECISION (narrowest); } else - tem = unsign ? unsigned_type_node : integer_type_node; + precision = TYPE_PRECISION (integer_type_node); - TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem); - TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem); - TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem); + if (precision == TYPE_PRECISION (integer_type_node)) + enum_value_type = c_common_type_for_size (precision, 0); + else + enum_value_type = enumtype; + + TYPE_MIN_VALUE (enumtype) = minnode; + TYPE_MAX_VALUE (enumtype) = maxnode; + TREE_UNSIGNED (enumtype) = unsign; TYPE_SIZE (enumtype) = 0; /* If the precision of the type was specific with an attribute and it @@ -5816,7 +5330,7 @@ finish_enum (tree enumtype, tree values, tree attributes) error ("specified mode too small for enumeral values"); } else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); + TYPE_PRECISION (enumtype) = precision; layout_type (enumtype); @@ -5832,7 +5346,6 @@ finish_enum (tree enumtype, tree values, tree attributes) for (pair = values; pair; pair = TREE_CHAIN (pair)) { tree enu = TREE_PURPOSE (pair); - tree ini = DECL_INITIAL (enu); TREE_TYPE (enu) = enumtype; @@ -5843,27 +5356,18 @@ finish_enum (tree enumtype, tree values, tree attributes) when comparing integers with enumerators that fit in the int range. When -pedantic is given, build_enumerator() would have already taken care of those that don't fit. */ - if (int_fits_type_p (ini, integer_type_node)) - tem = integer_type_node; + if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type)) + DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu)); else - tem = enumtype; - ini = convert (tem, ini); + DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu)); - DECL_INITIAL (enu) = ini; TREE_PURPOSE (pair) = DECL_NAME (enu); - TREE_VALUE (pair) = ini; + TREE_VALUE (pair) = DECL_INITIAL (enu); } TYPE_VALUES (enumtype) = values; } - /* Record the min/max values so that we can warn about bit-field - enumerations that are too small for the values. */ - lt = GGC_CNEW (struct lang_type); - lt->enum_min = minnode; - lt->enum_max = maxnode; - TYPE_LANG_SPECIFIC (enumtype) = lt; - /* Fix up all variant types of this enum type. */ for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem)) { @@ -5878,8 +5382,7 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype); - TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype); - TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype); + TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); } /* Finish debugging output for this type. */ @@ -5900,22 +5403,22 @@ build_enumerator (tree name, tree value) /* Validate and default VALUE. */ + /* Remove no-op casts from the value. */ + if (value) + STRIP_TYPE_NOPS (value); + if (value != 0) { - /* Don't issue more errors for error_mark_node (i.e. an - undeclared identifier) - just ignore the value expression. */ - if (value == error_mark_node) - value = 0; - else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)) - || TREE_CODE (value) != INTEGER_CST) + if (TREE_CODE (value) == INTEGER_CST) { - error ("enumerator value for %qE is not an integer constant", name); - value = 0; + value = default_conversion (value); + constant_expression_warning (value); } else { - value = default_conversion (value); - constant_expression_warning (value); + error ("enumerator value for `%s' not integer constant", + IDENTIFIER_POINTER (name)); + value = 0; } } @@ -5929,11 +5432,9 @@ build_enumerator (tree name, tree value) error ("overflow in enumeration values"); } - if (pedantic && !int_fits_type_p (value, integer_type_node)) + if (pedantic && ! int_fits_type_p (value, integer_type_node)) { - pedwarn ("ISO C restricts enumerator values to range of %<int%>"); - /* XXX This causes -pedantic to change the meaning of the program. - Remove? -zw 2004-03-15 */ + pedwarn ("ISO C restricts enumerator values to range of `int'"); value = convert (integer_type_node, value); } @@ -5948,7 +5449,7 @@ build_enumerator (tree name, tree value) TYPE_PRECISION (integer_type_node)), (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node) - && TYPE_UNSIGNED (type))); + && TREE_UNSIGNED (type))); decl = build_decl (CONST_DECL, name, type); DECL_INITIAL (decl) = convert (type, value); @@ -5971,47 +5472,30 @@ build_enumerator (tree name, tree value) yyparse to report a parse error. */ int -start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, - tree attributes) +start_function (tree declspecs, tree declarator, tree attributes) { tree decl1, old_decl; - tree restype, resdecl; - struct c_label_context_se *nstack_se; - struct c_label_context_vm *nstack_vm; + tree restype; + int old_immediate_size_expand = immediate_size_expand; current_function_returns_value = 0; /* Assume, until we see it does. */ current_function_returns_null = 0; current_function_returns_abnormally = 0; warn_about_return_type = 0; current_extern_inline = 0; - c_switch_stack = NULL; - - nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se); - nstack_se->labels_def = NULL; - nstack_se->labels_used = NULL; - nstack_se->next = label_context_stack_se; - label_context_stack_se = nstack_se; - - nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm); - nstack_vm->labels_def = NULL; - nstack_vm->labels_used = NULL; - nstack_vm->scope = 0; - nstack_vm->next = label_context_stack_vm; - label_context_stack_vm = nstack_vm; + c_in_iteration_stmt = 0; + c_in_case_stmt = 0; - /* Indicate no valid break/continue context by setting these variables - to some non-null, non-label value. We'll notice and emit the proper - error message in c_finish_bc_stmt. */ - c_break_label = c_cont_label = size_zero_node; + /* Don't expand any sizes in the return type of the function. */ + immediate_size_expand = 0; - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL); + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL); /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == 0) { - label_context_stack_se = label_context_stack_se->next; - label_context_stack_vm = label_context_stack_vm->next; + immediate_size_expand = old_immediate_size_expand; return 0; } @@ -6020,8 +5504,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, if (DECL_DECLARED_INLINE_P (decl1) && DECL_UNINLINABLE (decl1) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1))) - warning (OPT_Wattributes, "inline function %q+D given attribute noinline", - decl1); + warning ("%Jinline function '%D' given attribute noinline", decl1, decl1); announce_function (decl1); @@ -6035,105 +5518,63 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, } if (warn_about_return_type) - pedwarn_c99 ("return type defaults to %<int%>"); + pedwarn_c99 ("return type defaults to `int'"); + + /* 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; + current_function_parm_others = last_function_parm_others; /* Make the init_value nonzero so pushdecl knows this is not tentative. - error_mark_node is replaced below (in pop_scope) with the BLOCK. */ + error_mark_node is replaced below (in poplevel) with the BLOCK. */ DECL_INITIAL (decl1) = error_mark_node; /* If this definition isn't a prototype and we had a prototype declaration - before, copy the arg type info from that prototype. */ - old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope); - if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL) - old_decl = 0; - current_function_prototype_locus = UNKNOWN_LOCATION; - current_function_prototype_built_in = false; - current_function_prototype_arg_types = NULL_TREE; - if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) - { - if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE - && comptypes (TREE_TYPE (TREE_TYPE (decl1)), - TREE_TYPE (TREE_TYPE (old_decl)))) - { - TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl), - TREE_TYPE (decl1)); - current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl); - current_function_prototype_built_in - = C_DECL_BUILTIN_PROTOTYPE (old_decl); - current_function_prototype_arg_types - = TYPE_ARG_TYPES (TREE_TYPE (decl1)); - } - if (TREE_PUBLIC (decl1)) - { - /* If there is an external prototype declaration of this - function, record its location but do not copy information - to this decl. This may be an invisible declaration - (built-in or in a scope which has finished) or simply - have more refined argument types than any declaration - found above. */ - struct c_binding *b; - for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed) - if (B_IN_SCOPE (b, external_scope)) - break; - if (b) - { - tree ext_decl, ext_type; - ext_decl = b->decl; - ext_type = b->type ? b->type : TREE_TYPE (ext_decl); - if (TREE_CODE (ext_type) == FUNCTION_TYPE - && comptypes (TREE_TYPE (TREE_TYPE (decl1)), - TREE_TYPE (ext_type))) - { - current_function_prototype_locus - = DECL_SOURCE_LOCATION (ext_decl); - current_function_prototype_built_in - = C_DECL_BUILTIN_PROTOTYPE (ext_decl); - current_function_prototype_arg_types - = TYPE_ARG_TYPES (ext_type); - } - } - } + before, copy the arg type info from that prototype. + But not if what we had before was a builtin function. */ + old_decl = lookup_name_current_level (DECL_NAME (decl1)); + if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE + && !DECL_BUILT_IN (old_decl) + && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) + == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl)))) + && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) + { + TREE_TYPE (decl1) = TREE_TYPE (old_decl); + current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl); } /* Optionally warn of old-fashioned def with no previous prototype. */ if (warn_strict_prototypes - && old_decl != error_mark_node && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 && C_DECL_ISNT_PROTOTYPE (old_decl)) - warning (OPT_Wstrict_prototypes, - "function declaration isn%'t a prototype"); + warning ("function declaration isn't a prototype"); /* Optionally warn of any global def with no previous prototype. */ else if (warn_missing_prototypes - && old_decl != error_mark_node && TREE_PUBLIC (decl1) - && !MAIN_NAME_P (DECL_NAME (decl1)) + && ! MAIN_NAME_P (DECL_NAME (decl1)) && C_DECL_ISNT_PROTOTYPE (old_decl)) - warning (OPT_Wmissing_prototypes, "no previous prototype for %q+D", decl1); + warning ("%Jno previous prototype for '%D'", decl1, decl1); /* Optionally warn of any def with no previous prototype if the function has already been used. */ else if (warn_missing_prototypes - && old_decl != 0 - && old_decl != error_mark_node - && TREE_USED (old_decl) + && old_decl != 0 && TREE_USED (old_decl) && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0) - warning (OPT_Wmissing_prototypes, - "%q+D was used with no prototype before its definition", decl1); + warning ("%J'%D' was used with no prototype before its definition", + decl1, decl1); /* Optionally warn of any global def with no previous declaration. */ else if (warn_missing_declarations && TREE_PUBLIC (decl1) && old_decl == 0 - && !MAIN_NAME_P (DECL_NAME (decl1))) - warning (OPT_Wmissing_declarations, "no previous declaration for %q+D", - decl1); + && ! MAIN_NAME_P (DECL_NAME (decl1))) + warning ("%Jno previous declaration for '%D'", decl1, decl1); /* Optionally warn of any def with no previous declaration if the function has already been used. */ else if (warn_missing_declarations - && old_decl != 0 - && old_decl != error_mark_node - && TREE_USED (old_decl) + && old_decl != 0 && TREE_USED (old_decl) && C_DECL_IMPLICIT (old_decl)) - warning (OPT_Wmissing_declarations, - "%q+D was used with no declaration before its definition", decl1); + warning ("%J`%D' was used with no declaration before its definition", + decl1, decl1); /* This is a definition, not a reference. So normally clear DECL_EXTERNAL. @@ -6141,30 +5582,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, except for defining how to inline. So set DECL_EXTERNAL in that case. */ DECL_EXTERNAL (decl1) = current_extern_inline; - /* C99 specified different behaviour for non-static inline - functions, compared with the traditional GNU behaviour. We don't - support the C99 behaviour, but we do warn about non-static inline - functions here. The warning can be disabled via an explicit use - of -fgnu89-inline, or by using the gnu_inline attribute. */ - if (DECL_DECLARED_INLINE_P (decl1) - && TREE_PUBLIC (decl1) - && flag_isoc99 - && flag_gnu89_inline != 1 - && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)) - && diagnostic_report_warnings_p ()) - { - static bool info = false; - - warning (0, "C99 inline functions are not supported; using GNU89"); - if (!info) - { - warning (0, - "to disable this warning use -fgnu89-inline or " - "the gnu_inline function attribute"); - info = true; - } - } - /* This function exists in static storage. (This does not mean `static' in the C sense!) */ TREE_STATIC (decl1) = 1; @@ -6173,12 +5590,15 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, if (current_function_decl != 0) TREE_PUBLIC (decl1) = 0; +#ifdef ENABLE_CHECKING /* This is the earliest point at which we might know the assembler name of the function. Thus, if it's set before this, die horribly. */ - gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1)); + if (DECL_ASSEMBLER_NAME_SET_P (decl1)) + abort (); +#endif /* If #pragma weak was used, mark the decl weak now. */ - if (current_scope == file_scope) + if (current_scope == global_scope) maybe_apply_pragma_weak (decl1); /* Warn for unlikely, improbable, or stupid declarations of `main'. */ @@ -6189,7 +5609,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) != integer_type_node) - pedwarn ("return type of %q+D is not %<int%>", decl1); + pedwarn ("%Jreturn type of '%D' is not `int'", decl1, decl1); for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; args = TREE_CHAIN (args)) @@ -6204,7 +5624,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, { case 1: if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn ("first argument of %q+D should be %<int%>", decl1); + pedwarn ("%Jfirst argument of '%D' should be `int'", + decl1, decl1); break; case 2: @@ -6212,8 +5633,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn ("second argument of %q+D should be %<char **%>", - decl1); + pedwarn ("%Jsecond argument of '%D' should be 'char **'", + decl1, decl1); break; case 3: @@ -6221,8 +5642,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn ("third argument of %q+D should probably be " - "%<char **%>", decl1); + pedwarn ("%Jthird argument of '%D' should probably be " + "'char **'", decl1, decl1); break; } } @@ -6231,10 +5652,10 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, argument because it's only mentioned in an appendix of the standard. */ if (argct > 0 && (argct < 2 || argct > 3)) - pedwarn ("%q+D takes only zero or two arguments", decl1); + pedwarn ("%J'%D' takes only zero or two arguments", decl1, decl1); - if (!TREE_PUBLIC (decl1)) - pedwarn ("%q+D is normally a non-static function", decl1); + if (! TREE_PUBLIC (decl1)) + pedwarn ("%J'%D' is normally a non-static function", decl1, decl1); } /* Record the decl so that the function name is defined. @@ -6243,26 +5664,32 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, current_function_decl = pushdecl (decl1); - push_scope (); + pushlevel (0); declare_parm_level (); + make_decl_rtl (current_function_decl, NULL); + restype = TREE_TYPE (TREE_TYPE (current_function_decl)); /* Promote the value to int before returning it. */ if (c_promoting_integer_type_p (restype)) { /* It retains unsignedness if not really getting wider. */ - if (TYPE_UNSIGNED (restype) + if (TREE_UNSIGNED (restype) && (TYPE_PRECISION (restype) == TYPE_PRECISION (integer_type_node))) restype = unsigned_type_node; else restype = integer_type_node; } + DECL_RESULT (current_function_decl) + = build_decl (RESULT_DECL, NULL_TREE, restype); - resdecl = build_decl (RESULT_DECL, NULL_TREE, restype); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_RESULT (current_function_decl) = resdecl; + /* If this fcn was already referenced via a block-scope `extern' decl + (or an implicit decl), propagate certain information about the usage. */ + if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl))) + TREE_ADDRESSABLE (current_function_decl) = 1; + + immediate_size_expand = old_immediate_size_expand; start_fname_decls (); @@ -6274,78 +5701,98 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, need only record them as in effect and complain if any redundant old-style parm decls were written. */ static void -store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info) +store_parm_decls_newstyle (void) { - tree decl; + tree decl, last; + tree fndecl = current_function_decl; + tree parms = current_function_parms; + tree tags = current_function_parm_tags; + tree others = current_function_parm_others; - if (current_scope->bindings) + if (current_scope->parms || current_scope->names || current_scope->tags) { error ("%Jold-style parameter declarations in prototyped " "function definition", fndecl); /* Get rid of the old-style declarations. */ - pop_scope (); - push_scope (); - } - /* Don't issue this warning for nested functions, and don't issue this - warning if we got here because ARG_INFO_TYPES was error_mark_node - (this happens when a function definition has just an ellipsis in - its parameter list). */ - else if (!in_system_header && !current_function_scope - && arg_info->types != error_mark_node) - warning (OPT_Wtraditional, - "%Jtraditional C rejects ISO C style function definitions", - fndecl); + poplevel (0, 0, 0); + pushlevel (0); + } /* Now make all the parameter declarations visible in the function body. We can bypass most of the grunt work of pushdecl. */ - for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl)) + for (last = 0, decl = parms; decl; last = decl, decl = TREE_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; - if (DECL_NAME (decl)) + if (DECL_NAME (decl) == 0) + error ("%Jparameter name omitted", decl); + else { - bind (DECL_NAME (decl), decl, current_scope, - /*invisible=*/false, /*nested=*/false); - if (!TREE_USED (decl)) - warn_if_shadowing (decl); + if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl))) + current_scope->shadowed + = tree_cons (DECL_NAME (decl), + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)), + current_scope->shadowed); + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl; } - else - error ("%Jparameter name omitted", decl); } + current_scope->parms = parms; + current_scope->parms_last = last; /* Record the parameter list in the function declaration. */ - DECL_ARGUMENTS (fndecl) = arg_info->parms; + DECL_ARGUMENTS (fndecl) = parms; /* Now make all the ancillary declarations visible, likewise. */ - for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl)) + for (last = 0, decl = others; decl; last = decl, decl = TREE_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; - if (DECL_NAME (decl)) - bind (DECL_NAME (decl), decl, current_scope, - /*invisible=*/false, /*nested=*/false); + if (DECL_NAME (decl) + && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node) + { + if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl))) + current_scope->shadowed + = tree_cons (DECL_NAME (decl), + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)), + current_scope->shadowed); + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl; + } } + current_scope->names = others; + current_scope->names_last = last; /* And all the tag declarations. */ - for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl)) + for (decl = tags; decl; decl = TREE_CHAIN (decl)) if (TREE_PURPOSE (decl)) - bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope, - /*invisible=*/false, /*nested=*/false); + { + if (IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl))) + current_scope->shadowed_tags + = tree_cons (TREE_PURPOSE (decl), + IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (decl)), + current_scope->shadowed_tags); + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)) = TREE_VALUE (decl); + } + current_scope->tags = tags; } /* Subroutine of store_parm_decls which handles old-style function definitions (separate parameter list and declarations). */ static void -store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) +store_parm_decls_oldstyle (void) { - struct c_binding *b; tree parm, decl, last; - tree parmids = arg_info->parms; - struct pointer_set_t *seen_args = pointer_set_create (); + tree fndecl = current_function_decl; + + /* This is the identifier list from the function declarator. */ + tree parmids = current_function_parms; - if (!in_system_header) - warning (OPT_Wold_style_definition, "%Jold-style function definition", - fndecl); + /* We use DECL_WEAK as a flag to show which parameters have been + seen already, since it is not used on PARM_DECL. */ +#ifdef ENABLE_CHECKING + for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm)) + if (DECL_WEAK (parm)) + abort (); +#endif /* Match each formal parameter name with its declaration. Save each decl in the appropriate TREE_PURPOSE slot of the parmids chain. */ @@ -6358,18 +5805,17 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) continue; } - b = I_SYMBOL_BINDING (TREE_VALUE (parm)); - if (b && B_IN_CURRENT_SCOPE (b)) + decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm)); + if (decl && DECL_CONTEXT (decl) == fndecl) { - decl = b->decl; /* If we got something other than a PARM_DECL it is an error. */ if (TREE_CODE (decl) != PARM_DECL) - error ("%q+D declared as a non-parameter", decl); + error ("%J\"%D\" declared as a non-parameter", decl, decl); /* If the declaration is already marked, we have a duplicate name. Complain and ignore the duplicate. */ - else if (pointer_set_contains (seen_args, decl)) + else if (DECL_WEAK (decl)) { - error ("multiple parameters named %q+D", decl); + error ("%Jmultiple parameters named \"%D\"", decl, decl); TREE_PURPOSE (parm) = 0; continue; } @@ -6377,12 +5823,11 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) an int. */ else if (VOID_TYPE_P (TREE_TYPE (decl))) { - error ("parameter %q+D declared with void type", decl); + error ("%Jparameter \"%D\" declared void", decl, decl); TREE_TYPE (decl) = integer_type_node; DECL_ARG_TYPE (decl) = integer_type_node; layout_decl (decl, 0); } - warn_if_shadowing (decl); } /* If no declaration found, default to int. */ else @@ -6391,37 +5836,32 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) DECL_ARG_TYPE (decl) = TREE_TYPE (decl); DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (fndecl); pushdecl (decl); - warn_if_shadowing (decl); if (flag_isoc99) - pedwarn ("type of %q+D defaults to %<int%>", decl); + pedwarn ("%Jtype of \"%D\" defaults to \"int\"", decl, decl); else if (extra_warnings) - warning (OPT_Wextra, "type of %q+D defaults to %<int%>", decl); + warning ("%Jtype of \"%D\" defaults to \"int\"", decl, decl); } TREE_PURPOSE (parm) = decl; - pointer_set_insert (seen_args, decl); + DECL_WEAK (decl) = 1; } /* Now examine the parms chain for incomplete declarations and declarations with no corresponding names. */ - for (b = current_scope->bindings; b; b = b->prev) + for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm)) { - parm = b->decl; - if (TREE_CODE (parm) != PARM_DECL) - continue; - - if (TREE_TYPE (parm) != error_mark_node - && !COMPLETE_TYPE_P (TREE_TYPE (parm))) + if (!COMPLETE_TYPE_P (TREE_TYPE (parm))) { - error ("parameter %q+D has incomplete type", parm); + error ("%Jparameter \"%D\" has incomplete type", parm, parm); TREE_TYPE (parm) = error_mark_node; } - if (!pointer_set_contains (seen_args, parm)) + if (! DECL_WEAK (parm)) { - error ("declaration for parameter %q+D but no such parameter", parm); + error ("%Jdeclaration for parameter \"%D\" but no such parameter", + parm, parm); /* Pretend the parameter was not missing. This gets us to a standard state and minimizes @@ -6442,27 +5882,29 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) { last = TREE_PURPOSE (parm); DECL_ARGUMENTS (fndecl) = last; + current_scope->parms = last; + DECL_WEAK (last) = 0; for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm)) if (TREE_PURPOSE (parm)) { TREE_CHAIN (last) = TREE_PURPOSE (parm); last = TREE_PURPOSE (parm); + DECL_WEAK (last) = 0; } + current_scope->parms_last = last; TREE_CHAIN (last) = 0; } - pointer_set_destroy (seen_args); - /* If there was a previous prototype, set the DECL_ARG_TYPE of each argument according to the type previously specified, and report any mismatches. */ - if (current_function_prototype_arg_types) + if (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) { tree type; for (parm = DECL_ARGUMENTS (fndecl), - type = current_function_prototype_arg_types; + type = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node)); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) @@ -6470,22 +5912,17 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) if (parm == 0 || type == 0 || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { - if (current_function_prototype_built_in) - warning (0, "number of arguments doesn%'t match " - "built-in prototype"); - else - { - error ("number of arguments doesn%'t match prototype"); - error ("%Hprototype declaration", - ¤t_function_prototype_locus); - } + error ("number of arguments doesn't match prototype"); + error ("%Hprototype declaration", + ¤t_function_prototype_locus); break; } /* Type for passing arg must be consistent with that declared for the arg. ISO C says we take the unqualified type for parameters declared with qualified type. */ - if (!comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)), - TYPE_MAIN_VARIANT (TREE_VALUE (type)))) + if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)), + TYPE_MAIN_VARIANT (TREE_VALUE (type)), + COMPARE_STRICT)) { if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == TYPE_MAIN_VARIANT (TREE_VALUE (type))) @@ -6505,33 +5942,17 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) if (pedantic) { - /* ??? Is it possible to get here with a - built-in prototype or will it always have - been diagnosed as conflicting with an - old-style definition and discarded? */ - if (current_function_prototype_built_in) - warning (0, "promoted argument %qD " - "doesn%'t match built-in prototype", parm); - else - { - pedwarn ("promoted argument %qD " - "doesn%'t match prototype", parm); - pedwarn ("%Hprototype declaration", - ¤t_function_prototype_locus); - } + pedwarn ("promoted argument \"%D\" " + "doesn't match prototype", parm); + pedwarn ("%Hprototype declaration", + ¤t_function_prototype_locus); } } else { - if (current_function_prototype_built_in) - warning (0, "argument %qD doesn%'t match " - "built-in prototype", parm); - else - { - error ("argument %qD doesn%'t match prototype", parm); - error ("%Hprototype declaration", - ¤t_function_prototype_locus); - } + error ("argument \"%D\" doesn't match prototype", parm); + error ("%Hprototype declaration", + ¤t_function_prototype_locus); } } } @@ -6567,22 +5988,12 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) will be a variant of the main variant of the original function type. */ - TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl)); + TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl)); TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual; } } -/* Store parameter declarations passed in ARG_INFO into the current - function declaration. */ - -void -store_parm_decls_from (struct c_arg_info *arg_info) -{ - current_function_arg_info = arg_info; - store_parm_decls (); -} - /* Store the parameter declarations into the current function declaration. This is called after parsing the parameter declarations, before digesting the body of the function. @@ -6594,79 +6005,46 @@ void store_parm_decls (void) { tree fndecl = current_function_decl; - bool proto; - - /* The argument information block for FNDECL. */ - struct c_arg_info *arg_info = current_function_arg_info; - current_function_arg_info = 0; - /* True if this definition is written with a prototype. Note: - despite C99 6.7.5.3p14, we can *not* treat an empty argument - list in a function definition as equivalent to (void) -- an - empty argument list specifies the function has no parameters, - but only (void) sets up a prototype for future calls. */ - proto = arg_info->types != 0; + /* True if this definition is written with a prototype. */ + bool prototype = (current_function_parms + && TREE_CODE (current_function_parms) != TREE_LIST); - if (proto) - store_parm_decls_newstyle (fndecl, arg_info); + if (prototype) + store_parm_decls_newstyle (); else - store_parm_decls_oldstyle (fndecl, arg_info); + store_parm_decls_oldstyle (); - /* The next call to push_scope will be a function body. */ + /* The next call to pushlevel will be a function body. */ next_is_function_body = true; /* Write a record describing this function definition to the prototypes file (if requested). */ - gen_aux_info_record (fndecl, 1, 0, proto); + gen_aux_info_record (fndecl, 1, 0, prototype); /* Initialize the RTL code for the function. */ allocate_struct_function (fndecl); /* Begin the statement tree for this function. */ - DECL_SAVED_TREE (fndecl) = push_stmt_list (); - - /* ??? Insert the contents of the pending sizes list into the function - to be evaluated. The only reason left to have this is - void foo(int n, int array[n++]) - because we throw away the array type in favor of a pointer type, and - thus won't naturally see the SAVE_EXPR containing the increment. All - other pending sizes would be handled by gimplify_parameters. */ - { - tree t; - for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t)) - add_stmt (TREE_VALUE (t)); - } + begin_stmt_tree (&DECL_SAVED_TREE (fndecl)); + + /* Save away the sizes of any variable-size types so that we can + expand them when generating RTL. */ + DECL_LANG_SPECIFIC (fndecl)->pending_sizes = get_pending_sizes (); + + /* This function is being processed in whole-function mode. */ + cfun->x_whole_function_mode_p = 1; /* Even though we're inside a function body, we still don't want to call expand_expr to calculate the size of a variable-sized array. We haven't necessarily assigned RTL to all variables yet, so it's not safe to try to expand expressions involving them. */ + immediate_size_expand = 0; cfun->x_dont_save_pending_sizes_p = 1; } -/* Emit diagnostics that require gimple input for detection. Operate on - FNDECL and all its nested functions. */ - -static void -c_gimple_diagnostics_recursively (tree fndecl) -{ - struct cgraph_node *cgn; - - /* Handle attribute((warn_unused_result)). Relies on gimple input. */ - c_warn_unused_result (&DECL_SAVED_TREE (fndecl)); - - /* Notice when OpenMP structured block constraints are violated. */ - if (flag_openmp) - diagnose_omp_structured_block_errors (fndecl); - - /* Finalize all nested functions now. */ - cgn = cgraph_node (fndecl); - for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) - c_gimple_diagnostics_recursively (cgn->decl); -} - /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage for the function definition. @@ -6678,20 +6056,33 @@ finish_function (void) { tree fndecl = current_function_decl; - label_context_stack_se = label_context_stack_se->next; - label_context_stack_vm = label_context_stack_vm->next; + /* When a function declaration is totally empty, e.g. + void foo(void) { } + (the argument list is irrelevant) the compstmt rule will not + bother calling pushlevel/poplevel, which means we get here with + the scope stack out of sync. Detect this situation by noticing + that current_scope is still as store_parm_decls left it, and do + a dummy push/pop to get back to consistency. + Note that the call to pushlevel does not actually push another + scope - see there for details. */ + + if (current_scope->parm_flag && next_is_function_body) + { + pushlevel (0); + poplevel (0, 0, 0); + } if (TREE_CODE (fndecl) == FUNCTION_DECL && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))) { tree args = DECL_ARGUMENTS (fndecl); for (; args; args = TREE_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = integer_type_node; - } + { + tree type = TREE_TYPE (args); + if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (args) = integer_type_node; + } } if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) @@ -6710,41 +6101,30 @@ finish_function (void) /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned. If warn_main is -1 (-Wno-main) we don't want to be warned. */ if (!warn_main) - pedwarn ("return type of %q+D is not %<int%>", fndecl); + pedwarn ("%Jreturn type of '%D' is not `int'", fndecl, fndecl); } else { - if (flag_isoc99) - { - tree stmt = c_finish_return (integer_zero_node); -#ifdef USE_MAPPED_LOCATION - /* Hack. We don't want the middle-end to warn that this return - is unreachable, so we mark its location as special. Using - UNKNOWN_LOCATION has the problem that it gets clobbered in - annotate_one_with_locus. A cleaner solution might be to - ensure ! should_carry_locus_p (stmt), but that needs a flag. - */ - SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION); +#ifdef DEFAULT_MAIN_RETURN + /* Make it so that `main' always returns success by default. */ + DEFAULT_MAIN_RETURN; #else - /* Hack. We don't want the middle-end to warn that this - return is unreachable, so put the statement on the - special line 0. */ - annotate_with_file_line (stmt, input_filename, 0); + if (flag_isoc99) + c_expand_return (integer_zero_node); #endif - } } } - /* Tie off the statement tree for this function. */ - DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); - finish_fname_decls (); + /* Tie off the statement tree for this function. */ + finish_stmt_tree (&DECL_SAVED_TREE (fndecl)); + /* Complain if there's just no return statement. */ if (warn_return_type && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE && !current_function_returns_value && !current_function_returns_null - /* Don't complain if we are no-return. */ + /* Don't complain if we abort. */ && !current_function_returns_abnormally /* Don't warn for main(). */ && !MAIN_NAME_P (DECL_NAME (fndecl)) @@ -6753,116 +6133,111 @@ finish_function (void) /* Normally, with -Wreturn-type, flow will complain. Unless we're an inline function, as we might never be compiled separately. */ && DECL_INLINE (fndecl)) - { - warning (OPT_Wreturn_type, - "no return statement in function returning non-void"); - TREE_NO_WARNING (fndecl) = 1; - } + warning ("no return statement in function returning non-void"); /* With just -Wextra, complain only if function returns both with and without a value. */ if (extra_warnings && current_function_returns_value && current_function_returns_null) - warning (OPT_Wextra, "this function may return with or without a value"); - - /* Store the end of the function, so that we get good line number - info for the epilogue. */ - cfun->function_end_locus = input_location; + warning ("this function may return with or without a value"); - /* If we don't have ctors/dtors sections, and this is a static - constructor or destructor, it must be recorded now. */ - if (DECL_STATIC_CONSTRUCTOR (fndecl) - && !targetm.have_ctors_dtors) - static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); - if (DECL_STATIC_DESTRUCTOR (fndecl) - && !targetm.have_ctors_dtors) - static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); + /* We're leaving the context of this function, so zap cfun. It's still in + DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */ + cfun = NULL; - /* Finalize the ELF visibility for the function. */ - c_determine_visibility (fndecl); + /* ??? Objc emits functions after finalizing the compilation unit. + This should be cleaned up later and this conditional removed. */ + if (!cgraph_global_info_ready) + cgraph_finalize_function (fndecl, false); + else + c_expand_body (fndecl); + current_function_decl = NULL; +} - /* Genericize before inlining. Delay genericizing nested functions - until their parent function is genericized. Since finalizing - requires GENERIC, delay that as well. */ +/* Generate the RTL for a deferred function FNDECL. */ - if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node - && !undef_nested_function) +void +c_expand_deferred_function (tree fndecl) +{ + /* DECL_INLINE or DECL_RESULT might got cleared after the inline + function was deferred, e.g. in duplicate_decls. */ + if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl)) { - if (!decl_function_context (fndecl)) + if (flag_inline_trees) { - c_genericize (fndecl); - c_gimple_diagnostics_recursively (fndecl); + timevar_push (TV_INTEGRATION); + optimize_inline_calls (fndecl); + timevar_pop (TV_INTEGRATION); + } + c_expand_body (fndecl); + current_function_decl = NULL; + } +} - /* ??? Objc emits functions after finalizing the compilation unit. - This should be cleaned up later and this conditional removed. */ - if (cgraph_global_info_ready) - { - c_expand_body (fndecl); - return; - } +/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero, + then we are already in the process of generating RTL for another + function. */ - cgraph_finalize_function (fndecl, false); - } +static void +c_expand_body_1 (tree fndecl, int nested_p) +{ + if (nested_p) + /* Squirrel away our current state. */ + push_function_context (); + + /* Make sure that we will evaluate variable-sized types involved + in our function's type. */ + put_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes); + tree_rest_of_compilation (fndecl, nested_p); + + if (nested_p) + /* Return to the enclosing function. */ + pop_function_context (); + + if (DECL_STATIC_CONSTRUCTOR (fndecl)) + { + if (targetm.have_ctors_dtors) + (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0), + DEFAULT_INIT_PRIORITY); else - { - /* Register this function with cgraph just far enough to get it - added to our parent's nested function list. Handy, since the - C front end doesn't have such a list. */ - (void) cgraph_node (fndecl); - } + static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); } - if (!decl_function_context (fndecl)) - undef_nested_function = false; - - /* We're leaving the context of this function, so zap cfun. - It's still in DECL_STRUCT_FUNCTION, and we'll restore it in - tree_rest_of_compilation. */ - cfun = NULL; - current_function_decl = NULL; + if (DECL_STATIC_DESTRUCTOR (fndecl)) + { + if (targetm.have_ctors_dtors) + (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0), + DEFAULT_INIT_PRIORITY); + else + static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); + } } -/* Generate the RTL for the body of FNDECL. */ +/* Like c_expand_body_1 but only for unnested functions. */ void c_expand_body (tree fndecl) { - if (!DECL_INITIAL (fndecl) - || DECL_INITIAL (fndecl) == error_mark_node) - return; - - tree_rest_of_compilation (fndecl); - - if (DECL_STATIC_CONSTRUCTOR (fndecl) - && targetm.have_ctors_dtors) - targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0), - DEFAULT_INIT_PRIORITY); - if (DECL_STATIC_DESTRUCTOR (fndecl) - && targetm.have_ctors_dtors) - targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0), - DEFAULT_INIT_PRIORITY); + if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) + c_expand_body_1 (fndecl, 0); } /* Check the declarations given in a for-loop for satisfying the C99 - constraints. If exactly one such decl is found, return it. */ - -tree + constraints. */ +void check_for_loop_decls (void) { - struct c_binding *b; - tree one_decl = NULL_TREE; - int n_decls = 0; - + tree t; if (!flag_isoc99) { /* If we get here, declarations have been used in a for loop without the C99 for loop scope. This doesn't make much sense, so don't allow it. */ - error ("%<for%> loop initial declaration used outside C99 mode"); - return NULL_TREE; + error ("'for' loop initial declaration used outside C99 mode"); + return; } /* C99 subclause 6.8.5 paragraph 3: @@ -6878,47 +6253,36 @@ check_for_loop_decls (void) interpretation, to avoid creating an extension which later causes problems. */ - for (b = current_scope->bindings; b; b = b->prev) + for (t = current_scope->tags; t; t = TREE_CHAIN (t)) { - tree id = b->id; - tree decl = b->decl; + if (TREE_PURPOSE (t) != 0) + { + enum tree_code code = TREE_CODE (TREE_VALUE (t)); - if (!id) - continue; - - switch (TREE_CODE (decl)) - { - case VAR_DECL: - if (TREE_STATIC (decl)) - error ("declaration of static variable %q+D in %<for%> loop " - "initial declaration", decl); - else if (DECL_EXTERNAL (decl)) - error ("declaration of %<extern%> variable %q+D in %<for%> loop " - "initial declaration", decl); - break; - - case RECORD_TYPE: - error ("%<struct %E%> declared in %<for%> loop initial declaration", - id); - break; - case UNION_TYPE: - error ("%<union %E%> declared in %<for%> loop initial declaration", - id); - break; - case ENUMERAL_TYPE: - error ("%<enum %E%> declared in %<for%> loop initial declaration", - id); - break; - default: - error ("declaration of non-variable %q+D in %<for%> loop " - "initial declaration", decl); - } - - n_decls++; - one_decl = decl; + if (code == RECORD_TYPE) + error ("'struct %s' declared in 'for' loop initial declaration", + IDENTIFIER_POINTER (TREE_PURPOSE (t))); + else if (code == UNION_TYPE) + error ("'union %s' declared in 'for' loop initial declaration", + IDENTIFIER_POINTER (TREE_PURPOSE (t))); + else + error ("'enum %s' declared in 'for' loop initial declaration", + IDENTIFIER_POINTER (TREE_PURPOSE (t))); + } } - return n_decls == 1 ? one_decl : NULL_TREE; + for (t = getdecls (); t; t = TREE_CHAIN (t)) + { + if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t)) + error ("%Jdeclaration of non-variable '%D' in 'for' loop " + "initial declaration", t, t); + else if (TREE_STATIC (t)) + error ("%Jdeclaration of static variable '%D' in 'for' loop " + "initial declaration", t, t); + else if (DECL_EXTERNAL (t)) + error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop " + "initial declaration", t, t); + } } /* Save and reinitialize the variables @@ -6928,14 +6292,13 @@ void c_push_function_context (struct function *f) { struct language_function *p; - p = GGC_NEW (struct language_function); + p = ggc_alloc (sizeof (struct language_function)); f->language = p; p->base.x_stmt_tree = c_stmt_tree; - p->x_break_label = c_break_label; - p->x_cont_label = c_cont_label; - p->x_switch_stack = c_switch_stack; - p->arg_info = current_function_arg_info; + p->base.x_scope_stmt_stack = c_scope_stmt_stack; + p->x_in_iteration_stmt = c_in_iteration_stmt; + p->x_in_case_stmt = c_in_case_stmt; p->returns_value = current_function_returns_value; p->returns_null = current_function_returns_null; p->returns_abnormally = current_function_returns_abnormally; @@ -6950,7 +6313,7 @@ c_pop_function_context (struct function *f) { struct language_function *p = f->language; - if (DECL_STRUCT_FUNCTION (current_function_decl) == 0 + if (DECL_SAVED_INSNS (current_function_decl) == 0 && DECL_SAVED_TREE (current_function_decl) == NULL_TREE) { /* Stop pointing to the local nodes about to be freed. */ @@ -6961,10 +6324,9 @@ c_pop_function_context (struct function *f) } c_stmt_tree = p->base.x_stmt_tree; - c_break_label = p->x_break_label; - c_cont_label = p->x_cont_label; - c_switch_stack = p->x_switch_stack; - current_function_arg_info = p->arg_info; + c_scope_stmt_stack = p->base.x_scope_stmt_stack; + c_in_iteration_stmt = p->x_in_iteration_stmt; + c_in_case_stmt = p->x_in_case_stmt; current_function_returns_value = p->returns_value; current_function_returns_null = p->returns_null; current_function_returns_abnormally = p->returns_abnormally; @@ -6984,7 +6346,7 @@ c_dup_lang_specific_decl (tree decl) if (!DECL_LANG_SPECIFIC (decl)) return; - ld = GGC_NEW (struct lang_decl); + ld = ggc_alloc (sizeof (struct lang_decl)); memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl)); DECL_LANG_SPECIFIC (decl) = ld; } @@ -6994,6 +6356,16 @@ c_dup_lang_specific_decl (tree decl) functions are not called from anywhere in the C front end, but as these changes continue, that will change. */ +/* Returns nonzero if the current statement is a full expression, + i.e. temporaries created during that statement should be destroyed + at the end of the statement. */ + +int +stmts_are_full_exprs_p (void) +{ + return 0; +} + /* Returns the stmt_tree (if any) to which statements are currently being added. If there is no active statement-tree, NULL is returned. */ @@ -7004,26 +6376,74 @@ current_stmt_tree (void) return &c_stmt_tree; } +/* Returns the stack of SCOPE_STMTs for the current function. */ + +tree * +current_scope_stmt_stack (void) +{ + return &c_scope_stmt_stack; +} + /* Nonzero if TYPE is an anonymous union or struct type. Always 0 in C. */ int -anon_aggr_type_p (tree ARG_UNUSED (node)) +anon_aggr_type_p (tree node ATTRIBUTE_UNUSED) { return 0; } +/* Dummy function in place of callback used by C++. */ + +void +extract_interface_info (void) +{ +} + +/* Return a new COMPOUND_STMT, after adding it to the current + statement tree. */ + +tree +c_begin_compound_stmt (void) +{ + tree stmt; + + /* Create the COMPOUND_STMT. */ + stmt = add_stmt (build_stmt (COMPOUND_STMT, error_mark_node)); + + return stmt; +} + +/* Expand T (a DECL_STMT) if it declares an entity not handled by the + common code. */ + +void +c_expand_decl_stmt (tree t) +{ + tree decl = DECL_STMT_DECL (t); + + /* Expand nested functions. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_CONTEXT (decl) == current_function_decl + && DECL_SAVED_TREE (decl)) + c_expand_body_1 (decl, 1); +} + /* Return the global value of T as a symbol. */ tree identifier_global_value (tree t) { - struct c_binding *b; + tree decl = IDENTIFIER_SYMBOL_VALUE (t); + if (decl == 0 || DECL_FILE_SCOPE_P (decl)) + return decl; - for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed) - if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b)) - return b->decl; + /* Shadowed by something else; find the true global value. */ + for (decl = global_scope->names; decl; decl = TREE_CHAIN (decl)) + if (DECL_NAME (decl) == t) + return decl; + /* Only local values for this decl. */ return 0; } @@ -7033,15 +6453,12 @@ identifier_global_value (tree t) void record_builtin_type (enum rid rid_index, const char *name, tree type) { - tree id, decl; + tree id; if (name == 0) id = ridpointers[(int) rid_index]; else id = get_identifier (name); - decl = build_decl (TYPE_DECL, id, type); - pushdecl (decl); - if (debug_hooks->type_decl) - debug_hooks->type_decl (decl, false); + pushdecl (build_decl (TYPE_DECL, id, type)); } /* Build the void_list_node (void_type_node having been created). */ @@ -7052,916 +6469,214 @@ build_void_list_node (void) return t; } -/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */ - -struct c_parm * -build_c_parm (struct c_declspecs *specs, tree attrs, - struct c_declarator *declarator) -{ - struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm); - ret->specs = specs; - ret->attrs = attrs; - ret->declarator = declarator; - return ret; -} +/* Return something to represent absolute declarators containing a *. + TARGET is the absolute declarator that the * contains. + TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile + to apply to the pointer type, represented as identifiers, possible mixed + with attributes. -/* Return a declarator with nested attributes. TARGET is the inner - declarator to which these attributes apply. ATTRS are the - attributes. */ + We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST, + if attributes are present) and whose type is the modifier list. */ -struct c_declarator * -build_attrs_declarator (tree attrs, struct c_declarator *target) +tree +make_pointer_declarator (tree type_quals_attrs, tree target) { - struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); - ret->kind = cdk_attrs; - ret->declarator = target; - ret->u.attrs = attrs; - return ret; + tree quals, attrs; + tree itarget = target; + split_specs_attrs (type_quals_attrs, &quals, &attrs); + if (attrs != NULL_TREE) + itarget = tree_cons (attrs, target, NULL_TREE); + return build1 (INDIRECT_REF, quals, itarget); } -/* Return a declarator for a function with arguments specified by ARGS - and return type specified by TARGET. */ +/* A wrapper around lhd_set_decl_assembler_name that gives static + variables their C names if they are at file scope and only one + translation unit is being compiled, for backwards compatibility + with certain bizarre assembler hacks (like crtstuff.c). */ -struct c_declarator * -build_function_declarator (struct c_arg_info *args, - struct c_declarator *target) +void +c_static_assembler_name (tree decl) { - struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); - ret->kind = cdk_function; - ret->declarator = target; - ret->u.arg_info = args; - return ret; + if (num_in_fnames == 1 + && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL) + SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); + else + lhd_set_decl_assembler_name (decl); } -/* Return a declarator for the identifier IDENT (which may be - NULL_TREE for an abstract declarator). */ +/* Hash and equality functions for link_hash_table: key off + DECL_ASSEMBLER_NAME. */ -struct c_declarator * -build_id_declarator (tree ident) +static hashval_t +link_hash_hash (const void *x_p) { - struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); - ret->kind = cdk_id; - ret->declarator = 0; - ret->u.id = ident; - /* Default value - may get reset to a more precise location. */ - ret->id_loc = input_location; - return ret; + tree x = (tree)x_p; + return (hashval_t) (long)DECL_ASSEMBLER_NAME (x); } -/* Return something to represent absolute declarators containing a *. - TARGET is the absolute declarator that the * contains. - TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes - to apply to the pointer type. */ - -struct c_declarator * -make_pointer_declarator (struct c_declspecs *type_quals_attrs, - struct c_declarator *target) +static int +link_hash_eq (const void *x1_p, const void *x2_p) { - tree attrs; - int quals = 0; - struct c_declarator *itarget = target; - struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); - if (type_quals_attrs) - { - attrs = type_quals_attrs->attrs; - quals = quals_from_declspecs (type_quals_attrs); - if (attrs != NULL_TREE) - itarget = build_attrs_declarator (attrs, target); - } - ret->kind = cdk_pointer; - ret->declarator = itarget; - ret->u.pointer_quals = quals; - return ret; + tree x1 = (tree)x1_p; + tree x2 = (tree)x2_p; + return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2); } -/* Return a pointer to a structure for an empty list of declaration - specifiers. */ +/* Propagate information between definitions and uses between multiple + translation units in TU_LIST based on linkage rules. */ -struct c_declspecs * -build_null_declspecs (void) +void +merge_translation_unit_decls (void) { - struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs); - ret->type = 0; - ret->decl_attr = 0; - ret->attrs = 0; - ret->typespec_word = cts_none; - ret->storage_class = csc_none; - ret->declspecs_seen_p = false; - ret->type_seen_p = false; - ret->non_sc_seen_p = false; - ret->typedef_p = false; - ret->tag_defined_p = false; - ret->explicit_signed_p = false; - ret->deprecated_p = false; - ret->default_int_p = false; - ret->long_p = false; - ret->long_long_p = false; - ret->short_p = false; - ret->signed_p = false; - ret->unsigned_p = false; - ret->complex_p = false; - ret->inline_p = false; - ret->thread_p = false; - ret->const_p = false; - ret->volatile_p = false; - ret->restrict_p = false; - return ret; -} + const tree tu_list = current_file_decl; + tree tu; + tree decl; + htab_t link_hash_table; + tree block; -/* Add the type qualifier QUAL to the declaration specifiers SPECS, - returning SPECS. */ + /* Create the BLOCK that poplevel would have created, but don't + actually call poplevel since that's expensive. */ + block = make_node (BLOCK); + BLOCK_VARS (block) = current_scope->names; + TREE_USED (block) = 1; + DECL_INITIAL (current_file_decl) = block; -struct c_declspecs * -declspecs_add_qual (struct c_declspecs *specs, tree qual) -{ - enum rid i; - bool dupe = false; - specs->non_sc_seen_p = true; - specs->declspecs_seen_p = true; - gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE - && C_IS_RESERVED_WORD (qual)); - i = C_RID_CODE (qual); - switch (i) - { - case RID_CONST: - dupe = specs->const_p; - specs->const_p = true; - break; - case RID_VOLATILE: - dupe = specs->volatile_p; - specs->volatile_p = true; - break; - case RID_RESTRICT: - dupe = specs->restrict_p; - specs->restrict_p = true; - break; - default: - gcc_unreachable (); - } - if (dupe && pedantic && !flag_isoc99) - pedwarn ("duplicate %qE", qual); - return specs; -} + /* If only one translation unit seen, no copying necessary. */ + if (TREE_CHAIN (tu_list) == NULL_TREE) + return; -/* Add the type specifier TYPE to the declaration specifiers SPECS, - returning SPECS. */ + link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL); -struct c_declspecs * -declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) -{ - tree type = spec.spec; - specs->non_sc_seen_p = true; - specs->declspecs_seen_p = true; - specs->type_seen_p = true; - if (TREE_DEPRECATED (type)) - specs->deprecated_p = true; - - /* Handle type specifier keywords. */ - if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type)) - { - enum rid i = C_RID_CODE (type); - if (specs->type) - { - error ("two or more data types in declaration specifiers"); - return specs; - } - if ((int) i <= (int) RID_LAST_MODIFIER) + /* Enter any actual definitions into the hash table. */ + for (tu = tu_list; tu; tu = TREE_CHAIN (tu)) + for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl)) + if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl)) { - /* "long", "short", "signed", "unsigned" or "_Complex". */ - bool dupe = false; - switch (i) + PTR *slot; + slot = htab_find_slot (link_hash_table, decl, INSERT); + + /* If we've already got a definition, work out which one is + the real one, put it into the hash table, and make the + other one DECL_EXTERNAL. This is important to avoid + putting out two definitions of the same symbol in the + assembly output. */ + if (*slot != NULL) { - case RID_LONG: - if (specs->long_long_p) + tree old_decl = (tree) *slot; + + /* If this is weak or common or whatever, suppress it + in favor of the other definition. */ + if (DECL_WEAK (decl)) + DECL_EXTERNAL (decl) = 1; + else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl)) + DECL_EXTERNAL (old_decl) = 1; + else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl)) + DECL_EXTERNAL (decl) = 1; + else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl)) + DECL_EXTERNAL (old_decl) = 1; + + if (DECL_EXTERNAL (decl)) { - error ("%<long long long%> is too long for GCC"); - break; + DECL_INITIAL (decl) = NULL_TREE; + DECL_COMMON (decl) = 0; + DECL_ONE_ONLY (decl) = 0; + DECL_WEAK (decl) = 0; } - if (specs->long_p) + else if (DECL_EXTERNAL (old_decl)) { - if (specs->typespec_word == cts_double) - { - error ("both %<long long%> and %<double%> in " - "declaration specifiers"); - break; - } - if (pedantic && !flag_isoc99 && !in_system_header - && warn_long_long) - pedwarn ("ISO C90 does not support %<long long%>"); - specs->long_long_p = 1; - break; + DECL_INITIAL (old_decl) = NULL_TREE; + DECL_COMMON (old_decl) = 0; + DECL_ONE_ONLY (old_decl) = 0; + DECL_WEAK (old_decl) = 0; + *slot = decl; } - if (specs->short_p) - error ("both %<long%> and %<short%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_void) - error ("both %<long%> and %<void%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_bool) - error ("both %<long%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_char) - error ("both %<long%> and %<char%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_float) - error ("both %<long%> and %<float%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat32) - error ("both %<long%> and %<_Decimal32%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat64) - error ("both %<long%> and %<_Decimal64%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat128) - error ("both %<long%> and %<_Decimal128%> in " - "declaration specifiers"); else - specs->long_p = true; - break; - case RID_SHORT: - dupe = specs->short_p; - if (specs->long_p) - error ("both %<long%> and %<short%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_void) - error ("both %<short%> and %<void%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_bool) - error ("both %<short%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_char) - error ("both %<short%> and %<char%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_float) - error ("both %<short%> and %<float%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_double) - error ("both %<short%> and %<double%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat32) - error ("both %<short%> and %<_Decimal32%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat64) - error ("both %<short%> and %<_Decimal64%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat128) - error ("both %<short%> and %<_Decimal128%> in " - "declaration specifiers"); - else - specs->short_p = true; - break; - case RID_SIGNED: - dupe = specs->signed_p; - if (specs->unsigned_p) - error ("both %<signed%> and %<unsigned%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_void) - error ("both %<signed%> and %<void%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_bool) - error ("both %<signed%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_float) - error ("both %<signed%> and %<float%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_double) - error ("both %<signed%> and %<double%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat32) - error ("both %<signed%> and %<_Decimal32%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat64) - error ("both %<signed%> and %<_Decimal64%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat128) - error ("both %<signed%> and %<_Decimal128%> in " - "declaration specifiers"); - else - specs->signed_p = true; - break; - case RID_UNSIGNED: - dupe = specs->unsigned_p; - if (specs->signed_p) - error ("both %<signed%> and %<unsigned%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_void) - error ("both %<unsigned%> and %<void%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_bool) - error ("both %<unsigned%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_float) - error ("both %<unsigned%> and %<float%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_double) - error ("both %<unsigned%> and %<double%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat32) - error ("both %<unsigned%> and %<_Decimal32%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat64) - error ("both %<unsigned%> and %<_Decimal64%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat128) - error ("both %<unsigned%> and %<_Decimal128%> in " - "declaration specifiers"); - else - specs->unsigned_p = true; - break; - case RID_COMPLEX: - dupe = specs->complex_p; - if (pedantic && !flag_isoc99 && !in_system_header) - pedwarn ("ISO C90 does not support complex types"); - if (specs->typespec_word == cts_void) - error ("both %<complex%> and %<void%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_bool) - error ("both %<complex%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat32) - error ("both %<complex%> and %<_Decimal32%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat64) - error ("both %<complex%> and %<_Decimal64%> in " - "declaration specifiers"); - else if (specs->typespec_word == cts_dfloat128) - error ("both %<complex%> and %<_Decimal128%> in " - "declaration specifiers"); - else - specs->complex_p = true; - break; - default: - gcc_unreachable (); - } - - if (dupe) - error ("duplicate %qE", type); - - return specs; - } - else - { - /* "void", "_Bool", "char", "int", "float" or "double". */ - if (specs->typespec_word != cts_none) - { - error ("two or more data types in declaration specifiers"); - return specs; - } - switch (i) - { - case RID_VOID: - if (specs->long_p) - error ("both %<long%> and %<void%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<void%> in " - "declaration specifiers"); - else if (specs->signed_p) - error ("both %<signed%> and %<void%> in " - "declaration specifiers"); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<void%> in " - "declaration specifiers"); - else if (specs->complex_p) - error ("both %<complex%> and %<void%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_void; - return specs; - case RID_BOOL: - if (specs->long_p) - error ("both %<long%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->signed_p) - error ("both %<signed%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<_Bool%> in " - "declaration specifiers"); - else if (specs->complex_p) - error ("both %<complex%> and %<_Bool%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_bool; - return specs; - case RID_CHAR: - if (specs->long_p) - error ("both %<long%> and %<char%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<char%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_char; - return specs; - case RID_INT: - specs->typespec_word = cts_int; - return specs; - case RID_FLOAT: - if (specs->long_p) - error ("both %<long%> and %<float%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<float%> in " - "declaration specifiers"); - else if (specs->signed_p) - error ("both %<signed%> and %<float%> in " - "declaration specifiers"); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<float%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_float; - return specs; - case RID_DOUBLE: - if (specs->long_long_p) - error ("both %<long long%> and %<double%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<double%> in " - "declaration specifiers"); - else if (specs->signed_p) - error ("both %<signed%> and %<double%> in " - "declaration specifiers"); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<double%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_double; - return specs; - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - { - const char *str; - if (i == RID_DFLOAT32) - str = "_Decimal32"; - else if (i == RID_DFLOAT64) - str = "_Decimal64"; - else - str = "_Decimal128"; - if (specs->long_long_p) - error ("both %<long long%> and %<%s%> in " - "declaration specifiers", str); - if (specs->long_p) - error ("both %<long%> and %<%s%> in " - "declaration specifiers", str); - else if (specs->short_p) - error ("both %<short%> and %<%s%> in " - "declaration specifiers", str); - else if (specs->signed_p) - error ("both %<signed%> and %<%s%> in " - "declaration specifiers", str); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<%s%> in " - "declaration specifiers", str); - else if (specs->complex_p) - error ("both %<complex%> and %<%s%> in " - "declaration specifiers", str); - else if (i == RID_DFLOAT32) - specs->typespec_word = cts_dfloat32; - else if (i == RID_DFLOAT64) - specs->typespec_word = cts_dfloat64; - else - specs->typespec_word = cts_dfloat128; - } - if (!targetm.decimal_float_supported_p ()) - error ("decimal floating point not supported for this target"); - if (pedantic) - pedwarn ("ISO C does not support decimal floating point"); - return specs; - default: - /* ObjC reserved word "id", handled below. */ - break; + { + error ("%Jredefinition of global '%D'", decl, decl); + error ("%J'%D' previously defined here", old_decl, old_decl); + } } + else + *slot = decl; } - } - /* Now we have a typedef (a TYPE_DECL node), an identifier (some - form of ObjC type, cases such as "int" and "long" being handled - above), a TYPE (struct, union, enum and typeof specifiers) or an - ERROR_MARK. In none of these cases may there have previously - been any type specifiers. */ - if (specs->type || specs->typespec_word != cts_none - || specs->long_p || specs->short_p || specs->signed_p - || specs->unsigned_p || specs->complex_p) - error ("two or more data types in declaration specifiers"); - else if (TREE_CODE (type) == TYPE_DECL) - { - if (TREE_TYPE (type) == error_mark_node) - ; /* Allow the type to default to int to avoid cascading errors. */ - else + /* Now insert the desired information from all the definitions + into any plain declarations. */ + for (tu = tu_list; tu; tu = TREE_CHAIN (tu)) + for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl)) + if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl)) { - specs->type = TREE_TYPE (type); - specs->decl_attr = DECL_ATTRIBUTES (type); - specs->typedef_p = true; - specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type); - } - } - else if (TREE_CODE (type) == IDENTIFIER_NODE) - { - tree t = lookup_name (type); - if (!t || TREE_CODE (t) != TYPE_DECL) - error ("%qE fails to be a typedef or built in type", type); - else if (TREE_TYPE (t) == error_mark_node) - ; - else - specs->type = TREE_TYPE (t); - } - else if (TREE_CODE (type) != ERROR_MARK) - { - if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref) - specs->tag_defined_p = true; - if (spec.kind == ctsk_typeof) - specs->typedef_p = true; - specs->type = type; - } - - return specs; -} + tree global_decl; + global_decl = htab_find (link_hash_table, decl); -/* Add the storage class specifier or function specifier SCSPEC to the - declaration specifiers SPECS, returning SPECS. */ + if (! global_decl) + continue; -struct c_declspecs * -declspecs_add_scspec (struct c_declspecs *specs, tree scspec) -{ - enum rid i; - enum c_storage_class n = csc_none; - bool dupe = false; - specs->declspecs_seen_p = true; - gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE - && C_IS_RESERVED_WORD (scspec)); - i = C_RID_CODE (scspec); - if (extra_warnings && specs->non_sc_seen_p) - warning (OPT_Wextra, "%qE is not at beginning of declaration", scspec); - switch (i) - { - case RID_INLINE: - /* C99 permits duplicate inline. Although of doubtful utility, - it seems simplest to permit it in gnu89 mode as well, as - there is also little utility in maintaining this as a - difference between gnu89 and C99 inline. */ - dupe = false; - specs->inline_p = true; - break; - case RID_THREAD: - dupe = specs->thread_p; - if (specs->storage_class == csc_auto) - error ("%<__thread%> used with %<auto%>"); - else if (specs->storage_class == csc_register) - error ("%<__thread%> used with %<register%>"); - else if (specs->storage_class == csc_typedef) - error ("%<__thread%> used with %<typedef%>"); - else - specs->thread_p = true; - break; - case RID_AUTO: - n = csc_auto; - break; - case RID_EXTERN: - n = csc_extern; - /* Diagnose "__thread extern". */ - if (specs->thread_p) - error ("%<__thread%> before %<extern%>"); - break; - case RID_REGISTER: - n = csc_register; - break; - case RID_STATIC: - n = csc_static; - /* Diagnose "__thread static". */ - if (specs->thread_p) - error ("%<__thread%> before %<static%>"); - break; - case RID_TYPEDEF: - n = csc_typedef; - break; - default: - gcc_unreachable (); - } - if (n != csc_none && n == specs->storage_class) - dupe = true; - if (dupe) - error ("duplicate %qE", scspec); - if (n != csc_none) - { - if (specs->storage_class != csc_none && n != specs->storage_class) - { - error ("multiple storage classes in declaration specifiers"); + /* Print any appropriate error messages, and partially merge + the decls. */ + (void) duplicate_decls (decl, global_decl); } - else - { - specs->storage_class = n; - if (n != csc_extern && n != csc_static && specs->thread_p) - { - error ("%<__thread%> used with %qE", scspec); - specs->thread_p = false; - } - } - } - return specs; -} - -/* Add the attributes ATTRS to the declaration specifiers SPECS, - returning SPECS. */ -struct c_declspecs * -declspecs_add_attrs (struct c_declspecs *specs, tree attrs) -{ - specs->attrs = chainon (attrs, specs->attrs); - specs->declspecs_seen_p = true; - return specs; + htab_delete (link_hash_table); } -/* Combine "long", "short", "signed", "unsigned" and "_Complex" type - specifiers with any other type specifier to determine the resulting - type. This is where ISO C checks on complex types are made, since - "_Complex long" is a prefix of the valid ISO C type "_Complex long - double". */ +/* Perform final processing on file-scope data. */ -struct c_declspecs * -finish_declspecs (struct c_declspecs *specs) +void +c_write_global_declarations(void) { - /* If a type was specified as a whole, we have no modifiers and are - done. */ - if (specs->type != NULL_TREE) - { - gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p - && !specs->complex_p); - return specs; - } - - /* If none of "void", "_Bool", "char", "int", "float" or "double" - has been specified, treat it as "int" unless "_Complex" is - present and there are no other specifiers. If we just have - "_Complex", it is equivalent to "_Complex double", but e.g. - "_Complex short" is equivalent to "_Complex short int". */ - if (specs->typespec_word == cts_none) - { - if (specs->long_p || specs->short_p - || specs->signed_p || specs->unsigned_p) - { - specs->typespec_word = cts_int; - } - else if (specs->complex_p) - { - specs->typespec_word = cts_double; - if (pedantic) - pedwarn ("ISO C does not support plain %<complex%> meaning " - "%<double complex%>"); - } - else - { - specs->typespec_word = cts_int; - specs->default_int_p = true; - /* We don't diagnose this here because grokdeclarator will - give more specific diagnostics according to whether it is - a function definition. */ - } - } + tree link; - /* If "signed" was specified, record this to distinguish "int" and - "signed int" in the case of a bit-field with - -funsigned-bitfields. */ - specs->explicit_signed_p = specs->signed_p; - - /* Now compute the actual type. */ - switch (specs->typespec_word) + for (link = current_file_decl; link; link = TREE_CHAIN (link)) { - case cts_void: - gcc_assert (!specs->long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p - && !specs->complex_p); - specs->type = void_type_node; - break; - case cts_bool: - gcc_assert (!specs->long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p - && !specs->complex_p); - specs->type = boolean_type_node; - break; - case cts_char: - gcc_assert (!specs->long_p && !specs->short_p); - gcc_assert (!(specs->signed_p && specs->unsigned_p)); - if (specs->signed_p) - specs->type = signed_char_type_node; - else if (specs->unsigned_p) - specs->type = unsigned_char_type_node; - else - specs->type = char_type_node; - if (specs->complex_p) - { - if (pedantic) - pedwarn ("ISO C does not support complex integer types"); - specs->type = build_complex_type (specs->type); - } - break; - case cts_int: - gcc_assert (!(specs->long_p && specs->short_p)); - gcc_assert (!(specs->signed_p && specs->unsigned_p)); - if (specs->long_long_p) - specs->type = (specs->unsigned_p - ? long_long_unsigned_type_node - : long_long_integer_type_node); - else if (specs->long_p) - specs->type = (specs->unsigned_p - ? long_unsigned_type_node - : long_integer_type_node); - else if (specs->short_p) - specs->type = (specs->unsigned_p - ? short_unsigned_type_node - : short_integer_type_node); - else - specs->type = (specs->unsigned_p - ? unsigned_type_node - : integer_type_node); - if (specs->complex_p) - { - if (pedantic) - pedwarn ("ISO C does not support complex integer types"); - specs->type = build_complex_type (specs->type); - } - break; - case cts_float: - gcc_assert (!specs->long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p); - specs->type = (specs->complex_p - ? complex_float_type_node - : float_type_node); - break; - case cts_double: - gcc_assert (!specs->long_long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p); - if (specs->long_p) - { - specs->type = (specs->complex_p - ? complex_long_double_type_node - : long_double_type_node); - } - else - { - specs->type = (specs->complex_p - ? complex_double_type_node - : double_type_node); - } - break; - case cts_dfloat32: - case cts_dfloat64: - case cts_dfloat128: - gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p && !specs->complex_p); - if (specs->typespec_word == cts_dfloat32) - specs->type = dfloat32_type_node; - else if (specs->typespec_word == cts_dfloat64) - specs->type = dfloat64_type_node; - else - specs->type = dfloat128_type_node; - break; - default: - gcc_unreachable (); - } - - return specs; -} - -/* Synthesize a function which calls all the global ctors or global - dtors in this file. This is only used for targets which do not - support .ctors/.dtors sections. FIXME: Migrate into cgraph. */ -static void -build_cdtor (int method_type, tree cdtors) -{ - tree body = 0; + tree globals = BLOCK_VARS (DECL_INITIAL (link)); + int len = list_length (globals); + tree *vec = xmalloc (sizeof (tree) * len); + int i; + tree decl; - if (!cdtors) - return; + /* Process the decls in the order they were written. */ - for (; cdtors; cdtors = TREE_CHAIN (cdtors)) - append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0), - &body); + for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) + vec[i] = decl; - cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY); -} + wrapup_global_declarations (vec, len); -/* A subroutine of c_write_global_declarations. Perform final processing - on one file scope's declarations (or the external scope's declarations), - GLOBALS. */ + check_global_declarations (vec, len); -static void -c_write_global_declarations_1 (tree globals) -{ - tree decl; - bool reconsider; - - /* Process the decls in the order they were written. */ - for (decl = globals; decl; decl = TREE_CHAIN (decl)) - { - /* Check for used but undefined static functions using the C - standard's definition of "used", and set TREE_NO_WARNING so - that check_global_declarations doesn't repeat the check. */ - if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_INITIAL (decl) == 0 - && DECL_EXTERNAL (decl) - && !TREE_PUBLIC (decl) - && C_DECL_USED (decl)) - { - pedwarn ("%q+F used but never defined", decl); - TREE_NO_WARNING (decl) = 1; - } - - wrapup_global_declaration_1 (decl); + /* Clean up. */ + free (vec); } - - do - { - reconsider = false; - for (decl = globals; decl; decl = TREE_CHAIN (decl)) - reconsider |= wrapup_global_declaration_2 (decl); - } - while (reconsider); - - for (decl = globals; decl; decl = TREE_CHAIN (decl)) - check_global_declaration_1 (decl); -} - -/* A subroutine of c_write_global_declarations Emit debug information for each - of the declarations in GLOBALS. */ - -static void -c_write_global_declarations_2 (tree globals) -{ - tree decl; - - for (decl = globals; decl ; decl = TREE_CHAIN (decl)) - debug_hooks->global_decl (decl); } -/* Preserve the external declarations scope across a garbage collect. */ -static GTY(()) tree ext_block; +/* Reset the parser's state in preparation for a new file. */ void -c_write_global_declarations (void) +c_reset_state (void) { - tree t; - - /* We don't want to do this if generating a PCH. */ - if (pch_file) - return; - - /* Don't waste time on further processing if -fsyntax-only or we've - encountered errors. */ - if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in)) - return; - - /* Close the external scope. */ - ext_block = pop_scope (); - external_scope = 0; - gcc_assert (!current_scope); - - if (ext_block) - { - tree tmp = BLOCK_VARS (ext_block); - int flags; - FILE * stream = dump_begin (TDI_tu, &flags); - if (stream && tmp) - { - dump_node (tmp, flags & ~TDF_SLIM, stream); - dump_end (TDI_tu, stream); - } - } - - /* Process all file scopes in this compilation, and the external_scope, - through wrapup_global_declarations and check_global_declarations. */ - for (t = all_translation_units; t; t = TREE_CHAIN (t)) - c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); - c_write_global_declarations_1 (BLOCK_VARS (ext_block)); - - /* Generate functions to call static constructors and destructors - for targets that do not support .ctors/.dtors sections. These - functions have magic names which are detected by collect2. */ - build_cdtor ('I', static_ctors); static_ctors = 0; - build_cdtor ('D', static_dtors); static_dtors = 0; - - /* We're done parsing; proceed to optimize and emit assembly. - FIXME: shouldn't be the front end's responsibility to call this. */ - cgraph_optimize (); - - /* After cgraph has had a chance to emit everything that's going to - be emitted, output debug information for globals. */ - if (errorcount == 0 && sorrycount == 0) - { - timevar_push (TV_SYMOUT); - for (t = all_translation_units; t; t = TREE_CHAIN (t)) - c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); - c_write_global_declarations_2 (BLOCK_VARS (ext_block)); - timevar_pop (TV_SYMOUT); - } - - ext_block = NULL; + tree link; + tree file_scope_decl; + + /* Pop the global scope. */ + if (current_scope != global_scope) + current_scope = global_scope; + file_scope_decl = current_file_decl; + DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0); + BLOCK_SUPERCONTEXT (DECL_INITIAL (file_scope_decl)) = file_scope_decl; + truly_local_externals = NULL_TREE; + + /* Start a new global binding level. */ + pushlevel (0); + global_scope = current_scope; + current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL); + TREE_CHAIN (current_file_decl) = file_scope_decl; + + /* Reintroduce the builtin declarations. */ + for (link = first_builtin_decl; + link != TREE_CHAIN (last_builtin_decl); + link = TREE_CHAIN (link)) + pushdecl (copy_node (link)); } #include "gt-c-decl.h" |