X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-decl.c;h=690d3b3bc8018c34a8d2ff23e196696f03afa466;hb=1576dec74bf91e0130a9a3aefa2656b575e17ec8;hp=e867ebb6c7227b92237f8c0e2701385d3b606c5c;hpb=a021a5a651999cf512165dedb8de3fef5377890d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-decl.c b/gcc/c-decl.c index e867ebb6c72..690d3b3bc80 100644 --- a/gcc/c-decl.c +++ b/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 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" #include "coretypes.h" +#include "input.h" #include "tm.h" #include "intl.h" #include "tree.h" @@ -91,19 +92,22 @@ static tree enum_next_value; static int enum_overflow; -/* These #defines are for clarity in working with the information block - returned by get_parm_info. */ -#define ARG_INFO_PARMS(args) TREE_PURPOSE(args) -#define ARG_INFO_TAGS(args) TREE_VALUE(args) -#define ARG_INFO_TYPES(args) TREE_CHAIN(args) -#define ARG_INFO_OTHERS(args) TREE_TYPE(args) - /* The file and line that the prototype came from if this is an old-style definition; used for diagnostics in store_parm_decls_oldstyle. */ static location_t current_function_prototype_locus; +/* The argument information structure for the function currently being + defined. */ + +static struct c_arg_info *current_function_arg_info; + +/* 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; + /* The current statement tree. */ static GTY(()) struct stmt_tree_s c_stmt_tree; @@ -145,6 +149,11 @@ static int warn_about_return_type; 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; @@ -164,6 +173,16 @@ bool c_override_global_bindings_to_false; 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. @@ -176,13 +195,15 @@ bool c_override_global_bindings_to_false; 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 */ - /* two free bits */ + 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) @@ -190,17 +211,17 @@ struct c_binding GTY((chain_next ("%h.prev"))) #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) + (((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) + (((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) + (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding) #define I_LABEL_DECL(node) \ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0) @@ -224,7 +245,7 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate 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)"))) + 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)"))) @@ -383,8 +404,10 @@ static GTY(()) tree 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 (tree, tree, enum decl_context, int, tree *); -static tree grokparms (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); /* States indicating how grokdeclarator() should handle declspecs marked @@ -436,6 +459,9 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested) b->depth = scope->depth; b->invisible = invisible; b->nested = nested; + b->inner_comp = 0; + + b->type = 0; b->prev = scope->bindings; scope->bindings = b; @@ -457,7 +483,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested) case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break; default: - abort (); + gcc_unreachable (); } /* Locate the appropriate place in the chain of shadowed decls @@ -498,10 +524,10 @@ 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 ("%Jarray '%D' assumed to have one element", decl, decl); + warning ("%Jarray %qD assumed to have one element", decl, decl); complete_array_type (type, NULL_TREE, 1); @@ -513,7 +539,7 @@ c_finish_incomplete_decl (tree decl) /* The Objective-C front-end often needs to determine the current scope. */ void * -get_current_scope (void) +objc_get_current_scope (void) { return current_scope; } @@ -614,7 +640,7 @@ push_scope (void) if (current_scope && scope->depth == 0) { scope->depth--; - sorry ("GCC supports only %u nested scopes\n", scope->depth); + sorry ("GCC supports only %u nested scopes", scope->depth); } current_scope = scope; @@ -698,23 +724,20 @@ pop_scope (void) /* Warnings for unused labels, errors for undefined labels. */ if (TREE_USED (p) && !DECL_INITIAL (p)) { - error ("%Jlabel `%D' used but not defined", p, p); + error ("%Jlabel %qD 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 ("%Jlabel `%D' defined but not used", p, p); + warning ("%Jlabel %qD defined but not used", p, p); else - warning ("%Jlabel `%D' declared but not defined", p, p); + warning ("%Jlabel %qD declared but not defined", p, p); } /* Labels go in BLOCK_VARS. */ TREE_CHAIN (p) = BLOCK_VARS (block); BLOCK_VARS (block) = p; - -#ifdef ENABLE_CHECKING - if (I_LABEL_BINDING (b->id) != b) abort (); -#endif + gcc_assert (I_LABEL_BINDING (b->id) == b); I_LABEL_BINDING (b->id) = b->shadowed; break; @@ -727,9 +750,7 @@ pop_scope (void) appears in the bindings list with b->id NULL. */ if (b->id) { -#ifdef ENABLE_CHECKING - if (I_TAG_BINDING (b->id) != b) abort (); -#endif + gcc_assert (I_TAG_BINDING (b->id) == b); I_TAG_BINDING (b->id) = b->shadowed; } break; @@ -737,12 +758,18 @@ pop_scope (void) 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 ("%Jnested function %qD declared but never defined", p, p); + undef_nested_function = true; + } goto common_symbol; case VAR_DECL: @@ -752,11 +779,15 @@ pop_scope (void) && !DECL_IN_SYSTEM_HEADER (p) && DECL_NAME (p) && !DECL_ARTIFICIAL (p) - && (scope != file_scope - || (TREE_STATIC (p) && !TREE_PUBLIC (p) - && !TREE_THIS_VOLATILE (p))) - && scope != external_scope) - warning ("%Junused variable `%D'", p, p); + && scope != file_scope + && scope != external_scope) + warning ("%Junused variable %qD", p, p); + + if (b->inner_comp) + { + error ("%Jtype of array %qD completed incompatibly with" + " implicit initialization", p, p); + } /* Fall through. */ case TYPE_DECL: @@ -793,15 +824,15 @@ pop_scope (void) here with b->id NULL in this case. */ if (b->id) { -#ifdef ENABLE_CHECKING - if (I_SYMBOL_BINDING (b->id) != b) abort (); -#endif + 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; } break; default: - abort (); + gcc_unreachable (); } } @@ -877,6 +908,8 @@ pop_file_scope (void) /* Pop off the file scope and close this translation unit. */ pop_scope (); file_scope = 0; + + maybe_apply_pending_pragma_weaks (); cgraph_finalize_compilation_unit (); } @@ -944,10 +977,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; @@ -986,14 +1019,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; } @@ -1029,22 +1062,23 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) agree on the number of arguments. */ if (END_OF_ARGLIST (oldargtype)) { - error ("%Jprototype for '%D' declares more arguments " + error ("%Jprototype for %qD declares more arguments " "than previous old-style definition", newdecl, newdecl); return false; } else if (END_OF_ARGLIST (newargtype)) { - error ("%Jprototype for '%D' declares fewer arguments " + error ("%Jprototype for %qD 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)) { - error ("%Jprototype for '%D' declares arg %d with incompatible type", + error ("%Jprototype for %qD declares argument %d" + " with incompatible type", newdecl, newdecl, i); return false; } @@ -1056,7 +1090,7 @@ 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 ("%Jprototype for '%D' follows non-prototype definition", + warning ("%Jprototype for %qD follows non-prototype definition", newdecl, newdecl); return true; #undef END_OF_ARGLIST @@ -1071,11 +1105,11 @@ 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 (N_("%Jprevious definition of '%D' was here"), decl, decl); + diag (N_("%Jprevious definition of %qD was here"), decl, decl); else if (C_DECL_IMPLICIT (decl)) - diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl); + diag (N_("%Jprevious implicit declaration of %qD was here"), decl, decl); else - diag (N_("%Jprevious declaration of '%D' was here"), decl, decl); + diag (N_("%Jprevious declaration of %qD was here"), decl, decl); } /* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL. @@ -1093,6 +1127,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, tree newtype, oldtype; bool pedwarned = false; bool warned = false; + bool retval = true; /* If we have error_mark_node for either decl or type, just discard the previous decl - we're in an error cascade already. */ @@ -1111,19 +1146,28 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))) { - error ("%J'%D' redeclared as different kind of symbol", + error ("%J%qD redeclared as different kind of symbol", newdecl, newdecl); locate_old_decl (olddecl, error); } else if (TREE_PUBLIC (newdecl)) - warning ("%Jbuilt-in function '%D' declared as non-function", + warning ("%Jbuilt-in function %qD declared as non-function", newdecl, newdecl); else if (warn_shadow) - warning ("%Jdeclaration of '%D' shadows a built-in function", + warning ("%Jdeclaration of %qD shadows a built-in function", newdecl, newdecl); return false; } + /* Enumerators have no linkage, so may only be declared once in a + given scope. */ + if (TREE_CODE (olddecl) == CONST_DECL) + { + error ("%Jredeclaration of enumerator %qD", newdecl, newdecl); + locate_old_decl (olddecl, error); + return false; + } + if (!comptypes (oldtype, newtype)) { if (TREE_CODE (olddecl) == FUNCTION_DECL @@ -1140,7 +1184,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* 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 ("%Jconflicting types for built-in function '%D'", + warning ("%Jconflicting types for built-in function %qD", newdecl, newdecl); return false; } @@ -1162,20 +1206,32 @@ 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)) + && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl)) { - pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl); + pedwarn ("%Jconflicting types for %qD", 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 ("%Jconflicting types for %qD", newdecl, 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 ("%J conflicting type qualifiers for '%D'", newdecl, newdecl); + error ("%J conflicting type qualifiers for %qD", newdecl, newdecl); else - error ("%Jconflicting types for '%D'", newdecl, newdecl); + error ("%Jconflicting types for %qD", newdecl, newdecl); diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); locate_old_decl (olddecl, error); return false; @@ -1190,7 +1246,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl)) return true; /* Allow OLDDECL to continue in use. */ - error ("%Jredefinition of typedef '%D'", newdecl, newdecl); + error ("%Jredefinition of typedef %qD", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } @@ -1214,7 +1270,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !TYPE_ARG_TYPES (TREE_TYPE (newdecl))))) { if (warn_shadow) - warning ("%Jdeclaration of '%D' shadows a built-in function", + warning ("%Jdeclaration of %qD shadows a built-in function", newdecl, newdecl); /* Discard the old built-in function. */ return false; @@ -1222,17 +1278,47 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_INITIAL (newdecl)) { - if (DECL_INITIAL (olddecl) - && !(DECL_DECLARED_INLINE_P (olddecl) - && DECL_EXTERNAL (olddecl) - && !(DECL_DECLARED_INLINE_P (newdecl) - && DECL_EXTERNAL (newdecl) - && same_translation_unit_p (olddecl, newdecl)))) + if (DECL_INITIAL (olddecl)) { - error ("%Jredefinition of '%D'", newdecl, newdecl); - locate_old_decl (olddecl, error); - return false; - } + /* If both decls have extern inline and are in the same TU, + reject the new decl. */ + if (DECL_DECLARED_INLINE_P (olddecl) + && DECL_EXTERNAL (olddecl) + && DECL_DECLARED_INLINE_P (newdecl) + && DECL_EXTERNAL (newdecl) + && same_translation_unit_p (newdecl, olddecl)) + { + error ("%Jredefinition of %qD", newdecl, newdecl); + locate_old_decl (olddecl, error); + return false; + } + /* If both decls have not extern inline, reject the new decl. */ + if (!DECL_DECLARED_INLINE_P (olddecl) + && !DECL_EXTERNAL (olddecl) + && !DECL_DECLARED_INLINE_P (newdecl) + && !DECL_EXTERNAL (newdecl)) + { + error ("%Jredefinition of %qD", newdecl, newdecl); + locate_old_decl (olddecl, error); + return false; + } + /* If the new decl is declared as extern inline, error if they are + in the same TU, otherwise retain the old decl. */ + if (!DECL_DECLARED_INLINE_P (olddecl) + && !DECL_EXTERNAL (olddecl) + && DECL_DECLARED_INLINE_P (newdecl) + && DECL_EXTERNAL (newdecl)) + { + if (same_translation_unit_p (newdecl, olddecl)) + { + error ("%Jredefinition of %qD", newdecl, newdecl); + locate_old_decl (olddecl, error); + return false; + } + else + retval = false; + } + } } /* If we have a prototype after an old-style function definition, the argument types must be checked specially. */ @@ -1252,7 +1338,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, 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. */ + we do diagnose it if -Wtraditional. */ if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl)) { /* Two exceptions to the rule. If olddecl is an extern @@ -1264,7 +1350,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !(DECL_EXTERNAL (olddecl) && DECL_DECLARED_INLINE_P (olddecl))) { - error ("%Jstatic declaration of '%D' follows " + error ("%Jstatic declaration of %qD follows " "non-static declaration", newdecl, newdecl); locate_old_decl (olddecl, error); } @@ -1274,14 +1360,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, { if (DECL_CONTEXT (olddecl)) { - error ("%Jnon-static declaration of '%D' follows " + error ("%Jnon-static declaration of %qD follows " "static declaration", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } else if (warn_traditional) { - warning ("%Jnon-static declaration of '%D' follows " + warning ("%Jnon-static declaration of %qD follows " "static declaration", newdecl, newdecl); warned = true; } @@ -1294,10 +1380,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl)) { if (DECL_THREAD_LOCAL (newdecl)) - error ("%Jthread-local declaration of '%D' follows " + error ("%Jthread-local declaration of %qD follows " "non-thread-local declaration", newdecl, newdecl); else - error ("%Jnon-thread-local declaration of '%D' follows " + error ("%Jnon-thread-local declaration of %qD follows " "thread-local declaration", newdecl, newdecl); locate_old_decl (olddecl, error); @@ -1307,7 +1393,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* Multiple initialized definitions are not allowed (6.9p3,5). */ if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl)) { - error ("%Jredefinition of '%D'", newdecl, newdecl); + error ("%Jredefinition of %qD", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } @@ -1334,7 +1420,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, } else if (warn_traditional) { - warning ("%Jnon-static declaration of '%D' follows " + warning ("%Jnon-static declaration of %qD follows " "static declaration", newdecl, newdecl); warned = true; } @@ -1342,10 +1428,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, else { if (TREE_PUBLIC (newdecl)) - error ("%Jnon-static declaration of '%D' follows " + error ("%Jnon-static declaration of %qD follows " "static declaration", newdecl, newdecl); else - error ("%Jstatic declaration of '%D' follows " + error ("%Jstatic declaration of %qD follows " "non-static declaration", newdecl, newdecl); locate_old_decl (olddecl, error); @@ -1357,15 +1443,23 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, else if (!DECL_FILE_SCOPE_P (newdecl)) { if (DECL_EXTERNAL (newdecl)) - abort (); + { + /* Extern with initializer at block scope, which will + already have received an error. */ + } else if (DECL_EXTERNAL (olddecl)) - error ("%Jdeclaration of '%D' with no linkage follows " - "extern declaration", newdecl, newdecl); + { + error ("%Jdeclaration of %qD with no linkage follows " + "extern declaration", newdecl, newdecl); + locate_old_decl (olddecl, error); + } else - error ("%Jredeclaration of '%D' with no linkage", - newdecl, newdecl); + { + error ("%Jredeclaration of %qD with no linkage", + newdecl, newdecl); + locate_old_decl (olddecl, error); + } - locate_old_decl (olddecl, error); return false; } } @@ -1375,7 +1469,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl) && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) { - warning ("%Jredeclaration of '%D' with different visibility " + warning ("%Jredeclaration of %qD with different visibility " "(old visibility preserved)", newdecl, newdecl); warned = true; } @@ -1386,14 +1480,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (DECL_DECLARED_INLINE_P (newdecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) { - warning ("%Jinline declaration of '%D' follows " + warning ("%Jinline declaration of %qD follows " "declaration with attribute noinline", newdecl, newdecl); warned = true; } else if (DECL_DECLARED_INLINE_P (olddecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) { - warning ("%Jdeclaration of '%D' with attribute noinline follows " + warning ("%Jdeclaration of %qD with attribute noinline follows " "inline declaration ", newdecl, newdecl); warned = true; } @@ -1408,13 +1502,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, { if (TREE_USED (olddecl)) { - warning ("%J'%D' declared inline after being called", + warning ("%J%qD declared inline after being called", olddecl, olddecl); warned = true; } else if (DECL_INITIAL (olddecl)) { - warning ("%J'%D' declared inline after its definition", + warning ("%J%qD declared inline after its definition", olddecl, olddecl); warned = true; } @@ -1434,7 +1528,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (TREE_CODE (newdecl) == PARM_DECL && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl))) { - error ("%Jredefinition of parameter '%D'", newdecl, newdecl); + error ("%Jredefinition of parameter %qD", newdecl, newdecl); locate_old_decl (olddecl, error); return false; } @@ -1447,7 +1541,7 @@ 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) @@ -1458,7 +1552,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !(TREE_CODE (newdecl) == PARM_DECL && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))) { - warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl); + warning ("%Jredundant redeclaration of %qD", newdecl, newdecl); warned = true; } @@ -1466,7 +1560,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (warned || pedwarned) locate_old_decl (olddecl, pedwarned ? pedwarn : warning); - return true; + return retval; } /* Subroutine of duplicate_decls. NEWDECL has been found to be @@ -1484,14 +1578,14 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) in its new location and clear TREE_ASM_WRITTEN (it's not a forward decl anymore). */ 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; - abort (); + gcc_unreachable (); found: b = *here; @@ -1511,7 +1605,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) = composite_type (newtype, oldtype); /* Lay the type out, unless already done. */ - if (oldtype != TREE_TYPE (newdecl)) + if (!comptypes (oldtype, TREE_TYPE (newdecl))) { if (TREE_TYPE (newdecl) != error_mark_node) layout_type (TREE_TYPE (newdecl)); @@ -1548,6 +1642,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) make_var_volatile (newdecl); } + /* Merge deprecatedness. */ + if (TREE_DEPRECATED (newdecl)) + TREE_DEPRECATED (olddecl) = 1; + /* 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); @@ -1604,7 +1702,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) 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)) + if (!TREE_PUBLIC (olddecl)) TREE_PUBLIC (DECL_NAME (olddecl)) = 0; } if (DECL_EXTERNAL (newdecl)) @@ -1614,7 +1712,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); @@ -1667,7 +1765,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) } /* 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); @@ -1677,7 +1775,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) /* 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) @@ -1689,7 +1787,7 @@ 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; } } @@ -1763,23 +1861,30 @@ warn_if_shadowing (tree new_decl) { tree old_decl = b->decl; - if (TREE_CODE (old_decl) == PARM_DECL) - warning ("%Jdeclaration of '%D' shadows a parameter", + if (old_decl == error_mark_node) + { + warning ("%Jdeclaration of %qD shadows previous non-variable", + new_decl, new_decl); + break; + } + else if (TREE_CODE (old_decl) == PARM_DECL) + warning ("%Jdeclaration of %qD shadows a parameter", new_decl, new_decl); else if (DECL_FILE_SCOPE_P (old_decl)) - warning ("%Jdeclaration of '%D' shadows a global declaration", + warning ("%Jdeclaration of %qD shadows a global declaration", new_decl, new_decl); else if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl)) - warning ("%Jdeclaration of '%D' shadows a built-in function", - new_decl, new_decl); + { + warning ("%Jdeclaration of %qD shadows a built-in function", + new_decl, new_decl); + break; + } else - warning ("%Jdeclaration of '%D' shadows a previous local", + warning ("%Jdeclaration of %qD shadows a previous local", new_decl, new_decl); - if (TREE_CODE (old_decl) != FUNCTION_DECL - || ! DECL_BUILT_IN (old_decl)) - warning ("%Jshadowed declaration is here", old_decl); + warning ("%Jshadowed declaration is here", old_decl); break; } @@ -1843,7 +1948,7 @@ clone_underlying_type (tree x) { tree tt = TREE_TYPE (x); DECL_ORIGINAL_TYPE (x) = tt; - tt = build_type_copy (tt); + tt = build_variant_type_copy (tt); TYPE_NAME (tt) = x; TREE_USED (tt) = TREE_USED (x); TREE_TYPE (x) = tt; @@ -1867,7 +1972,7 @@ pushdecl (tree x) bool nested = false; /* Functions need the lang_decl data. */ - if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x)) + 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 @@ -1895,6 +2000,9 @@ pushdecl (tree x) b = I_SYMBOL_BINDING (name); if (b && B_IN_SCOPE (b, scope)) { + if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE + && COMPLETE_TYPE_P (TREE_TYPE (x))) + b->inner_comp = false; if (duplicate_decls (x, b->decl)) return b->decl; else @@ -1915,13 +2023,63 @@ pushdecl (tree x) 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); + } if (warn_nested_externs && scope != file_scope && !DECL_IN_SYSTEM_HEADER (x)) - warning ("nested extern declaration of '%D'", x); + warning ("nested extern declaration of %qD", x); while (b && !B_IN_EXTERNAL_SCOPE (b)) - b = b->shadowed; + { + /* 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 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 @@ -1932,37 +2090,35 @@ pushdecl (tree x) && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl)) && duplicate_decls (x, b->decl)) { + tree thistype; + thistype = (vistype ? composite_type (vistype, type) : 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)) { - bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false); - nested = true; - } - } - /* Similarly, a declaration of a function with static linkage at - block scope must be checked against any existing declaration - of that function at file scope. */ - else if (TREE_CODE (x) == FUNCTION_DECL && scope != file_scope - && !TREE_PUBLIC (x) && !DECL_INITIAL (x)) - { - if (warn_nested_externs && !DECL_IN_SYSTEM_HEADER (x)) - warning ("nested static declaration of '%D'", x); - - while (b && !B_IN_FILE_SCOPE (b)) - b = b->shadowed; - - if (b && same_translation_unit_p (x, b->decl) - && duplicate_decls (x, b->decl)) - { - bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true); - return b->decl; - } - else - { - bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false); - nested = true; + 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; + } } } @@ -2013,14 +2169,11 @@ pushdecl_top_level (tree x) { tree name; bool nested = false; - - if (TREE_CODE (x) != VAR_DECL) - abort (); + gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL); name = DECL_NAME (x); - if (I_SYMBOL_BINDING (name)) - abort (); + gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name)); if (TREE_PUBLIC (x)) { @@ -2042,10 +2195,10 @@ implicit_decl_warning (tree id, tree olddecl) case 0: return; case 1: diag = warning; break; case 2: diag = error; break; - default: abort (); + default: gcc_unreachable (); } - diag (N_("implicit declaration of function '%E'"), id); + diag (N_("implicit declaration of function %qE"), id); if (olddecl) locate_old_decl (olddecl, diag); } @@ -2056,10 +2209,24 @@ implicit_decl_warning (tree id, tree olddecl) tree implicitly_declare (tree functionid) { - tree decl = lookup_name_in_scope (functionid, external_scope); + 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; + } + } 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 @@ -2073,10 +2240,13 @@ implicitly_declare (tree functionid) } else { + 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. */ + then recycle the old declaration but with the new type. */ if (!C_DECL_IMPLICIT (decl)) { implicit_decl_warning (functionid, decl); @@ -2084,21 +2254,27 @@ implicitly_declare (tree functionid) } if (DECL_BUILT_IN (decl)) { - if (!comptypes (default_function_type, TREE_TYPE (decl))) + newtype = build_type_attribute_variant (newtype, + TYPE_ATTRIBUTES + (TREE_TYPE (decl))); + if (!comptypes (newtype, TREE_TYPE (decl))) { warning ("incompatible implicit declaration of built-in" " function %qD", decl); + newtype = TREE_TYPE (decl); } } else { - if (!comptypes (default_function_type, TREE_TYPE (decl))) + 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; @@ -2111,6 +2287,9 @@ implicitly_declare (tree functionid) 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)); /* C89 says implicit declarations are in the innermost block. So we record the decl in the standard fashion. */ @@ -2142,14 +2321,14 @@ undeclared_variable (tree id) if (current_function_decl == 0) { - error ("'%E' undeclared here (not in a function)", id); + error ("%qE undeclared here (not in a function)", id); scope = current_scope; } else { - error ("'%E' undeclared (first use in this function)", id); + error ("%qE undeclared (first use in this function)", id); - if (! already) + if (!already) { error ("(Each undeclared identifier is reported only once"); error ("for each function it appears in.)"); @@ -2190,7 +2369,7 @@ lookup_label (tree name) if (current_function_decl == 0) { - error ("label %s referenced outside of any function", + error ("label %qs referenced outside of any function", IDENTIFIER_POINTER (name)); return 0; } @@ -2233,7 +2412,7 @@ declare_label (tree name) at this scope */ if (b && B_IN_CURRENT_SCOPE (b)) { - error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name)); + error ("duplicate label declaration %qs", IDENTIFIER_POINTER (name)); locate_old_decl (b->decl, error); /* Just use the previous declaration. */ @@ -2268,7 +2447,7 @@ define_label (location_t location, tree name) || (DECL_CONTEXT (label) != current_function_decl && C_DECLARED_LABEL_FLAG (label)))) { - error ("%Hduplicate label `%D'", &location, label); + error ("%Hduplicate label %qD", &location, label); locate_old_decl (label, error); return 0; } @@ -2291,7 +2470,7 @@ define_label (location_t location, tree name) if (warn_traditional && !in_system_header && lookup_name (name)) warning ("%Htraditional C lacks a separate namespace for labels, " - "identifier `%s' conflicts", &location, + "identifier %qs conflicts", &location, IDENTIFIER_POINTER (name)); /* Mark label as having been defined. */ @@ -2356,7 +2535,7 @@ void pending_xref_error (void) { if (pending_invalid_xref != 0) - error ("%H`%s' defined as wrong kind of tag", + error ("%H%qs defined as wrong kind of tag", &pending_invalid_xref_location, IDENTIFIER_POINTER (pending_invalid_xref)); pending_invalid_xref = 0; @@ -2402,11 +2581,13 @@ c_init_decl_processing (void) tree ptr_ftype_void, ptr_ftype_ptr; location_t save_loc = input_location; - /* Adds some ggc roots, and reserved words for c-parse.in. */ + /* Initialize reserved words for parser. */ c_parse_init (); current_function_decl = 0; + gcc_obstack_init (&parser_obstack); + /* Make the externals scope. */ push_scope (); external_scope = current_scope; @@ -2421,7 +2602,7 @@ c_init_decl_processing (void) input_location.line = 0; #endif - build_common_tree_nodes (flag_signed_char); + build_common_tree_nodes (flag_signed_char, false); c_common_nodes_and_builtins (); @@ -2462,9 +2643,9 @@ c_make_fname_decl (tree id, int type_dep) tree decl, type, init; size_t length = strlen (name); - type = build_array_type - (build_qualified_type (char_type_node, TYPE_QUAL_CONST), - build_index_type (size_int (length))); + type = build_array_type (char_type_node, + build_index_type (size_int (length))); + type = c_build_qualified_type (type, TYPE_QUAL_CONST); decl = build_decl (VAR_DECL, id, type); @@ -2516,8 +2697,7 @@ builtin_function (const char *name, tree type, int function_code, SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); /* Should never be called on a symbol with a preexisting meaning. */ - if (I_SYMBOL_BINDING (id)) - abort (); + gcc_assert (!I_SYMBOL_BINDING (id)); bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false); @@ -2547,7 +2727,7 @@ builtin_function (const char *name, tree type, int function_code, Otherwise, it is an error. */ void -shadow_tag (tree declspecs) +shadow_tag (const struct c_declspecs *declspecs) { shadow_tag_warned (declspecs, 0); } @@ -2555,21 +2735,13 @@ shadow_tag (tree declspecs) /* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning, but no pedwarn. */ void -shadow_tag_warned (tree declspecs, int warned) +shadow_tag_warned (const struct c_declspecs *declspecs, int warned) { - int found_tag = 0; - tree link; - tree specs, attrs; + bool found_tag = false; - 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)) + if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p) { - tree value = TREE_VALUE (link); + tree value = declspecs->type; enum tree_code code = TREE_CODE (value); if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) @@ -2579,7 +2751,7 @@ shadow_tag_warned (tree declspecs, int warned) tree name = TYPE_NAME (value); tree t; - found_tag++; + found_tag = true; if (name == 0) { @@ -2590,8 +2762,29 @@ shadow_tag_warned (tree 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) @@ -2603,67 +2796,153 @@ shadow_tag_warned (tree declspecs, int warned) } else { - if (!warned && ! in_system_header) + if (warned != 1 && !in_system_header) { - warning ("useless keyword or type name in empty declaration"); - warned = 2; + pedwarn ("useless type name in empty declaration"); + warned = 1; } } } + 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 ("% in empty declaration"); + warned = 1; + } + + if (current_scope == file_scope && declspecs->storage_class == csc_auto) + { + error ("% in file-scope empty declaration"); + warned = 1; + } + + if (current_scope == file_scope && declspecs->storage_class == csc_register) + { + error ("% in file-scope empty declaration"); + warned = 1; + } + + if (!warned && !in_system_header && declspecs->storage_class != csc_none) + { + warning ("useless storage class specifier in empty declaration"); + warned = 2; + } + + if (!warned && !in_system_header && declspecs->thread_p) + { + warning ("useless %<__thread%> in empty declaration"); + warned = 2; + } - if (found_tag > 1) - error ("two types specified in one empty declaration"); + if (!warned && !in_system_header && (declspecs->const_p + || declspecs->volatile_p + || declspecs->restrict_p)) + { + warning ("useless type qualifier in empty declaration"); + warned = 2; + } if (warned != 1) { - if (found_tag == 0) + if (!found_tag) pedwarn ("empty declaration"); } } + +/* 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 - nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P - is nonzero is the array is [*], a VLA of unspecified length which 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 (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. */ + false otherwise. The field for the contained declarator is left to be + filled in by set_array_declarator_inner. */ -tree -build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p) +struct c_declarator * +build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, + bool vla_unspec_p) { - tree decl; - decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE); - TREE_TYPE (decl) = quals; - TREE_STATIC (decl) = (static_p ? 1 : 0); + 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; if (pedantic && !flag_isoc99) { - if (static_p || quals != NULL_TREE) - pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators"); + if (static_p || quals != NULL) + pedwarn ("ISO C90 does not support % 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) - warning ("GCC does not yet properly implement `[*]' array declarators"); - return decl; + warning ("GCC does not yet properly implement %<[*]%> array declarators"); + return declarator; } -/* 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. */ +/* 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). */ -tree -set_array_declarator_type (tree decl, tree type, int abstract_p) +struct c_declarator * +set_array_declarator_inner (struct c_declarator *decl, + struct c_declarator *inner, bool abstract_p) { - TREE_OPERAND (decl, 0) = type; - if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl))) + decl->declarator = inner; + if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED + || decl->u.array.attrs != NULL_TREE + || decl->u.array.static_p)) error ("static or type qualifiers in abstract declarator"); return decl; } @@ -2671,34 +2950,20 @@ set_array_declarator_type (tree decl, tree type, int abstract_p) /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree -groktypename (tree type_name) +groktypename (struct c_type_name *type_name) { - tree specs, attrs; - - if (TREE_CODE (type_name) != TREE_LIST) - return type_name; + tree type; + tree attrs = type_name->specs->attrs; - split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs); + type_name->specs->attrs = NULL_TREE; - type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, 0, - NULL); + type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME, + false, NULL); /* Apply attributes. */ - decl_attributes (&type_name, attrs, 0); + decl_attributes (&type, attrs, 0); - return type_name; -} - -/* Return a PARM_DECL node for a given pair of specs and declarator. */ - -tree -groktypename_in_parm_context (tree type_name) -{ - if (TREE_CODE (type_name) != TREE_LIST) - return type_name; - return grokdeclarator (TREE_VALUE (type_name), - TREE_PURPOSE (type_name), - PARM, 0, NULL); + return type; } /* Decode a declarator in an ordinary declaration or data definition. @@ -2717,7 +2982,8 @@ groktypename_in_parm_context (tree type_name) grokfield and not through here. */ tree -start_decl (tree declarator, tree declspecs, int initialized, tree attributes) +start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, + bool initialized, tree attributes) { tree decl; tree tem; @@ -2729,12 +2995,14 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes) 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 ("%J'%D' is usually a function", decl, decl); + warning ("%J%qD is usually a function", decl, decl); if (initialized) /* Is it valid for this decl to have an initializer at all? @@ -2743,18 +3011,18 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes) switch (TREE_CODE (decl)) { case TYPE_DECL: - error ("typedef '%D' is initialized (use __typeof__ instead)", decl); + error ("typedef %qD is initialized (use __typeof__ instead)", decl); initialized = 0; break; case FUNCTION_DECL: - error ("function '%D' is initialized like a variable", decl); + error ("function %qD is initialized like a variable", decl); initialized = 0; break; case PARM_DECL: /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */ - error ("parameter '%D' is initialized", decl); + error ("parameter %qD is initialized", decl); initialized = 0; break; @@ -2779,12 +3047,16 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes) } else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) { - error ("variable '%D' has initializer but incomplete type", decl); + error ("variable %qD has initializer but incomplete type", decl); initialized = 0; } - else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) + else if (C_DECL_VARIABLE_SIZE (decl)) { - error ("elements of array '%D' have incomplete 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"); initialized = 0; } } @@ -2830,13 +3102,13 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes) if (TREE_CODE (decl) == FUNCTION_DECL && targetm.calls.promote_prototypes (TREE_TYPE (decl))) { - tree ce = declarator; + struct c_declarator *ce = declarator; - if (TREE_CODE (ce) == INDIRECT_REF) - ce = TREE_OPERAND (declarator, 0); - if (TREE_CODE (ce) == CALL_EXPR) + if (ce->kind == cdk_pointer) + ce = declarator->declarator; + if (ce->kind == cdk_function) { - tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1)); + tree args = ce->u.arg_info->parms; for (; args; args = TREE_CHAIN (args)) { tree type = TREE_TYPE (args); @@ -2851,14 +3123,17 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes) && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) - warning ("%Jinline function '%D' given attribute noinline", decl, decl); + warning ("%Jinline function %qD 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) = 0; + if (initialized && DECL_EXTERNAL (tem)) + { + DECL_EXTERNAL (tem) = 0; + TREE_STATIC (tem) = 1; + } return tem; } @@ -2876,7 +3151,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree) const char *asmspec = 0; /* If a name was specified, get the string. */ - if (current_scope == file_scope) + if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) + && DECL_FILE_SCOPE_P (decl)) asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); @@ -2915,19 +3191,19 @@ finish_decl (tree decl, tree init, tree asmspec_tree) type = TREE_TYPE (decl); if (failure == 1) - error ("%Jinitializer fails to determine size of '%D'", decl, decl); + error ("%Jinitializer fails to determine size of %qD", decl, decl); else if (failure == 2) { if (do_default) - error ("%Jarray size missing in '%D'", decl, decl); + error ("%Jarray size missing in %qD", 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; } @@ -2936,7 +3212,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) 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); + error ("%Jzero or negative size array %qD", decl, decl); layout_decl (decl, 0); } @@ -2962,7 +3238,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) is an error. */ : !DECL_EXTERNAL (decl))) { - error ("%Jstorage size of '%D' isn't known", decl, decl); + error ("%Jstorage size of %qD isn%'t known", decl, decl); TREE_TYPE (decl) = error_mark_node; } @@ -2972,7 +3248,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 ("%Jstorage size of '%D' isn't constant", decl, decl); + error ("%Jstorage size of %qD isn%'t constant", decl, decl); } if (TREE_USED (type)) @@ -2985,14 +3261,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (TREE_CODE (decl) == FUNCTION_DECL && asmspec) { if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) - { - tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)]; - set_user_assembler_name (builtin, asmspec); - if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY) - init_block_move_fn (asmspec); - else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET) - init_block_clear_fn (asmspec); - } + set_builtin_user_assembler_name (decl, asmspec); set_user_assembler_name (decl, asmspec); } @@ -3023,12 +3292,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree) ordinary, non-register local variable. Historically, GCC has accepted -- but ignored -- the ASMSPEC in this case. */ - if (! DECL_FILE_SCOPE_P (decl) + if (!DECL_FILE_SCOPE_P (decl) && TREE_CODE (decl) == VAR_DECL && !C_DECL_REGISTER (decl) && !TREE_STATIC (decl)) warning ("%Jignoring asm-specifier for non-static local " - "variable '%D'", decl, decl); + "variable %qD", decl, decl); else if (C_DECL_REGISTER (decl)) change_decl_assembler_name (decl, get_identifier (asmspec)); else @@ -3087,7 +3356,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) /* 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); @@ -3152,18 +3421,29 @@ finish_decl (tree decl, tree init, tree asmspec_tree) } } +/* 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 (tree parm) +push_parm_decl (const struct c_parm *parm) { tree decl; - decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)), - TREE_PURPOSE (TREE_PURPOSE (parm)), - PARM, 0, NULL); - decl_attributes (&decl, TREE_VALUE (parm), 0); + decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL); + decl_attributes (&decl, parm->attrs, 0); decl = pushdecl (decl); @@ -3202,9 +3482,14 @@ 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 = build_decl (VAR_DECL, NULL_TREE, type); + tree decl; 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); @@ -3217,8 +3502,8 @@ build_compound_literal (tree type, tree init) if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) { int failure = complete_array_type (type, DECL_INITIAL (decl), 1); - if (failure) - abort (); + + gcc_assert (!failure); } type = TREE_TYPE (decl); @@ -3244,6 +3529,7 @@ build_compound_literal (tree type, tree init) 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); } @@ -3271,12 +3557,12 @@ complete_array_type (tree type, tree initial_value, int do_default) = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); maxindex = build_int_cst (NULL_TREE, (TREE_STRING_LENGTH (initial_value) - / eltsize) - 1, 0); + / eltsize) - 1); } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { tree elts = CONSTRUCTOR_ELTS (initial_value); - maxindex = build_int_cst (NULL_TREE, -1, -1); + maxindex = build_int_cst (NULL_TREE, -1); for (; elts; elts = TREE_CHAIN (elts)) { if (TREE_PURPOSE (elts)) @@ -3293,22 +3579,22 @@ complete_array_type (tree type, tree initial_value, int do_default) value = 1; /* Prevent further error messages. */ - maxindex = build_int_cst (NULL_TREE, 0, 0); + maxindex = build_int_cst (NULL_TREE, 0); } } if (!maxindex) { if (do_default) - maxindex = build_int_cst (NULL_TREE, 0, 0); + maxindex = build_int_cst (NULL_TREE, 0); value = 2; } if (maxindex) { TYPE_DOMAIN (type) = build_index_type (maxindex); - if (!TREE_TYPE (maxindex)) - abort (); + + gcc_assert (TREE_TYPE (maxindex)); } /* Lay out the type now that we can get the real answer. */ @@ -3368,7 +3654,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) field widths. */ if (TREE_CODE (*width) != INTEGER_CST) { - error ("bit-field `%s' width not an integer constant", name); + error ("bit-field %qs width not an integer constant", name); *width = integer_one_node; } else @@ -3376,12 +3662,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 `%s'", name); + error ("negative width in bit-field %qs", name); *width = integer_one_node; } else if (integer_zerop (*width) && orig_name) { - error ("zero width for bit-field `%s'", name); + error ("zero width for bit-field %qs", name); *width = integer_one_node; } } @@ -3391,7 +3677,7 @@ 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 `%s' has invalid type", name); + error ("bit-field %qs has invalid type", name); *type = unsigned_type_node; } @@ -3400,7 +3686,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) && type_mv != integer_type_node && type_mv != unsigned_type_node && type_mv != boolean_type_node) - pedwarn ("type of bit-field `%s' is a GCC extension", name); + pedwarn ("type of bit-field %qs is a GCC extension", name); if (type_mv == boolean_type_node) max_width = CHAR_TYPE_SIZE; @@ -3409,9 +3695,9 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) if (0 < compare_tree_int (*width, max_width)) { - error ("width of `%s' exceeds its type", name); + error ("width of %qs exceeds its type", name); w = max_width; - *width = build_int_cst (NULL_TREE, w, 0); + *width = build_int_cst (NULL_TREE, w); } else w = tree_low_cst (*width, 1); @@ -3422,7 +3708,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) if (!lt || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type)) || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type))) - warning ("`%s' is narrower than values of its type", name); + warning ("%qs is narrower than values of its type", name); } } @@ -3432,8 +3718,7 @@ 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 chain of tree_list nodes whose value fields - are the storage classes and type specifiers. + DECLSPECS is a c_declspecs structure for the declaration 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. @@ -3445,7 +3730,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 1 if the decl has an initializer. + INITIALIZED is true 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. @@ -3457,34 +3742,30 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) and `extern' are interpreted. */ static tree -grokdeclarator (tree declarator, tree declspecs, - enum decl_context decl_context, int initialized, tree *width) +grokdeclarator (const struct c_declarator *declarator, + struct c_declspecs *declspecs, + enum decl_context decl_context, bool initialized, tree *width) { - int specbits = 0; - tree spec; - tree type = NULL_TREE; - int longlong = 0; + tree type = declspecs->type; + bool threadp = declspecs->thread_p; + enum c_storage_class storage_class = declspecs->storage_class; 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; int funcdef_flag = 0; - enum tree_code innermost_code = ERROR_MARK; + bool funcdef_syntax = false; int size_varies = 0; - tree decl_attr = NULL_TREE; - tree array_ptr_quals = NULL_TREE; + tree decl_attr = declspecs->decl_attr; + int array_ptr_quals = TYPE_UNQUALIFIED; + tree array_ptr_attrs = NULL_TREE; int array_parm_static = 0; tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; - tree arg_info = NULL_TREE; + struct c_arg_info *arg_info = 0; if (decl_context == FUNCDEF) funcdef_flag = 1, decl_context = NORMAL; @@ -3492,30 +3773,31 @@ grokdeclarator (tree declarator, tree declspecs, /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ { - tree decl = declarator; + const struct c_declarator *decl = declarator; name = 0; while (decl) - switch (TREE_CODE (decl)) + switch (decl->kind) { - case ARRAY_REF: - case INDIRECT_REF: - case CALL_EXPR: - innermost_code = TREE_CODE (decl); - decl = TREE_OPERAND (decl, 0); + case cdk_function: + case cdk_array: + case cdk_pointer: + funcdef_syntax = (decl->kind == cdk_function); + decl = decl->declarator; break; - case TREE_LIST: - decl = TREE_VALUE (decl); + case cdk_attrs: + decl = decl->declarator; break; - case IDENTIFIER_NODE: - name = IDENTIFIER_POINTER (decl); + case cdk_id: + if (decl->u.id) + name = IDENTIFIER_POINTER (decl->u.id); decl = 0; break; default: - abort (); + gcc_unreachable (); } orig_name = name; if (name == 0) @@ -3525,7 +3807,7 @@ grokdeclarator (tree declarator, tree declspecs, /* A function definition's declarator must have the form of a function declarator. */ - if (funcdef_flag && innermost_code != CALL_EXPR) + if (funcdef_flag && !funcdef_syntax) return 0; /* If this looks like a function definition, make it one, @@ -3534,791 +3816,483 @@ grokdeclarator (tree declarator, tree declspecs, if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag) decl_context = PARM; - /* 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 (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS) + warn_deprecated_use (declspecs->type); - Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char' - and did not come from a user typedef. + typedef_type = type; + size_varies = C_TYPE_VARIABLE_SIZE (type); - Set LONGLONG if `long' is mentioned twice. */ + /* Diagnose defaulting to "int". */ - for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) + if (declspecs->default_int_p && !in_system_header) { - 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; + /* 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 % in declaration of %qs", name); + } - 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)); - } + /* 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); - /* 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'"); - } + /* Figure out the type qualifiers for the declaration. There are + two ways a declaration can become qualified. One is something + like `const int i' where the `const' is explicit. Another is + something like `typedef const int CI; CI i' where the type of the + declaration contains the `const'. A third possibility is that + there is a type qualifier on the element type of a typedefed + array type, in which case we should extract that qualifier so + that c_apply_type_quals_to_decls receives the full list of + qualifiers to work with (C90 is not entirely clear about whether + 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); + if (pedantic && !flag_isoc99) + { + if (constp > 1) + pedwarn ("duplicate %"); + if (restrictp > 1) + pedwarn ("duplicate %"); + if (volatilep > 1) + pedwarn ("duplicate %"); + } + if (!flag_gen_aux_info && (TYPE_QUALS (element_type))) + type = TYPE_MAIN_VARIANT (type); + type_quals = ((constp ? TYPE_QUAL_CONST : 0) + | (restrictp ? TYPE_QUAL_RESTRICT : 0) + | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - 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) + /* 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 %"); + if (storage_class == csc_register) + error ("function definition declared %"); + if (storage_class == csc_typedef) + error ("function definition declared %"); + 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 { - if (TREE_TYPE (id) == error_mark_node) - ; /* Allow the type to default to int to avoid cascading errors. */ - else + switch (decl_context) { - type = TREE_TYPE (id); - decl_attr = DECL_ATTRIBUTES (id); - typedef_decl = id; + 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; } - /* Built-in types come as identifiers. */ - else if (TREE_CODE (id) == IDENTIFIER_NODE) + } + else if (storage_class == csc_extern + && initialized + && !funcdef_flag) + { + /* 'extern' with initialization is invalid if not at file scope. */ + if (current_scope == file_scope) + warning ("%qs initialized and declared %", name); + else + error ("%qs has both % and initializer", name); + } + else if (current_scope == file_scope) + { + if (storage_class == csc_auto) + error ("file-scope declaration of %qs specifies %", name); + if (pedantic && storage_class == csc_register) + pedwarn ("file-scope declaration of %qs specifies %", name); + } + else + { + if (storage_class == csc_extern && funcdef_flag) + error ("nested function %qs declared %", name); + else if (threadp && storage_class == csc_none) { - tree t = lookup_name (id); - if (!t || TREE_CODE (t) != TYPE_DECL) - error ("`%s' fails to be a typedef or built in type", - IDENTIFIER_POINTER (id)); - else if (TREE_TYPE (t) == error_mark_node) - ; - else - { - type = TREE_TYPE (t); - typedef_decl = t; - } + error ("function-scope %qs implicitly auto and declared " + "%<__thread%>", + name); + threadp = false; } - else if (TREE_CODE (id) != ERROR_MARK) - type = id; - - found: - ; } - typedef_type = type; - if (type) - size_varies = C_TYPE_VARIABLE_SIZE (type); - - /* No type at all: default to `int', and set DEFAULTED_INT - because it was not a user-defined typedef. */ + /* 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. */ - if (type == 0) + while (declarator && declarator->kind != cdk_id) { - 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) + if (type == error_mark_node) { - /* 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); + declarator = declarator->declarator; + continue; } - defaulted_int = 1; - type = integer_type_node; - } - - /* Now process the modifiers that were specified - and check for invalid combinations. */ + /* 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 + where the name was omitted). + For the last case, we have just exited the loop. - /* Long double is a special combination. */ + 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. + After this sequence of ifs, TYPE is the type of the + array or function or pointer, and DECLARATOR has had its + outermost layer removed. */ - 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); - } - } - - /* Check the type and width of a bit-field. */ - if (bitfield) - check_bitfield_type_and_width (&type, width, orig_name); - - /* Figure out the type qualifiers for the declaration. There are - two ways a declaration can become qualified. One is something - like `const int i' where the `const' is explicit. Another is - something like `typedef const int CI; CI i' where the type of the - declaration contains the `const'. A third possibility is that - there is a type qualifier on the element type of a typedefed - array type, in which case we should extract that qualifier so - that c_apply_type_quals_to_decls receives the full list of - qualifiers to work with (C90 is not entirely clear about whether - duplicate qualifiers should be diagnosed in this case, but it - seems most appropriate to do so). */ - element_type = strip_array_types (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'"); - if (restrictp > 1) - pedwarn ("duplicate `restrict'"); - if (volatilep > 1) - pedwarn ("duplicate `volatile'"); - } - 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 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 == file_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 == file_scope) - warning ("`%s' initialized and declared `extern'", name); - else - error ("`%s' has both `extern' and initializer", name); - } - else if (current_scope == file_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). */ - - while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE) - { - if (type == error_mark_node) - { - declarator = TREE_OPERAND (declarator, 0); - continue; - } - - /* 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 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. - After this sequence of ifs, TYPE is the type of the - array or function or pointer, and DECLARATOR has had its - outermost layer removed. */ - - if (array_ptr_quals != NULL_TREE || array_parm_static) + if (array_ptr_quals != TYPE_UNQUALIFIED + || array_ptr_attrs != 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 = NULL_TREE; + array_ptr_quals = TYPE_UNQUALIFIED; + array_ptr_attrs = NULL_TREE; array_parm_static = 0; } - if (TREE_CODE (declarator) == TREE_LIST) + switch (declarator->kind) { - /* 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 = TREE_TYPE (declarator); - array_parm_static = TREE_STATIC (declarator); - - declarator = TREE_OPERAND (declarator, 0); - - /* Check for some types that there cannot be arrays of. */ - - 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 `%s' as array of functions", name); + 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); + + array_ptr_quals = declarator->u.array.quals; + array_ptr_attrs = declarator->u.array.attrs; + array_parm_static = declarator->u.array.static_p; + + declarator = declarator->declarator; + + /* 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 (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("declaration of %qs 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 (size == error_mark_node) type = error_mark_node; - } - - 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 (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) - { - /* 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 `%s' has non-integer type", name); - size = integer_one_node; - } - - 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 `%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 `%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 - { - /* 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_OVERFLOW (itype)) - { - error ("size of array `%s' is too large", name); - type = error_mark_node; - continue; - } - - if (size_varies) - itype = variable_size (itype); - 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 (type == error_mark_node) + continue; - /* 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); - } + /* 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 pedantic, complain about arrays of incomplete types. */ + 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 (pedantic && integer_zerop (size)) + pedwarn ("ISO C forbids zero-size array %qs", 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 + { + /* 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 (pedantic && !COMPLETE_TYPE_P (type)) - pedwarn ("array type has incomplete element type"); + 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_OVERFLOW (itype)) + { + error ("size of array %qs 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"); - /* 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. */ + /* 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); + } - type = build_array_type (type, itype); - if (type_quals) - type = c_build_qualified_type (type, type_quals); + /* Complain about arrays of incomplete types. */ + if (!COMPLETE_TYPE_P (type)) + { + error ("array type has incomplete element type"); + type = error_mark_node; + } + else + type = build_array_type (type, itype); - if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; + if (size_varies) + C_TYPE_VARIABLE_SIZE (type) = 1; - /* 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; - } - else if (declarator && TREE_CODE (declarator) == INDIRECT_REF) - /* We can never complete an array type which is the target of a - pointer, so go ahead and lay it out. */ - layout_type (type); + /* The GCC extension for zero-length arrays differs from + ISO flexible array members in that sizeof yields + zero. */ + if (size && integer_zerop (size)) + { + 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); - } + 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); + } - /* Declaring a function type. - Make sure we have a valid type for the function to return. */ - if (type == error_mark_node) - continue; + /* Declaring a function type. Make sure we have a valid + type for the function to return. */ + if (type == error_mark_node) + continue; + + size_varies = 0; - size_varies = 0; + /* 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; + } - /* Warn about some types functions can't return. */ + /* 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 (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("`%s' declared as function returning a function", name); - type = integer_type_node; - } - if (TREE_CODE (type) == ARRAY_TYPE) + /* 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 if (warn_return_type) + warning ("type qualifiers ignored on function return type"); + + type = c_build_qualified_type (type, type_quals); + } + type_quals = TYPE_UNQUALIFIED; + + type = build_function_type (type, arg_types); + declarator = declarator->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. */ { - error ("`%s' declared as function returning an array", name); - type = integer_type_node; + tree link; + + for (link = arg_info->tags; + link; + link = TREE_CHAIN (link)) + TYPE_CONTEXT (TREE_VALUE (link)) = type; } + break; + } + case cdk_pointer: + { + /* Merge any constancy or volatility into the target type + for the pointer. */ - /* Construct the function type and go to the next - inner layer of declarator. */ - arg_info = TREE_OPERAND (declarator, 1); - arg_types = grokparms (arg_info, really_funcdef); - - /* 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 if (warn_return_type) - warning ("type qualifiers ignored on function return type"); - + 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; - - 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. */ + size_varies = 0; - { - tree link; + type = build_pointer_type (type); + + /* Process type qualifiers (such as const or volatile) + that were given inside the `*'. */ + type_quals = declarator->u.pointer_quals; - for (link = ARG_INFO_TAGS (arg_info); - link; - link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = type; + declarator = declarator->declarator; + break; } + default: + gcc_unreachable (); } - else if (TREE_CODE (declarator) == INDIRECT_REF) - { - /* Merge any constancy or volatility into the target type - for the pointer. */ - - 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); - - /* Process a list of type modifier keywords - (such as const or volatile) that were given inside the `*'. */ - - 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. */ + /* Now TYPE has the actual type, apart from any qualifiers in + TYPE_QUALS. */ + + /* Check the type and width of a bit-field. */ + if (bitfield) + check_bitfield_type_and_width (&type, width, orig_name); /* Did array size calculations overflow? */ @@ -4326,7 +4300,7 @@ grokdeclarator (tree declarator, tree declspecs, && COMPLETE_TYPE_P (type) && TREE_OVERFLOW (TYPE_SIZE (type))) { - error ("size of array `%s' is too large", name); + error ("size of array %qs 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; @@ -4334,21 +4308,20 @@ grokdeclarator (tree declarator, tree declspecs, /* If this is declaring a typedef name, return a TYPE_DECL. */ - if (specbits & (1 << (int) RID_TYPEDEF)) + if (storage_class == csc_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, type); - if ((specbits & (1 << (int) RID_SIGNED)) - || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) + decl = build_decl (TYPE_DECL, declarator->u.id, type); + if (declspecs->explicit_signed_p) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; decl_attributes (&decl, returned_attrs, 0); + if (declspecs->inline_p) + pedwarn ("%Jtypedef %qD declared %", decl, decl); return decl; } @@ -4372,8 +4345,10 @@ grokdeclarator (tree declarator, tree declspecs, if (decl_context == TYPENAME) { - /* Note that the grammar rejects storage classes - in typenames, fields or parameters */ + /* Note that the grammar rejects storage classes in typenames + and fields. */ + gcc_assert (storage_class == csc_none && !threadp + && !declspecs->inline_p); if (pedantic && TREE_CODE (type) == FUNCTION_TYPE && type_quals) pedwarn ("ISO C forbids const or volatile function types"); @@ -4390,13 +4365,13 @@ grokdeclarator (tree declarator, tree declspecs, a better error message can be made later. */ if (VOID_TYPE_P (type) && decl_context != PARM - && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) - && ((specbits & (1 << (int) RID_EXTERN)) + && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) + && (storage_class == csc_extern || (current_scope == file_scope - && !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))))))) + && !(storage_class == csc_static + || storage_class == csc_register))))) { - error ("variable or field `%s' declared void", name); + error ("variable or field %qs declared void", name); type = integer_type_node; } @@ -4421,45 +4396,12 @@ grokdeclarator (tree declarator, tree declspecs, if (type_quals) type = c_build_qualified_type (type, type_quals); type = build_pointer_type (type); - 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); - - 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++; - } + type_quals = array_ptr_quals; - if (erred) - error ("invalid type modifier within array declarator"); + /* We don't yet implement attributes in this context. */ + if (array_ptr_attrs != NULL_TREE) + warning ("attributes in parameter array declarator ignored"); - 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) @@ -4476,7 +4418,7 @@ grokdeclarator (tree declarator, tree declspecs, type_as_written = type; - decl = build_decl (PARM_DECL, declarator, type); + decl = build_decl (PARM_DECL, declarator->u.id, type); if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; @@ -4492,28 +4434,31 @@ grokdeclarator (tree declarator, tree declspecs, DECL_ARG_TYPE (decl) = promoted_type; DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; + if (declspecs->inline_p) + pedwarn ("%Jparameter %qD declared %", decl, decl); } 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 `%s' declared as a function", name); + error ("field %qs declared as a function", name); type = build_pointer_type (type); } else if (TREE_CODE (type) != ERROR_MARK && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type)) { - error ("field `%s' has incomplete type", name); + error ("field %qs has incomplete type", name); type = error_mark_node; } - /* 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); + type = c_build_qualified_type (type, type_quals); + decl = build_decl (FIELD_DECL, declarator->u.id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (size_varies) @@ -4521,66 +4466,75 @@ grokdeclarator (tree declarator, tree declspecs, } else if (TREE_CODE (type) == FUNCTION_TYPE) { - if (specbits & (1 << (int) RID_AUTO) - && (pedantic || current_scope == file_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 != file_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); + 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); decl = build_decl_attribute_variant (decl, decl_attr); - DECL_LANG_SPECIFIC (decl) - = GGC_CNEW (struct lang_decl); + DECL_LANG_SPECIFIC (decl) = GGC_CNEW (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 that the function does not return. */ if ((type_quals & TYPE_QUAL_VOLATILE) && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) - warning ("`noreturn' function returns non-void value"); + warning ("% 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 ((specbits & (1 << RID_AUTO)) && current_scope != file_scope) + if (storage_class == csc_auto && current_scope != file_scope) DECL_EXTERNAL (decl) = 0; else DECL_EXTERNAL (decl) = 1; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) - = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO))); + = !(storage_class == csc_static || storage_class == csc_auto); /* For a function definition, record the argument information - block in DECL_ARGUMENTS where store_parm_decls will look - for it. */ + block where store_parm_decls will look for it. */ if (funcdef_flag) - DECL_ARGUMENTS (decl) = arg_info; + current_function_arg_info = arg_info; - if (defaulted_int) + if (declspecs->default_int_p) C_FUNCTION_IMPLICIT_INT (decl) = 1; /* Record presence of `inline', if it is reasonable. */ - if (MAIN_NAME_P (declarator)) + if (flag_hosted && MAIN_NAME_P (declarator->u.id)) { - if (inlinep) - warning ("cannot inline function `main'"); + if (declspecs->inline_p) + pedwarn ("cannot inline function %"); } - else if (inlinep) + else if (declspecs->inline_p) { /* Record that the function is declared `inline'. */ DECL_DECLARED_INLINE_P (decl) = 1; @@ -4592,7 +4546,7 @@ grokdeclarator (tree declarator, tree declspecs, if (initialized) { DECL_INLINE (decl) = 1; - if (specbits & (1 << (int) RID_EXTERN)) + if (storage_class == csc_extern) current_extern_inline = 1; } } @@ -4606,19 +4560,9 @@ grokdeclarator (tree declarator, tree declspecs, { /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); + int extern_ref = !initialized && storage_class == csc_extern; - /* 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); + 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 @@ -4628,28 +4572,28 @@ grokdeclarator (tree declarator, tree declspecs, the 'extern' declaration is taken to refer to that decl.) */ if (extern_ref && current_scope != file_scope) { - tree global_decl = identifier_global_value (declarator); - tree visible_decl = lookup_name (declarator); + tree global_decl = identifier_global_value (declarator->u.id); + tree visible_decl = lookup_name (declarator->u.id); if (global_decl && global_decl != visible_decl && TREE_CODE (global_decl) == VAR_DECL && !TREE_PUBLIC (global_decl)) - error ("variable previously declared 'static' redeclared " - "'extern'"); + error ("variable previously declared % redeclared " + "%"); } - decl = build_decl (VAR_DECL, declarator, type); + decl = build_decl (VAR_DECL, declarator->u.id, type); if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; - if (inlinep) - pedwarn ("%Jvariable '%D' declared `inline'", decl, decl); + if (declspecs->inline_p) + pedwarn ("%Jvariable %qD declared %", 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) = !!(specbits & (1 << (int) RID_EXTERN)); + DECL_EXTERNAL (decl) = (storage_class == csc_extern); /* At file scope, the presence of a `static' or `register' storage class specifier, or the absence of all storage class specifiers @@ -4657,18 +4601,18 @@ grokdeclarator (tree declarator, tree declspecs, the absence of both `static' and `register' makes it public. */ if (current_scope == file_scope) { - TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) - | (1 << (int) RID_REGISTER))); + TREE_PUBLIC (decl) = !(storage_class == csc_static + || storage_class == csc_register); TREE_STATIC (decl) = !extern_ref; } /* Not at file scope, only `static' makes a static definition. */ else { - TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; + TREE_STATIC (decl) = (storage_class == csc_static); TREE_PUBLIC (decl) = extern_ref; } - if (specbits & 1 << (int) RID_THREAD) + if (threadp) { if (targetm.have_tls) DECL_THREAD_LOCAL (decl) = 1; @@ -4682,7 +4626,7 @@ grokdeclarator (tree declarator, tree declspecs, /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ - if (specbits & (1 << (int) RID_REGISTER)) + if (storage_class == csc_register) { C_DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1; @@ -4706,12 +4650,9 @@ grokdeclarator (tree declarator, tree declspecs, C_DECL_REGISTER (decl) = was_reg; } -#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. */ - if (DECL_ASSEMBLER_NAME_SET_P (decl)) - abort (); -#endif + gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)); decl_attributes (&decl, returned_attrs, 0); @@ -4729,29 +4670,29 @@ grokdeclarator (tree declarator, tree declspecs, Return a list of arg types to use in the FUNCTION_TYPE for this function. - FUNCDEF_FLAG is nonzero for a function definition, 0 for + FUNCDEF_FLAG is true for a function definition, false for a mere declaration. A nonempty identifier-list gets an error message - when FUNCDEF_FLAG is zero. */ + when FUNCDEF_FLAG is false. */ static tree -grokparms (tree arg_info, int funcdef_flag) +grokparms (struct c_arg_info *arg_info, bool funcdef_flag) { - tree arg_types = ARG_INFO_TYPES (arg_info); + tree arg_types = arg_info->types; if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag && !in_system_header) - warning ("function declaration isn't a prototype"); + warning ("function declaration isn%'t a prototype"); if (arg_types == error_mark_node) return 0; /* don't set TYPE_ARG_TYPES in this case */ else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE) { - if (! funcdef_flag) + if (!funcdef_flag) pedwarn ("parameter names (without types) in function declaration"); - ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info); - ARG_INFO_TYPES (arg_info) = 0; + arg_info->parms = arg_info->types; + arg_info->types = 0; return 0; } else @@ -4759,12 +4700,16 @@ grokparms (tree arg_info, int funcdef_flag) tree parm, type, typelt; unsigned int parmno; - /* 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. */ + /* 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. */ - for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1; + for (parm = arg_info->parms, typelt = arg_types, parmno = 1; parm; parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++) { @@ -4777,7 +4722,7 @@ grokparms (tree arg_info, int funcdef_flag) if (funcdef_flag) { if (DECL_NAME (parm)) - error ("%Jparameter %u ('%D') has incomplete type", + error ("%Jparameter %u (%qD) has incomplete type", parm, parmno, parm); else error ("%Jparameter %u has incomplete type", @@ -4786,13 +4731,13 @@ grokparms (tree arg_info, int funcdef_flag) TREE_VALUE (typelt) = error_mark_node; TREE_TYPE (parm) = error_mark_node; } - else + else if (VOID_TYPE_P (type)) { if (DECL_NAME (parm)) - warning ("%Jparameter %u ('%D') has incomplete type", + warning ("%Jparameter %u (%qD) has void type", parm, parmno, parm); else - warning ("%Jparameter %u has incomplete type", + warning ("%Jparameter %u has void type", parm, parmno); } } @@ -4801,26 +4746,20 @@ grokparms (tree arg_info, int funcdef_flag) } } -/* Take apart the current scope and return a tree_list node with info - on a parameter list just parsed. This tree_list node should be - examined using the ARG_INFO_* macros, defined above: +/* Take apart the current scope and return a c_arg_info structure with + info on a parameter list just parsed. - ARG_INFO_PARMS: a list of parameter decls. - ARG_INFO_TAGS: a list of structure, union and enum tags defined. - ARG_INFO_TYPES: a list of argument types to go in the FUNCTION_TYPE. - ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration - constants) defined with the parameters. - - This tree_list node is later fed to 'grokparms' and 'store_parm_decls'. + This structure is later fed to 'grokparms' and 'store_parm_decls'. 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. */ -tree +struct c_arg_info * get_parm_info (bool ellipsis) { struct c_binding *b = current_scope->bindings; - tree arg_info = make_node (TREE_LIST); + struct c_arg_info *arg_info = XOBNEW (&parser_obstack, + struct c_arg_info); tree parms = 0; tree tags = 0; tree types = 0; @@ -4829,16 +4768,18 @@ get_parm_info (bool ellipsis) 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; + /* 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. */ -#ifdef ENABLE_CHECKING - if (b == 0) - abort (); -#endif + gcc_assert (b); /* A parameter list consisting solely of 'void' indicates that the function takes no arguments. But if the 'void' is qualified @@ -4853,13 +4794,13 @@ get_parm_info (bool ellipsis) if (TREE_THIS_VOLATILE (b->decl) || TREE_READONLY (b->decl) || C_DECL_REGISTER (b->decl)) - error ("'void' as only parameter may not be qualified"); + error ("% as only parameter may not be qualified"); /* There cannot be an ellipsis. */ if (ellipsis) - error ("'void' must be the only parameter"); + error ("% must be the only parameter"); - ARG_INFO_TYPES (arg_info) = void_list_node; + arg_info->types = void_list_node; return arg_info; } @@ -4879,22 +4820,20 @@ get_parm_info (bool ellipsis) case PARM_DECL: if (b->id) { -#ifdef ENABLE_CHECKING - if (I_SYMBOL_BINDING (b->id) != b) abort (); -#endif + gcc_assert (I_SYMBOL_BINDING (b->id) == b); I_SYMBOL_BINDING (b->id) = b->shadowed; } /* Check for forward decls that never got their actual decl. */ if (TREE_ASM_WRITTEN (decl)) - error ("%Jparameter '%D' has just a forward declaration", + error ("%Jparameter %qD has just a forward declaration", decl, 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"); + error ("% must be the only parameter"); gave_void_only_once_err = true; } } @@ -4919,9 +4858,7 @@ get_parm_info (bool ellipsis) appears in the bindings list with b->id NULL. */ if (b->id) { -#ifdef ENABLE_CHECKING - if (I_TAG_BINDING (b->id) != b) abort (); -#endif + gcc_assert (I_TAG_BINDING (b->id) == b); I_TAG_BINDING (b->id) = b->shadowed; } @@ -4935,14 +4872,14 @@ get_parm_info (bool ellipsis) { if (b->id) /* The %s will be one of 'struct', 'union', or 'enum'. */ - warning ("'%s %E' declared inside parameter list", + warning ("%<%s %E%> declared inside parameter list", keyword, b->id); else /* The %s will be one of 'struct', 'union', or 'enum'. */ warning ("anonymous %s declared inside parameter list", keyword); - if (! explained_incomplete_types) + if (!explained_incomplete_types) { warning ("its scope is only this definition or declaration," " which is probably not what you want"); @@ -4955,10 +4892,13 @@ get_parm_info (bool ellipsis) 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. */ + type itself. FUNCTION_DECLs appear when there is an implicit + function declaration in the parameter list. */ + TREE_CHAIN (decl) = others; others = decl; /* fall through */ @@ -4968,37 +4908,36 @@ get_parm_info (bool ellipsis) variable. Just throw it away. */ if (b->id) { -#ifdef ENABLE_CHECKING - if (I_SYMBOL_BINDING (b->id) != b) abort (); -#endif + gcc_assert (I_SYMBOL_BINDING (b->id) == b); I_SYMBOL_BINDING (b->id) = b->shadowed; } break; /* Other things that might be encountered. */ case LABEL_DECL: - case FUNCTION_DECL: case VAR_DECL: default: - abort (); + gcc_unreachable (); } b = free_binding_and_advance (b); } - ARG_INFO_PARMS (arg_info) = parms; - ARG_INFO_TAGS (arg_info) = tags; - ARG_INFO_TYPES (arg_info) = types; - ARG_INFO_OTHERS (arg_info) = others; + arg_info->parms = parms; + arg_info->tags = tags; + arg_info->types = types; + arg_info->others = others; return arg_info; } /* Get the struct, enum or union (CODE says which) with tag NAME. - Define the tag as a forward-reference if it is not defined. */ + Define the tag as a forward-reference if it is not defined. + Return a c_typespec structure for the type specifier. */ -tree -xref_tag (enum tree_code code, tree name) +struct c_typespec +parser_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. */ @@ -5014,8 +4953,12 @@ 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) - return ref; + { + ret.spec = ref; + return ret; + } /* If no such tag is yet defined, create a forward-reference node and record it as the "definition". @@ -5038,7 +4981,18 @@ xref_tag (enum tree_code code, tree name) pushtag (name, ref); - return 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; } /* Make sure that the tag NAME is defined *in the current scope* @@ -5057,12 +5011,21 @@ start_struct (enum tree_code code, tree name) ref = lookup_tag (code, name, 1); if (ref && TREE_CODE (ref) == code) { - if (TYPE_FIELDS (ref)) + if (TYPE_SIZE (ref)) { if (code == UNION_TYPE) - error ("redefinition of `union %s'", IDENTIFIER_POINTER (name)); + error ("redefinition of %", IDENTIFIER_POINTER (name)); + else + error ("redefinition of %", IDENTIFIER_POINTER (name)); + } + else if (C_TYPE_BEING_DEFINED (ref)) + { + if (code == UNION_TYPE) + error ("nested redefinition of %", + IDENTIFIER_POINTER (name)); else - error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name)); + error ("nested redefinition of %", + IDENTIFIER_POINTER (name)); } } else @@ -5078,7 +5041,7 @@ start_struct (enum tree_code code, tree name) return ref; } -/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) +/* Process the specs, declarator 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. @@ -5087,11 +5050,13 @@ start_struct (enum tree_code code, tree name) are ultimately passed to `build_struct' to make the RECORD_TYPE node. */ tree -grokfield (tree declarator, tree declspecs, tree width) +grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs, + tree width) { tree value; - if (declarator == NULL_TREE && width == NULL_TREE) + if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE + && width == NULL_TREE) { /* This is an unnamed decl. @@ -5112,30 +5077,33 @@ grokfield (tree declarator, tree declspecs, tree width) took this from Plan 9 or if it was an accident of implementation that took root before someone noticed the bug... */ - tree type = TREE_VALUE (declspecs); + tree type = declspecs->type; + bool type_ok = (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE); + bool ok = false; - 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 (type_ok + && (flag_ms_extensions || !declspecs->typedef_p)) { if (flag_ms_extensions) - ; /* ok */ + ok = true; else if (flag_iso) - goto warn_unnamed_field; + ok = false; else if (TYPE_NAME (type) == NULL) - ; /* ok */ + ok = true; else - goto warn_unnamed_field; + ok = false; } - else + if (!ok) { - warn_unnamed_field: - warning ("declaration does not declare anything"); + pedwarn ("declaration does not declare anything"); return NULL_TREE; } + if (pedantic) + pedwarn ("ISO C doesn%'t support unnamed structs/unions"); } - value = grokdeclarator (declarator, declspecs, FIELD, 0, + value = grokdeclarator (declarator, declspecs, FIELD, false, width ? &width : NULL); finish_decl (value, NULL_TREE, NULL_TREE); @@ -5175,7 +5143,7 @@ detect_field_duplicates (tree fieldlist) for (y = fieldlist; y != x; y = TREE_CHAIN (y)) if (DECL_NAME (y) == DECL_NAME (x)) { - error ("%Jduplicate member '%D'", x, x); + error ("%Jduplicate member %qD", x, x); DECL_NAME (x) = NULL_TREE; } } @@ -5191,7 +5159,7 @@ detect_field_duplicates (tree fieldlist) slot = htab_find_slot (htab, y, INSERT); if (*slot) { - error ("%Jduplicate member '%D'", x, x); + error ("%Jduplicate member %qD", x, x); DECL_NAME (x) = NULL_TREE; } *slot = y; @@ -5226,9 +5194,22 @@ finish_struct (tree t, tree fieldlist, tree attributes) break; if (x == 0) - pedwarn ("%s has no %s", - TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"), - fieldlist ? _("named members") : _("members")); + { + 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"); + } + } } /* Install struct as DECL_CONTEXT of each field decl. @@ -5267,11 +5248,6 @@ finish_struct (tree t, tree fieldlist, tree attributes) if (C_DECL_VARIABLE_SIZE (x)) C_TYPE_VARIABLE_SIZE (t) = 1; - /* Detect invalid nested redefinition. */ - if (TREE_TYPE (x) == t) - error ("nested redefinition of `%s'", - IDENTIFIER_POINTER (TYPE_NAME (t))); - if (DECL_INITIAL (x)) { unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1); @@ -5296,7 +5272,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; @@ -5331,8 +5307,11 @@ finish_struct (tree t, tree fieldlist, tree attributes) = tree_low_cst (DECL_INITIAL (*fieldlistp), 1); tree type = TREE_TYPE (*fieldlistp); if (width != TYPE_PRECISION (type)) - TREE_TYPE (*fieldlistp) - = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type)); + { + TREE_TYPE (*fieldlistp) + = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type)); + DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp)); + } DECL_INITIAL (*fieldlistp) = 0; } else @@ -5428,7 +5407,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) if (c_dialect_objc ()) objc_check_decl (decl); rest_of_decl_compilation (decl, toplevel, 0); - if (! toplevel) + if (!toplevel) expand_decl (decl); } } @@ -5437,6 +5416,12 @@ 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)) + add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t))); + return t; } @@ -5474,12 +5459,15 @@ start_enum (tree name) pushtag (name, enumtype); } + if (C_TYPE_BEING_DEFINED (enumtype)) + error ("nested redefinition of %", 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 %s'", IDENTIFIER_POINTER (name)); + error ("redeclaration of %", IDENTIFIER_POINTER (name)); /* Completely replace its old definition. The old enumerators remain defined, however. */ @@ -5536,6 +5524,7 @@ 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); @@ -5550,9 +5539,19 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem); TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem); - TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem); TYPE_SIZE (enumtype) = 0; + + /* If the precision of the type was specific with an attribute and it + was too small, give an error. Otherwise, use it. */ + if (TYPE_PRECISION (enumtype)) + { + if (precision > TYPE_PRECISION (enumtype)) + error ("specified mode too small for enumeral values"); + } + else + TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); + layout_type (enumtype); if (values != error_mark_node) @@ -5647,7 +5646,7 @@ build_enumerator (tree name, tree value) value = 0; else if (TREE_CODE (value) != INTEGER_CST) { - error ("enumerator value for '%E' is not an integer constant", name); + error ("enumerator value for %qE is not an integer constant", name); value = 0; } else @@ -5667,9 +5666,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'"); + pedwarn ("ISO C restricts enumerator values to range of %"); /* XXX This causes -pedantic to change the meaning of the program. Remove? -zw 2004-03-15 */ value = convert (integer_type_node, value); @@ -5709,7 +5708,8 @@ build_enumerator (tree name, tree value) yyparse to report a parse error. */ int -start_function (tree declspecs, tree declarator, tree attributes) +start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, + tree attributes) { tree decl1, old_decl; tree restype, resdecl; @@ -5726,7 +5726,7 @@ start_function (tree declspecs, tree declarator, tree attributes) error message in c_finish_bc_stmt. */ c_break_label = c_cont_label = size_zero_node; - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL); + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL); /* If the declarator is not suitable for a function definition, cause a syntax error. */ @@ -5738,7 +5738,7 @@ start_function (tree declspecs, tree declarator, tree attributes) if (DECL_DECLARED_INLINE_P (decl1) && DECL_UNINLINABLE (decl1) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1))) - warning ("%Jinline function '%D' given attribute noinline", decl1, decl1); + warning ("%Jinline function %qD given attribute noinline", decl1, decl1); announce_function (decl1); @@ -5752,18 +5752,16 @@ start_function (tree declspecs, tree declarator, tree attributes) } if (warn_about_return_type) - pedwarn_c99 ("return type defaults to `int'"); + pedwarn_c99 ("return type defaults to %"); /* Make the init_value nonzero so pushdecl knows this is not tentative. error_mark_node is replaced below (in pop_scope) 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. - But not if what we had before was a builtin function. */ + before, copy the arg type info from that prototype. */ old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope); if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE - && !DECL_BUILT_IN (old_decl) && comptypes (TREE_TYPE (TREE_TYPE (decl1)), TREE_TYPE (TREE_TYPE (old_decl))) && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) @@ -5777,32 +5775,32 @@ start_function (tree declspecs, tree declarator, tree attributes) if (warn_strict_prototypes && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 && C_DECL_ISNT_PROTOTYPE (old_decl)) - warning ("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 && TREE_PUBLIC (decl1) - && ! MAIN_NAME_P (DECL_NAME (decl1)) + && !MAIN_NAME_P (DECL_NAME (decl1)) && C_DECL_ISNT_PROTOTYPE (old_decl)) - warning ("%Jno previous prototype for '%D'", decl1, decl1); + warning ("%Jno previous prototype for %qD", 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 && TREE_USED (old_decl) && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0) - warning ("%J'%D' was used with no prototype before its definition", + warning ("%J%qD 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 ("%Jno previous declaration for '%D'", decl1, decl1); + && !MAIN_NAME_P (DECL_NAME (decl1))) + warning ("%Jno previous declaration for %qD", 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 && TREE_USED (old_decl) && C_DECL_IMPLICIT (old_decl)) - warning ("%J`%D' was used with no declaration before its definition", + warning ("%J%qD was used with no declaration before its definition", decl1, decl1); /* This is a definition, not a reference. @@ -5819,12 +5817,9 @@ start_function (tree declspecs, tree declarator, tree attributes) 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. */ - if (DECL_ASSEMBLER_NAME_SET_P (decl1)) - abort (); -#endif + gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1)); /* If #pragma weak was used, mark the decl weak now. */ if (current_scope == file_scope) @@ -5838,7 +5833,7 @@ start_function (tree declspecs, tree declarator, tree attributes) if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) != integer_type_node) - pedwarn ("%Jreturn type of '%D' is not `int'", decl1, decl1); + pedwarn ("%Jreturn type of %qD is not %", decl1, decl1); for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; args = TREE_CHAIN (args)) @@ -5853,7 +5848,7 @@ start_function (tree declspecs, tree declarator, tree attributes) { case 1: if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn ("%Jfirst argument of '%D' should be `int'", + pedwarn ("%Jfirst argument of %qD should be %", decl1, decl1); break; @@ -5862,7 +5857,7 @@ start_function (tree declspecs, tree declarator, tree attributes) || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn ("%Jsecond argument of '%D' should be 'char **'", + pedwarn ("%Jsecond argument of %qD should be %", decl1, decl1); break; @@ -5871,8 +5866,8 @@ start_function (tree declspecs, tree declarator, tree attributes) || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn ("%Jthird argument of '%D' should probably be " - "'char **'", decl1, decl1); + pedwarn ("%Jthird argument of %qD should probably be " + "%", decl1, decl1); break; } } @@ -5881,10 +5876,10 @@ start_function (tree declspecs, tree declarator, tree attributes) argument because it's only mentioned in an appendix of the standard. */ if (argct > 0 && (argct < 2 || argct > 3)) - pedwarn ("%J'%D' takes only zero or two arguments", decl1, decl1); + pedwarn ("%J%qD takes only zero or two arguments", decl1, decl1); - if (! TREE_PUBLIC (decl1)) - pedwarn ("%J'%D' is normally a non-static function", decl1, decl1); + if (!TREE_PUBLIC (decl1)) + pedwarn ("%J%qD is normally a non-static function", decl1, decl1); } /* Record the decl so that the function name is defined. @@ -5924,12 +5919,9 @@ start_function (tree declspecs, tree declarator, tree attributes) 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, tree arg_info) +store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info) { tree decl; - tree parms = ARG_INFO_PARMS (arg_info); - tree tags = ARG_INFO_TAGS (arg_info); - tree others = ARG_INFO_OTHERS (arg_info); if (current_scope->bindings) { @@ -5945,13 +5937,13 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info) (this happens when a function definition has just an ellipsis in its parameter list). */ else if (warn_traditional && !in_system_header && !current_function_scope - && ARG_INFO_TYPES (arg_info) != error_mark_node) + && arg_info->types != error_mark_node) warning ("%Jtraditional C rejects ISO C style function definitions", fndecl); /* Now make all the parameter declarations visible in the function body. We can bypass most of the grunt work of pushdecl. */ - for (decl = parms; decl; decl = TREE_CHAIN (decl)) + for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; if (DECL_NAME (decl)) @@ -5962,10 +5954,10 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info) } /* Record the parameter list in the function declaration. */ - DECL_ARGUMENTS (fndecl) = parms; + DECL_ARGUMENTS (fndecl) = arg_info->parms; /* Now make all the ancillary declarations visible, likewise. */ - for (decl = others; decl; decl = TREE_CHAIN (decl)) + for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; if (DECL_NAME (decl)) @@ -5974,7 +5966,7 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info) } /* And all the tag declarations. */ - for (decl = tags; decl; decl = TREE_CHAIN (decl)) + for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl)) if (TREE_PURPOSE (decl)) bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope, /*invisible=*/false, /*nested=*/false); @@ -5984,18 +5976,17 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info) definitions (separate parameter list and declarations). */ static void -store_parm_decls_oldstyle (tree fndecl, tree arg_info) +store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) { struct c_binding *b; tree parm, decl, last; - tree parmids = ARG_INFO_PARMS (arg_info); + tree parmids = arg_info->parms; /* 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 (b = current_scope->bindings; b; b = b->prev) - if (TREE_CODE (b->decl) == PARM_DECL && DECL_WEAK (b->decl)) - abort (); + gcc_assert (TREE_CODE (b->decl) != PARM_DECL || !DECL_WEAK (b->decl)); #endif if (warn_old_style_definition && !in_system_header) @@ -6018,12 +6009,12 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) decl = b->decl; /* If we got something other than a PARM_DECL it is an error. */ if (TREE_CODE (decl) != PARM_DECL) - error ("%J'%D' declared as a non-parameter", decl, decl); + error ("%J%qD 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 (DECL_WEAK (decl)) { - error ("%Jmultiple parameters named '%D'", decl, decl); + error ("%Jmultiple parameters named %qD", decl, decl); TREE_PURPOSE (parm) = 0; continue; } @@ -6031,7 +6022,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) an int. */ else if (VOID_TYPE_P (TREE_TYPE (decl))) { - error ("%Jparameter '%D' declared with void type", decl, decl); + error ("%Jparameter %qD declared with void type", decl, decl); TREE_TYPE (decl) = integer_type_node; DECL_ARG_TYPE (decl) = integer_type_node; layout_decl (decl, 0); @@ -6046,9 +6037,9 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) pushdecl (decl); if (flag_isoc99) - pedwarn ("%Jtype of '%D' defaults to 'int'", decl, decl); + pedwarn ("%Jtype of %qD defaults to %", decl, decl); else if (extra_warnings) - warning ("%Jtype of '%D' defaults to 'int'", decl, decl); + warning ("%Jtype of %qD defaults to %", decl, decl); } TREE_PURPOSE (parm) = decl; @@ -6064,15 +6055,16 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) if (TREE_CODE (parm) != PARM_DECL) continue; - if (!COMPLETE_TYPE_P (TREE_TYPE (parm))) + if (TREE_TYPE (parm) != error_mark_node + && !COMPLETE_TYPE_P (TREE_TYPE (parm))) { - error ("%Jparameter '%D' has incomplete type", parm, parm); + error ("%Jparameter %qD has incomplete type", parm, parm); TREE_TYPE (parm) = error_mark_node; } - if (! DECL_WEAK (parm)) + if (!DECL_WEAK (parm)) { - error ("%Jdeclaration for parameter '%D' but no such parameter", + error ("%Jdeclaration for parameter %qD but no such parameter", parm, parm); /* Pretend the parameter was not missing. @@ -6122,7 +6114,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) if (parm == 0 || type == 0 || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { - error ("number of arguments doesn't match prototype"); + error ("number of arguments doesn%'t match prototype"); error ("%Hprototype declaration", ¤t_function_prototype_locus); break; @@ -6130,8 +6122,8 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) /* 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)))) { if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == TYPE_MAIN_VARIANT (TREE_VALUE (type))) @@ -6151,15 +6143,15 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) if (pedantic) { - pedwarn ("promoted argument '%D' " - "doesn't match prototype", parm); + pedwarn ("promoted argument %qD " + "doesn%'t match prototype", parm); pedwarn ("%Hprototype declaration", ¤t_function_prototype_locus); } } else { - error ("argument '%D' doesn't match prototype", parm); + error ("argument %qD doesn%'t match prototype", parm); error ("%Hprototype declaration", ¤t_function_prototype_locus); } @@ -6197,12 +6189,22 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) will be a variant of the main variant of the original function type. */ - TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl)); + TREE_TYPE (fndecl) = build_variant_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. @@ -6214,16 +6216,18 @@ void store_parm_decls (void) { tree fndecl = current_function_decl; + bool proto; /* The argument information block for FNDECL. */ - tree arg_info = DECL_ARGUMENTS (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. */ - bool proto = ARG_INFO_TYPES (arg_info) != 0; + proto = arg_info->types != 0; if (proto) store_parm_decls_newstyle (fndecl, arg_info); @@ -6246,8 +6250,11 @@ store_parm_decls (void) DECL_SAVED_TREE (fndecl) = push_stmt_list (); /* ??? Insert the contents of the pending sizes list into the function - to be evaluated. This just changes mis-behaviour until assign_parms - phase ordering problems are resolved. */ + 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)) @@ -6261,30 +6268,21 @@ store_parm_decls (void) cfun->x_dont_save_pending_sizes_p = 1; } -/* Give FNDECL and all its nested functions to cgraph for compilation. */ +/* Handle attribute((warn_unused_result)) on FNDECL and all its nested + functions. */ static void -c_finalize (tree fndecl) +c_warn_unused_result_recursively (tree fndecl) { struct cgraph_node *cgn; /* Handle attribute((warn_unused_result)). Relies on gimple input. */ c_warn_unused_result (&DECL_SAVED_TREE (fndecl)); - /* ??? 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; - } - /* Finalize all nested functions now. */ cgn = cgraph_node (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) - c_finalize (cgn->decl); - - cgraph_finalize_function (fndecl, false); + c_warn_unused_result_recursively (cgn->decl); } /* Finish up a function declaration and compile that function @@ -6327,12 +6325,18 @@ 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 ("%Jreturn type of '%D' is not `int'", fndecl, fndecl); + pedwarn ("%Jreturn type of %qD is not %", fndecl, fndecl); } else { if (flag_isoc99) - c_finish_return (integer_zero_node); + { + tree stmt = c_finish_return (integer_zero_node); + /* 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); + } } } @@ -6383,13 +6387,23 @@ finish_function (void) until their parent function is genericized. Since finalizing requires GENERIC, delay that as well. */ - if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) + if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node + && !undef_nested_function) { if (!decl_function_context (fndecl)) { c_genericize (fndecl); - lower_nested_functions (fndecl); - c_finalize (fndecl); + c_warn_unused_result_recursively (fndecl); + + /* ??? 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; + } + + cgraph_finalize_function (fndecl, false); } else { @@ -6400,6 +6414,9 @@ finish_function (void) } } + 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. */ @@ -6417,7 +6434,7 @@ c_expand_body (tree fndecl) || DECL_INITIAL (fndecl) == error_mark_node) return; - tree_rest_of_compilation (fndecl, false); + tree_rest_of_compilation (fndecl); if (DECL_STATIC_CONSTRUCTOR (fndecl) && targetm.have_ctors_dtors) @@ -6441,7 +6458,7 @@ check_for_loop_decls (void) /* 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"); + error ("% loop initial declaration used outside C99 mode"); return; } /* C99 subclause 6.8.5 paragraph 3: @@ -6470,24 +6487,27 @@ check_for_loop_decls (void) { case VAR_DECL: if (TREE_STATIC (decl)) - error ("%Jdeclaration of static variable '%D' in 'for' loop " + error ("%Jdeclaration of static variable %qD in % loop " "initial declaration", decl, decl); else if (DECL_EXTERNAL (decl)) - error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop " + error ("%Jdeclaration of % variable %qD in % loop " "initial declaration", decl, decl); break; case RECORD_TYPE: - error ("'struct %E' declared in 'for' loop initial declaration", id); + error ("% declared in % loop initial declaration", + id); break; case UNION_TYPE: - error ("'union %E' declared in 'for' loop initial declaration", id); + error ("% declared in % loop initial declaration", + id); break; case ENUMERAL_TYPE: - error ("'enum %E' declared in 'for' loop initial declaration", id); + error ("% declared in % loop initial declaration", + id); break; default: - error ("%Jdeclaration of non-variable '%D' in 'for' loop " + error ("%Jdeclaration of non-variable %qD in % loop " "initial declaration", decl, decl); } } @@ -6507,6 +6527,7 @@ c_push_function_context (struct function *f) 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->returns_value = current_function_returns_value; p->returns_null = current_function_returns_null; p->returns_abnormally = current_function_returns_abnormally; @@ -6535,6 +6556,7 @@ c_pop_function_context (struct function *f) 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; current_function_returns_value = p->returns_value; current_function_returns_null = p->returns_null; current_function_returns_abnormally = p->returns_abnormally; @@ -6593,13 +6615,6 @@ anon_aggr_type_p (tree ARG_UNUSED (node)) return 0; } -/* Dummy function in place of callback used by C++. */ - -void -extract_interface_info (void) -{ -} - /* Return the global value of T as a symbol. */ tree @@ -6639,24 +6654,684 @@ 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 a declarator with nested attributes. TARGET is the inner + declarator to which these attributes apply. ATTRS are the + attributes. */ + +struct c_declarator * +build_attrs_declarator (tree attrs, struct c_declarator *target) +{ + struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); + ret->kind = cdk_attrs; + ret->declarator = target; + ret->u.attrs = attrs; + return ret; +} + +/* Return a declarator for a function with arguments specified by ARGS + and return type specified by TARGET. */ + +struct c_declarator * +build_function_declarator (struct c_arg_info *args, + struct c_declarator *target) +{ + struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); + ret->kind = cdk_function; + ret->declarator = target; + ret->u.arg_info = args; + return ret; +} + +/* Return a declarator for the identifier IDENT (which may be + NULL_TREE for an abstract declarator). */ + +struct c_declarator * +build_id_declarator (tree ident) +{ + struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); + ret->kind = cdk_id; + ret->declarator = 0; + ret->u.id = ident; + 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. + 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) +{ + 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; +} - We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST, - if attributes are present) and whose type is the modifier list. */ +/* Return a pointer to a structure for an empty list of declaration + specifiers. */ -tree -make_pointer_declarator (tree type_quals_attrs, tree target) +struct c_declspecs * +build_null_declspecs (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; +} + +/* Add the type qualifier QUAL to the declaration specifiers SPECS, + returning SPECS. */ + +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 %qs", IDENTIFIER_POINTER (qual)); + return specs; +} + +/* Add the type specifier TYPE to the declaration specifiers SPECS, + returning SPECS. */ + +struct c_declspecs * +declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) { - 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); + 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) + { + /* "long", "short", "signed", "unsigned" or "_Complex". */ + bool dupe = false; + switch (i) + { + case RID_LONG: + if (specs->long_long_p) + { + error ("% is too long for GCC"); + break; + } + if (specs->long_p) + { + if (specs->typespec_word == cts_double) + { + error ("both % and % in " + "declaration specifiers"); + break; + } + if (pedantic && !flag_isoc99 && !in_system_header + && warn_long_long) + pedwarn ("ISO C90 does not support %"); + specs->long_long_p = 1; + break; + } + if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_char) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else + specs->long_p = true; + break; + case RID_SHORT: + dupe = specs->short_p; + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_char) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % in " + "declaration specifiers"); + else + specs->short_p = true; + break; + case RID_SIGNED: + dupe = specs->signed_p; + if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % in " + "declaration specifiers"); + else + specs->signed_p = true; + break; + case RID_UNSIGNED: + dupe = specs->unsigned_p; + if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % 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 % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else + specs->complex_p = true; + break; + default: + gcc_unreachable (); + } + + if (dupe) + error ("duplicate %qs", IDENTIFIER_POINTER (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 % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->complex_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_void; + return specs; + case RID_BOOL: + if (specs->long_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->complex_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else + specs->typespec_word = cts_bool; + return specs; + case RID_CHAR: + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % 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 % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_float; + return specs; + case RID_DOUBLE: + if (specs->long_long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_double; + return specs; + default: + /* ObjC reserved word "id", handled below. */ + break; + } + } + } + + /* 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 + { + 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 ("%qs fails to be a typedef or built in type", + IDENTIFIER_POINTER (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; +} + +/* Add the storage class specifier or function specifier SCSPEC to the + declaration specifiers SPECS, returning SPECS. */ + +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 ("%qs is not at beginning of declaration", + IDENTIFIER_POINTER (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 %"); + else if (specs->storage_class == csc_register) + error ("%<__thread%> used with %"); + else if (specs->storage_class == csc_typedef) + error ("%<__thread%> used with %"); + 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 %"); + break; + case RID_REGISTER: + n = csc_register; + break; + case RID_STATIC: + n = csc_static; + /* Diagnose "__thread static". */ + if (specs->thread_p) + error ("%<__thread%> before %"); + 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 %qs", IDENTIFIER_POINTER (scspec)); + if (n != csc_none) + { + if (specs->storage_class != csc_none && n != specs->storage_class) + { + error ("multiple storage classes in declaration specifiers"); + } + else + { + specs->storage_class = n; + if (n != csc_extern && n != csc_static && specs->thread_p) + { + error ("%<__thread%> used with %qs", + IDENTIFIER_POINTER (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; +} + +/* 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". */ + +struct c_declspecs * +finish_declspecs (struct c_declspecs *specs) +{ + /* 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 % meaning " + "%"); + } + 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. */ + } + } + + /* 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) + { + 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; + default: + gcc_unreachable (); + } + + return specs; } /* Synthesize a function which calls all the global ctors or global @@ -6689,7 +7364,21 @@ c_write_global_declarations_1 (tree globals) /* Process the decls in the order they were written. */ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) - vec[i] = decl; + { + vec[i] = 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 ("%J%qF used but never defined", decl, decl); + TREE_NO_WARNING (decl) = 1; + } + } wrapup_global_declarations (vec, len); check_global_declarations (vec, len); @@ -6714,8 +7403,7 @@ c_write_global_declarations (void) /* Close the external scope. */ ext_block = pop_scope (); external_scope = 0; - if (current_scope) - abort (); + gcc_assert (!current_scope); /* Process all file scopes in this compilation, and the external_scope, through wrapup_global_declarations and check_global_declarations. */ @@ -6732,11 +7420,6 @@ c_write_global_declarations (void) /* We're done parsing; proceed to optimize and emit assembly. FIXME: shouldn't be the front end's responsibility to call this. */ cgraph_optimize (); - - /* Presently this has to happen after cgraph_optimize. - FIXME: shouldn't be the front end's responsibility to call this. */ - if (flag_mudflap) - mudflap_finish_file (); } #include "gt-c-decl.h"