X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-decl.c;h=ea05852396627ca6f89dbdf89c78cbecbbc2f4e2;hp=09c2755b768e10abd800d991f95a802c45ae9c36;hb=81f218ecb3acb624ea04cb97c1c5f280a6bc23e1;hpb=40c4b476ccfc54dddcb41f0b6983bd8f0e8474f8 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 09c2755b768..ea058523966 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, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -70,6 +70,16 @@ enum decl_context FIELD, /* Declaration inside struct or union */ TYPENAME}; /* Typename (inside cast or sizeof) */ +/* States indicating how grokdeclarator() should handle declspecs marked + with __attribute__((deprecated)). An object declared as + __attribute__((deprecated)) suppresses warnings of uses of other + deprecated items. */ + +enum deprecated_states { + DEPRECATED_NORMAL, + DEPRECATED_SUPPRESS +}; + /* Nonzero if we have seen an invalid cross reference to a struct, union, or enum, but not yet printed the message. */ @@ -81,18 +91,6 @@ location_t pending_invalid_xref_location; /* True means we've initialized exception handling. */ bool c_eh_initialized_p; -/* While defining an enum type, this is 1 plus the last enumerator - constant value. Note that will do not have to save this or `enum_overflow' - around nested function definition since such a definition could only - occur in an enum value expression and we don't use these variables in - that case. */ - -static tree enum_next_value; - -/* Nonzero means that there was overflow computing enum_next_value. */ - -static int enum_overflow; - /* The file and line that the prototype came from if this is an old-style definition; used for diagnostics in store_parm_decls_oldstyle. */ @@ -154,10 +152,6 @@ int current_function_returns_abnormally; static int warn_about_return_type; -/* Nonzero when starting a function declared `extern inline'. */ - -static int current_extern_inline; - /* Nonzero when the current toplevel function contains a declaration of a nested function which is never defined. */ @@ -254,7 +248,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 *) GENERIC_NEXT (&%h.generic))"))) { union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) @@ -331,6 +325,10 @@ struct c_scope GTY((chain_next ("%h.outer"))) declarations. */ BOOL_BITFIELD parm_flag : 1; + /* True if we saw [*] in this scope. Used to give an error messages + if these appears in a function definition. */ + BOOL_BITFIELD had_vla_unspec : 1; + /* True if we already complained about forward parameter decls in this scope. This prevents double warnings on foo (int a; int b; ...) */ @@ -405,17 +403,13 @@ static bool keep_next_level_flag; static bool next_is_function_body; -/* Functions called automatically at the beginning and end of execution. */ - -static GTY(()) tree static_ctors; -static GTY(()) tree static_dtors; - /* Forward declarations. */ static tree lookup_name_in_scope (tree, struct c_scope *); static tree c_make_fname_decl (tree, int); static tree grokdeclarator (const struct c_declarator *, struct c_declspecs *, - enum decl_context, bool, tree *); + enum decl_context, bool, tree *, + enum deprecated_states); static tree grokparms (struct c_arg_info *, bool); static void layout_array_type (tree); @@ -428,7 +422,7 @@ add_stmt (tree t) { enum tree_code code = TREE_CODE (t); - if (EXPR_P (t) && code != LABEL_EXPR) + if (CAN_HAVE_LOCATION_P (t) && code != LABEL_EXPR) { if (!EXPR_HAS_LOCATION (t)) SET_EXPR_LOCATION (t, input_location); @@ -444,17 +438,6 @@ add_stmt (tree t) return t; } -/* States indicating how grokdeclarator() should handle declspecs marked - with __attribute__((deprecated)). An object declared as - __attribute__((deprecated)) suppresses warnings of uses of other - deprecated items. */ - -enum deprecated_states { - DEPRECATED_NORMAL, - DEPRECATED_SUPPRESS -}; - -static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; void c_print_identifier (FILE *file, tree node, int indent) @@ -466,7 +449,7 @@ c_print_identifier (FILE *file, tree node, int indent) { tree rid = ridpointers[C_RID_CODE (node)]; indent_to (file, indent + 4); - fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"", + fprintf (file, "rid %p \"%s\"", (void *) rid, IDENTIFIER_POINTER (rid)); } } @@ -755,19 +738,15 @@ pop_scope (void) error ("label %q+D used but not defined", p); DECL_INITIAL (p) = error_mark_node; } - else if (!TREE_USED (p) && warn_unused_label) - { - if (DECL_INITIAL (p)) - warning (0, "label %q+D defined but not used", p); - else - warning (0, "label %q+D declared but not defined", p); - } + else + warn_for_unused_label (p); + /* Labels go in BLOCK_VARS. */ TREE_CHAIN (p) = BLOCK_VARS (block); BLOCK_VARS (block) = p; gcc_assert (I_LABEL_BINDING (b->id) == b); - I_LABEL_BINDING (b->id) = b->shadowed; - break; + I_LABEL_BINDING (b->id) = b->shadowed; + break; case ENUMERAL_TYPE: case UNION_TYPE: @@ -781,7 +760,7 @@ pop_scope (void) gcc_assert (I_TAG_BINDING (b->id) == b); I_TAG_BINDING (b->id) = b->shadowed; } - break; + break; case FUNCTION_DECL: /* Propagate TREE_ADDRESSABLE from nested functions to their @@ -793,21 +772,33 @@ pop_scope (void) && DECL_ABSTRACT_ORIGIN (p) != p) TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1; if (!DECL_EXTERNAL (p) - && DECL_INITIAL (p) == 0) + && !DECL_INITIAL (p) + && scope != file_scope + && scope != external_scope) { error ("nested function %q+D declared but never defined", p); undef_nested_function = true; } + /* C99 6.7.4p6: "a function with external linkage... declared + with an inline function specifier ... shall also be defined in the + same translation unit." */ + else if (DECL_DECLARED_INLINE_P (p) + && TREE_PUBLIC (p) + && !DECL_INITIAL (p) + && !flag_gnu89_inline) + pedwarn ("inline function %q+D declared but never defined", p); + goto common_symbol; case VAR_DECL: /* Warnings for unused variables. */ if (!TREE_USED (p) + && !TREE_NO_WARNING (p) && !DECL_IN_SYSTEM_HEADER (p) && DECL_NAME (p) && !DECL_ARTIFICIAL (p) && scope != file_scope - && scope != external_scope) + && scope != external_scope) warning (OPT_Wunused_variable, "unused variable %q+D", p); if (b->inner_comp) @@ -1078,8 +1069,14 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) for (;;) { - tree oldargtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs)); - tree newargtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs)); + tree oldargtype = TREE_VALUE (oldargs); + tree newargtype = TREE_VALUE (newargs); + + if (oldargtype == error_mark_node || newargtype == error_mark_node) + return false; + + oldargtype = TYPE_MAIN_VARIANT (oldargtype); + newargtype = TYPE_MAIN_VARIANT (newargtype); if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype)) break; @@ -1281,10 +1278,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* Function declarations can either be 'static' or 'extern' (no qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore - can never conflict with each other on account of linkage (6.2.2p4). - Multiple definitions are not allowed (6.9p3,5) but GCC permits - two definitions if one is 'extern inline' and one is not. The non- - extern-inline definition supersedes the extern-inline definition. */ + can never conflict with each other on account of linkage + (6.2.2p4). Multiple definitions are not allowed (6.9p3,5) but + gnu89 mode permits two definitions if one is 'extern inline' and + one is not. The non- extern-inline definition supersedes the + extern-inline definition. */ else if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -1310,16 +1308,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, { /* If both decls are in the same TU and the new declaration isn't overriding an extern inline reject the new decl. - When we handle c99 style inline rules we'll want to reject - the following: - - DECL_EXTERN_INLINE (olddecl) - && !DECL_EXTERN_INLINE (newdecl) - - if they're in the same translation unit. Until we implement - the full semantics we accept the construct. */ - if (!(DECL_EXTERN_INLINE (olddecl) - && !DECL_EXTERN_INLINE (newdecl)) + In c99, no overriding is allowed in the same translation + unit. */ + if ((!DECL_EXTERN_INLINE (olddecl) + || DECL_EXTERN_INLINE (newdecl) + || (!flag_gnu89_inline + && (!DECL_DECLARED_INLINE_P (olddecl) + || !lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (olddecl))) + && (!DECL_DECLARED_INLINE_P (newdecl) + || !lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (newdecl)))) + ) && same_translation_unit_p (newdecl, olddecl)) { error ("redefinition of %q+D", newdecl); @@ -1379,12 +1379,36 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, warned = true; } } + + /* Make sure gnu_inline attribute is either not present, or + present on all inline decls. */ + if (DECL_DECLARED_INLINE_P (olddecl) + && DECL_DECLARED_INLINE_P (newdecl)) + { + bool newa = lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (newdecl)) != NULL; + bool olda = lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (olddecl)) != NULL; + if (newa != olda) + { + error ("% attribute present on %q+D", + newa ? newdecl : olddecl); + error ("%Jbut not here", newa ? olddecl : newdecl); + } + } } else if (TREE_CODE (newdecl) == VAR_DECL) { /* Only variables can be thread-local, and all declarations must agree on this property. */ - if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)) + if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl)) + { + /* Nothing to check. Since OLDDECL is marked threadprivate + and NEWDECL does not have a thread-local attribute, we + will merge the threadprivate attribute into NEWDECL. */ + ; + } + else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)) { if (DECL_THREAD_LOCAL_P (newdecl)) error ("thread-local declaration of %q+D follows " @@ -1472,7 +1496,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* warnings */ /* All decls must agree on a visibility. */ - if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS) + if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS) && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl) && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) { @@ -1503,9 +1527,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ??? Should we still warn about this now we have unit-at-a-time mode and can get it right? Definitely don't complain if the decls are in different translation - units. */ + units. + C99 permits this, so don't warn in that case. (The function + may not be inlined everywhere in function-at-a-time mode, but + we still shouldn't warn.) */ if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl) - && same_translation_unit_p (olddecl, newdecl)) + && same_translation_unit_p (olddecl, newdecl) + && flag_gnu89_inline) { if (TREE_USED (olddecl)) { @@ -1555,7 +1583,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl)) /* Don't warn about forward parameter decls. */ && !(TREE_CODE (newdecl) == PARM_DECL - && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))) + && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)) + /* Don't warn about a variable definition following a declaration. */ + && !(TREE_CODE (newdecl) == VAR_DECL + && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))) { warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D", newdecl); @@ -1579,12 +1610,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, static void merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) { - int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_INITIAL (newdecl) != 0); - int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0); - int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0); + bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_INITIAL (newdecl) != 0); + bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL + && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0); + bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL + && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0); + bool extern_changed = false; /* For real parm decl following a forward decl, rechain the old decl in its new location and clear TREE_ASM_WRITTEN (it's not a @@ -1646,11 +1678,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) - { - TREE_THIS_VOLATILE (olddecl) = 1; - if (TREE_CODE (newdecl) == VAR_DECL) - make_var_volatile (newdecl); - } + TREE_THIS_VOLATILE (olddecl) = 1; /* Merge deprecatedness. */ if (TREE_DEPRECATED (newdecl)) @@ -1664,164 +1692,187 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) && !C_DECL_BUILTIN_PROTOTYPE (olddecl))) DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl); - /* Merge the unused-warning information. */ - if (DECL_IN_SYSTEM_HEADER (olddecl)) - DECL_IN_SYSTEM_HEADER (newdecl) = 1; - else if (DECL_IN_SYSTEM_HEADER (newdecl)) - DECL_IN_SYSTEM_HEADER (olddecl) = 1; - /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == 0) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)) - { - /* Merge the section attribute. - We want to issue an error if the sections conflict but that must be - done later in decl_attributes since we are called before attributes - are assigned. */ - if (DECL_SECTION_NAME (newdecl) == NULL_TREE) - DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); - - /* Copy the assembler name. - Currently, it can only be defined in the prototype. */ - COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); - - /* Use visibility of whichever declaration had it specified */ - if (DECL_VISIBILITY_SPECIFIED (olddecl)) - { - DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); - DECL_VISIBILITY_SPECIFIED (newdecl) = 1; - } - - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); - DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); - DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); - DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) - |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); - TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); - TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); - DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); - DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl); - DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl); - } - - /* Merge the storage class information. */ - merge_weak (newdecl, olddecl); + /* Merge the threadprivate attribute. */ + if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl)) + { + DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl); + C_DECL_THREADPRIVATE_P (newdecl) = 1; + } - /* For functions, static overrides non-static. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); - /* This is since we don't automatically - copy the attributes of NEWDECL into OLDDECL. */ - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - /* If this clears `static', clear it in the identifier too. */ - if (!TREE_PUBLIC (olddecl)) - TREE_PUBLIC (DECL_NAME (olddecl)) = 0; - } - } - - if (DECL_EXTERNAL (newdecl)) - { - TREE_STATIC (newdecl) = TREE_STATIC (olddecl); - DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); - - /* An extern decl does not override previous storage class. */ - TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); - if (!DECL_EXTERNAL (newdecl)) - { - DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); - DECL_COMMON (newdecl) = DECL_COMMON (olddecl); - } - } - else - { - TREE_STATIC (olddecl) = TREE_STATIC (newdecl); - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - } - - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - /* If we're redefining a function previously defined as extern - inline, make sure we emit debug info for the inline before we - throw it away, in case it was inlined into a function that hasn't - been written out yet. */ - if (new_is_definition && DECL_INITIAL (olddecl)) - { - if (TREE_USED (olddecl) - /* In unit-at-a-time mode we never inline re-defined extern - inline functions. */ - && !flag_unit_at_a_time - && cgraph_function_possibly_inlined_p (olddecl)) - (*debug_hooks->outlining_inline_function) (olddecl); - - /* The new defn must not be inline. */ - DECL_INLINE (newdecl) = 0; - DECL_UNINLINABLE (newdecl) = 1; - } - else - { - /* If either decl says `inline', this fn is inline, - unless its definition was passed already. */ - if (DECL_DECLARED_INLINE_P (newdecl) - || DECL_DECLARED_INLINE_P (olddecl)) - DECL_DECLARED_INLINE_P (newdecl) = 1; - - DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl) - = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)); - } + if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)) + { + /* Merge the unused-warning information. */ + if (DECL_IN_SYSTEM_HEADER (olddecl)) + DECL_IN_SYSTEM_HEADER (newdecl) = 1; + else if (DECL_IN_SYSTEM_HEADER (newdecl)) + DECL_IN_SYSTEM_HEADER (olddecl) = 1; - if (DECL_BUILT_IN (olddecl)) - { - /* If redeclaring a builtin function, it stays built in. - But it gets tagged as having been declared. */ - DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); - C_DECL_DECLARED_BUILTIN (newdecl) = 1; - if (new_is_prototype) - C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0; - else - C_DECL_BUILTIN_PROTOTYPE (newdecl) - = C_DECL_BUILTIN_PROTOTYPE (olddecl); - } + /* Merge the section attribute. + We want to issue an error if the sections conflict but that + must be done later in decl_attributes since we are called + before attributes are assigned. */ + if (DECL_SECTION_NAME (newdecl) == NULL_TREE) + DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); - /* Also preserve various other info from the definition. */ - if (!new_is_definition) - { - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); - DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); - DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); - - /* Set DECL_INLINE on the declaration if we've got a body - from which to instantiate. */ - if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl)) - { - DECL_INLINE (newdecl) = 1; - DECL_ABSTRACT_ORIGIN (newdecl) - = DECL_ABSTRACT_ORIGIN (olddecl); - } - } - else - { - /* If a previous declaration said inline, mark the - definition as inlinable. */ - if (DECL_DECLARED_INLINE_P (newdecl) - && !DECL_UNINLINABLE (newdecl)) - DECL_INLINE (newdecl) = 1; - } - } - - /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. + /* Copy the assembler name. + Currently, it can only be defined in the prototype. */ + COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); + + /* Use visibility of whichever declaration had it specified */ + if (DECL_VISIBILITY_SPECIFIED (olddecl)) + { + DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); + DECL_VISIBILITY_SPECIFIED (newdecl) = 1; + } + + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); + DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); + DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); + DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) + |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); + TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); + TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); + DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); + DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl); + DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl); + } + + /* Merge the storage class information. */ + merge_weak (newdecl, olddecl); + + /* For functions, static overrides non-static. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); + /* This is since we don't automatically + copy the attributes of NEWDECL into OLDDECL. */ + TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); + /* If this clears `static', clear it in the identifier too. */ + if (!TREE_PUBLIC (olddecl)) + TREE_PUBLIC (DECL_NAME (olddecl)) = 0; + } + } + + /* In c99, 'extern' declaration before (or after) 'inline' means this + function is not DECL_EXTERNAL, unless 'gnu_inline' attribute + is present. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL + && !flag_gnu89_inline + && (DECL_DECLARED_INLINE_P (newdecl) + || DECL_DECLARED_INLINE_P (olddecl)) + && (!DECL_DECLARED_INLINE_P (newdecl) + || !DECL_DECLARED_INLINE_P (olddecl) + || !DECL_EXTERNAL (olddecl)) + && DECL_EXTERNAL (newdecl) + && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl))) + DECL_EXTERNAL (newdecl) = 0; + + if (DECL_EXTERNAL (newdecl)) + { + TREE_STATIC (newdecl) = TREE_STATIC (olddecl); + DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); + + /* An extern decl does not override previous storage class. */ + TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); + if (!DECL_EXTERNAL (newdecl)) + { + DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); + DECL_COMMON (newdecl) = DECL_COMMON (olddecl); + } + } + else + { + TREE_STATIC (olddecl) = TREE_STATIC (newdecl); + TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); + } + + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + /* If we're redefining a function previously defined as extern + inline, make sure we emit debug info for the inline before we + throw it away, in case it was inlined into a function that + hasn't been written out yet. */ + if (new_is_definition && DECL_INITIAL (olddecl)) + { + if (TREE_USED (olddecl) + /* In unit-at-a-time mode we never inline re-defined extern + inline functions. */ + && !flag_unit_at_a_time + && cgraph_function_possibly_inlined_p (olddecl)) + (*debug_hooks->outlining_inline_function) (olddecl); + + /* The new defn must not be inline. */ + DECL_INLINE (newdecl) = 0; + DECL_UNINLINABLE (newdecl) = 1; + } + else + { + /* If either decl says `inline', this fn is inline, unless + its definition was passed already. */ + if (DECL_DECLARED_INLINE_P (newdecl) + || DECL_DECLARED_INLINE_P (olddecl)) + DECL_DECLARED_INLINE_P (newdecl) = 1; + + DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl) + = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)); + } + + if (DECL_BUILT_IN (olddecl)) + { + /* If redeclaring a builtin function, it stays built in. + But it gets tagged as having been declared. */ + DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + C_DECL_DECLARED_BUILTIN (newdecl) = 1; + if (new_is_prototype) + C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0; + else + C_DECL_BUILTIN_PROTOTYPE (newdecl) + = C_DECL_BUILTIN_PROTOTYPE (olddecl); + } + + /* Also preserve various other info from the definition. */ + if (!new_is_definition) + { + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); + DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); + DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + + /* Set DECL_INLINE on the declaration if we've got a body + from which to instantiate. */ + if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl)) + { + DECL_INLINE (newdecl) = 1; + DECL_ABSTRACT_ORIGIN (newdecl) + = DECL_ABSTRACT_ORIGIN (olddecl); + } + } + else + { + /* If a previous declaration said inline, mark the + definition as inlinable. */ + if (DECL_DECLARED_INLINE_P (newdecl) + && !DECL_UNINLINABLE (newdecl)) + DECL_INLINE (newdecl) = 1; + } + } + + extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl); + + /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */ { unsigned olddecl_uid = DECL_UID (olddecl); tree olddecl_context = DECL_CONTEXT (olddecl); - + memcpy ((char *) olddecl + sizeof (struct tree_common), (char *) newdecl + sizeof (struct tree_common), sizeof (struct tree_decl_common) - sizeof (struct tree_common)); @@ -1841,7 +1892,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) break; default: - + memcpy ((char *) olddecl + sizeof (struct tree_decl_common), (char *) newdecl + sizeof (struct tree_decl_common), sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common)); @@ -1858,6 +1909,13 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) || (TREE_CODE (olddecl) == VAR_DECL && TREE_STATIC (olddecl)))) make_decl_rtl (olddecl); + + /* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL, + and the definition is coming from the old version, cgraph needs + to be called again. */ + if (extern_changed && !new_is_definition + && TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl)) + cgraph_finalize_function (olddecl, false); } /* Handle when a new declaration NEWDECL has the same name as an old @@ -1873,7 +1931,11 @@ duplicate_decls (tree newdecl, tree olddecl) tree newtype = NULL, oldtype = NULL; if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype)) - return false; + { + /* Avoid `unused variable' and other warnings warnings for OLDDECL. */ + TREE_NO_WARNING (olddecl) = 1; + return false; + } merge_decls (newdecl, olddecl, newtype, oldtype); return true; @@ -1946,7 +2008,7 @@ warn_if_shadowing (tree new_decl) translation and get back the corresponding typedef name. For example, given: - typedef struct S MY_TYPE; + typedef struct S MY_TYPE; MY_TYPE object; Later parts of the compiler might only know that `object' was of @@ -2283,18 +2345,16 @@ pushdecl_top_level (tree x) static void implicit_decl_warning (tree id, tree olddecl) { - void (*diag) (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2); - switch (mesg_implicit_function_declaration) + if (warn_implicit_function_declaration) { - case 0: return; - case 1: diag = warning0; break; - case 2: diag = error; break; - default: gcc_unreachable (); + if (flag_isoc99) + pedwarn (G_("implicit declaration of function %qE"), id); + else + warning (OPT_Wimplicit_function_declaration, + G_("implicit declaration of function %qE"), id); + if (olddecl) + locate_old_decl (olddecl, inform); } - - diag (G_("implicit declaration of function %qE"), id); - if (olddecl) - locate_old_decl (olddecl, diag); } /* Generate an implicit declaration for identifier FUNCTIONID as a @@ -2430,7 +2490,7 @@ undeclared_variable (tree id, location_t loc) } /* If we are parsing old-style parameter decls, current_function_decl - will be nonnull but current_function_scope will be null. */ + will be nonnull but current_function_scope will be null. */ scope = current_function_scope ? current_function_scope : current_scope; } bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false); @@ -2569,7 +2629,7 @@ define_label (location_t location, tree name) if (!in_system_header && lookup_name (name)) warning (OPT_Wtraditional, "%Htraditional C lacks a separate namespace " - "for labels, identifier %qE conflicts", &location, name); + "for labels, identifier %qE conflicts", &location, name); nlist_se = XOBNEW (&parser_obstack, struct c_label_list); nlist_se->next = label_context_stack_se->labels_def; @@ -2644,7 +2704,7 @@ pending_xref_error (void) { if (pending_invalid_xref != 0) error ("%H%qE defined as wrong kind of tag", - &pending_invalid_xref_location, pending_invalid_xref); + &pending_invalid_xref_location, pending_invalid_xref); pending_invalid_xref = 0; } @@ -2759,7 +2819,16 @@ c_make_fname_decl (tree id, int type_dep) TREE_USED (decl) = 1; - if (current_function_decl) + if (current_function_decl + /* For invalid programs like this: + + void foo() + const char* p = __FUNCTION__; + + the __FUNCTION__ is believed to appear in K&R style function + parameter declarator. In that case we still don't have + function_scope. */ + && (!errorcount || current_function_scope)) { DECL_CONTEXT (decl) = current_function_decl; bind (id, decl, current_function_scope, @@ -2771,30 +2840,15 @@ c_make_fname_decl (tree id, int type_dep) return decl; } -/* Return a definition for a builtin function named NAME and whose data type - is TYPE. TYPE should be a function type with argument types. - FUNCTION_CODE tells later passes how to compile calls to this function. - See tree.h for its possible values. - - If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, - the name to be called if we can't opencode the function. If - ATTRS is nonzero, use that for the function's attribute list. */ - tree -builtin_function (const char *name, tree type, int function_code, - enum built_in_class cl, const char *library_name, - tree attrs) +c_builtin_function (tree decl) { - tree id = get_identifier (name); - tree decl = build_decl (FUNCTION_DECL, id, type); - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; + tree type = TREE_TYPE (decl); + tree id = DECL_NAME (decl); + + const char *name = IDENTIFIER_POINTER (id); DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl); - DECL_BUILT_IN_CLASS (decl) = cl; - DECL_FUNCTION_CODE (decl) = function_code; C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0); - if (library_name) - SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); /* Should never be called on a symbol with a preexisting meaning. */ gcc_assert (!I_SYMBOL_BINDING (id)); @@ -2809,12 +2863,6 @@ builtin_function (const char *name, tree type, int function_code, visible_builtins = decl; } - /* Possibly apply some default attributes to this built-in function. */ - if (attrs) - decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN); - else - decl_attributes (&decl, NULL_TREE, 0); - return decl; } @@ -2985,14 +3033,14 @@ quals_from_declspecs (const struct c_declspecs *specs) return quals; } -/* Construct an array declarator. EXPR is the expression inside [], or - NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied - to the pointer to which a parameter array is converted). STATIC_P is - true if "static" is inside the [], false otherwise. VLA_UNSPEC_P - is true if the array is [*], a VLA of unspecified length which is - nevertheless a complete type (not currently implemented by GCC), - false otherwise. The field for the contained declarator is left to be - filled in by set_array_declarator_inner. */ +/* Construct an array declarator. EXPR is the expression inside [], + or NULL_TREE. QUALS are the type qualifiers inside the [] (to be + applied to the pointer to which a parameter array is converted). + STATIC_P is true if "static" is inside the [], false otherwise. + VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified + length which is nevertheless a complete type, false otherwise. The + field for the contained declarator is left to be filled in by + set_array_declarator_inner. */ struct c_declarator * build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, @@ -3024,7 +3072,16 @@ build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, pedwarn ("ISO C90 does not support %<[*]%> array declarators"); } if (vla_unspec_p) - warning (0, "GCC does not yet properly implement %<[*]%> array declarators"); + { + if (!current_scope->parm_flag) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + declarator->u.array.vla_unspec_p = false; + return NULL; + } + current_scope->had_vla_unspec = true; + } return declarator; } @@ -3046,6 +3103,33 @@ set_array_declarator_inner (struct c_declarator *decl, error ("static or type qualifiers in abstract declarator"); return decl; } + +/* INIT is a constructor that forms DECL's initializer. If the final + element initializes a flexible array field, add the size of that + initializer to DECL's size. */ + +static void +add_flexible_array_elts_to_size (tree decl, tree init) +{ + tree elt, type; + + if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))) + return; + + elt = VEC_last (constructor_elt, CONSTRUCTOR_ELTS (init))->value; + type = TREE_TYPE (elt); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + { + complete_array_type (&type, elt, false); + DECL_SIZE (decl) + = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type)); + DECL_SIZE_UNIT (decl) + = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type)); + } +} /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ @@ -3058,7 +3142,7 @@ groktypename (struct c_type_name *type_name) type_name->specs->attrs = NULL_TREE; type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME, - false, NULL); + false, NULL, DEPRECATED_NORMAL); /* Apply attributes. */ decl_attributes (&type, attrs, 0); @@ -3087,6 +3171,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, { tree decl; tree tem; + enum deprecated_states deprecated_state = DEPRECATED_NORMAL; /* An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ @@ -3094,12 +3179,11 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, deprecated_state = DEPRECATED_SUPPRESS; decl = grokdeclarator (declarator, declspecs, - NORMAL, initialized, NULL); + NORMAL, initialized, NULL, + deprecated_state); if (!decl) return 0; - deprecated_state = DEPRECATED_NORMAL; - if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))) warning (OPT_Wmain, "%q+D is usually a function", decl); @@ -3199,6 +3283,18 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, /* Set attributes here so if duplicate decl, will have proper attributes. */ decl_attributes (&decl, attributes, 0); + /* Handle gnu_inline attribute. */ + if (declspecs->inline_p + && !flag_gnu89_inline + && TREE_CODE (decl) == FUNCTION_DECL + && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))) + { + if (declspecs->storage_class == csc_auto && current_scope != file_scope) + ; + else if (declspecs->storage_class != csc_static) + DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl); + } + if (TREE_CODE (decl) == FUNCTION_DECL && targetm.calls.promote_prototypes (TREE_TYPE (decl))) { @@ -3226,6 +3322,17 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, warning (OPT_Wattributes, "inline function %q+D given attribute noinline", decl); + /* C99 6.7.4p3: An inline definition of a function with external + linkage shall not contain a definition of a modifiable object + with static storage duration... */ + if (TREE_CODE (decl) == VAR_DECL + && current_scope != file_scope + && TREE_STATIC (decl) + && DECL_DECLARED_INLINE_P (current_function_decl) + && DECL_EXTERNAL (current_function_decl)) + pedwarn ("%q+D is static but declared in inline function %qD " + "which is not static", decl, current_function_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); @@ -3239,6 +3346,23 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, return tem; } +/* Initialize EH if not initialized yet and exceptions are enabled. */ + +void +c_maybe_initialize_eh (void) +{ + if (!flag_exceptions || c_eh_initialized_p) + return; + + c_eh_initialized_p = true; + eh_personality_libfunc + = init_one_libfunc (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + default_init_unwind_resume_libfunc (); + using_eh_for_cleanups (); +} + /* Finish processing of a declaration; install its initial value. If the length of an array type is not known before, @@ -3247,7 +3371,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, void finish_decl (tree decl, tree init, tree asmspec_tree) { - tree type = TREE_TYPE (decl); + tree type; int was_incomplete = (DECL_SIZE (decl) == 0); const char *asmspec = 0; @@ -3274,6 +3398,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree) || TREE_CODE (decl) == FIELD_DECL)) objc_check_decl (decl); + type = TREE_TYPE (decl); + /* Deduce size of array from initialization, if not already known. */ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0 @@ -3345,6 +3471,9 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (TREE_CODE (decl) == VAR_DECL) { + if (init && TREE_CODE (init) == CONSTRUCTOR) + add_flexible_array_elts_to_size (decl, init); + if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node && COMPLETE_TYPE_P (TREE_TYPE (decl))) layout_decl (decl, 0); @@ -3394,23 +3523,21 @@ finish_decl (tree decl, tree init, tree asmspec_tree) /* If #pragma weak was used, mark the decl weak now. */ maybe_apply_pragma_weak (decl); - /* If this is a variable definition, determine its ELF visibility. */ - if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) - && !DECL_EXTERNAL (decl)) - c_determine_visibility (decl); - /* Output the assembler code and/or RTL code for variables and functions, unless the type is an undefined structure or union. If not, it will get done when the type is completed. */ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) { + /* Determine the ELF visibility. */ + if (TREE_PUBLIC (decl)) + c_determine_visibility (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ if (c_dialect_objc ()) objc_check_decl (decl); - if (asmspec) + if (asmspec) { /* If this is not a static variable, issue a warning. It doesn't make any sense to give an ASMSPEC for an @@ -3423,12 +3550,10 @@ finish_decl (tree decl, tree init, tree asmspec_tree) && !TREE_STATIC (decl)) warning (0, "ignoring asm-specifier for non-static local " "variable %q+D", decl); - else if (C_DECL_REGISTER (decl)) - change_decl_assembler_name (decl, get_identifier (asmspec)); else set_user_assembler_name (decl, asmspec); } - + if (DECL_FILE_SCOPE_P (decl)) { if (DECL_INITIAL (decl) == NULL_TREE @@ -3474,7 +3599,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) add_stmt (build_stmt (DECL_EXPR, decl)); } } - + if (!DECL_FILE_SCOPE_P (decl)) { @@ -3493,7 +3618,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) } /* If this was marked 'used', be sure it will be output. */ - if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) + if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl))) mark_decl_referenced (decl); if (TREE_CODE (decl) == TYPE_DECL) @@ -3531,16 +3656,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) TREE_USED (cleanup_decl) = 1; /* Initialize EH, if we've been told to do so. */ - if (flag_exceptions && !c_eh_initialized_p) - { - c_eh_initialized_p = true; - eh_personality_libfunc - = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcc_personality_sj0" - : "__gcc_personality_v0"); - default_init_unwind_resume_libfunc (); - using_eh_for_cleanups (); - } + c_maybe_initialize_eh (); push_cleanup (decl, cleanup, false); } @@ -3553,7 +3669,7 @@ tree grokparm (const struct c_parm *parm) { tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, - NULL); + NULL, DEPRECATED_NORMAL); decl_attributes (&decl, parm->attrs, 0); @@ -3568,7 +3684,8 @@ push_parm_decl (const struct c_parm *parm) { tree decl; - decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL); + decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL, + DEPRECATED_NORMAL); decl_attributes (&decl, parm->attrs, 0); decl = pushdecl (decl); @@ -3595,8 +3712,6 @@ mark_forward_parm_decls (void) TREE_ASM_WRITTEN (b->decl) = 1; } -static GTY(()) int compound_literal_number; - /* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound literal, which may be an incomplete array type completed by the initializer; INIT is a CONSTRUCTOR that initializes the compound @@ -3646,14 +3761,8 @@ build_compound_literal (tree type, tree init) if (TREE_STATIC (decl)) { - /* This decl needs a name for the assembler output. We also need - a unique suffix to be added to the name. */ - char *name; - - ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", - compound_literal_number); - compound_literal_number++; - DECL_NAME (decl) = get_identifier (name); + /* This decl needs a name for the assembler output. */ + set_compound_literal_name (decl); DECL_DEFER_OUTPUT (decl) = 1; DECL_COMDAT (decl) = 1; DECL_ARTIFICIAL (decl) = 1; @@ -3742,6 +3851,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) type_mv = TYPE_MAIN_VARIANT (*type); if (pedantic + && !in_system_header && type_mv != integer_type_node && type_mv != unsigned_type_node && type_mv != boolean_type_node) @@ -3765,36 +3875,68 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) { struct lang_type *lt = TYPE_LANG_SPECIFIC (*type); if (!lt - || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type)) + || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type)) || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type))) warning (0, "%qs is narrower than values of its type", name); } } -/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */ -static tree -c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp) + + +/* Print warning about variable length array if necessary. */ + +static void +warn_variable_length_array (const char *name, tree size) { - /* Extended integer types of the same width as a standard type have - lesser rank, so those of the same width as int promote to int or - unsigned int and are valid for printf formats expecting int or - unsigned int. To avoid such special cases, avoid creating - extended integer types for bit-fields if a standard integer type - is available. */ - if (width == TYPE_PRECISION (integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - if (width == TYPE_PRECISION (signed_char_type_node)) - return unsignedp ? unsigned_char_type_node : signed_char_type_node; - if (width == TYPE_PRECISION (short_integer_type_node)) - return unsignedp ? short_unsigned_type_node : short_integer_type_node; - if (width == TYPE_PRECISION (long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - if (width == TYPE_PRECISION (long_long_integer_type_node)) - return (unsignedp ? long_long_unsigned_type_node - : long_long_integer_type_node); - return build_nonstandard_integer_type (width, unsignedp); + int ped = !flag_isoc99 && pedantic && warn_vla != 0; + int const_size = TREE_CONSTANT (size); + + if (ped) + { + if (const_size) + { + if (name) + pedwarn ("ISO C90 forbids array %qs whose size " + "can%'t be evaluated", + name); + else + pedwarn ("ISO C90 forbids array whose size " + "can%'t be evaluated"); + } + else + { + if (name) + pedwarn ("ISO C90 forbids variable length array %qs", + name); + else + pedwarn ("ISO C90 forbids variable length array"); + } + } + else if (warn_vla > 0) + { + if (const_size) + { + if (name) + warning (OPT_Wvla, + "the size of array %qs can" + "%'t be evaluated", name); + else + warning (OPT_Wvla, + "the size of array can %'t be evaluated"); + } + else + { + if (name) + warning (OPT_Wvla, + "variable length array %qs is used", + name); + else + warning (OPT_Wvla, + "variable length array is used"); + } + } } - + /* Given declspecs and a declarator, determine the name and type of the object declared and construct a ..._DECL node for it. @@ -3816,6 +3958,8 @@ c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp) 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. + DEPRECATED_STATE is a deprecated_states value indicating whether + deprecation warnings should be suppressed. In the TYPENAME case, DECLARATOR is really an absolute declarator. It may also be so in the PARM case, for a prototype where the @@ -3827,7 +3971,8 @@ c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp) static tree grokdeclarator (const struct c_declarator *declarator, struct c_declspecs *declspecs, - enum decl_context decl_context, bool initialized, tree *width) + enum decl_context decl_context, bool initialized, tree *width, + enum deprecated_states deprecated_state) { tree type = declspecs->type; bool threadp = declspecs->thread_p; @@ -3838,20 +3983,21 @@ grokdeclarator (const struct c_declarator *declarator, int type_quals = TYPE_UNQUALIFIED; const char *name, *orig_name; tree typedef_type = 0; - int funcdef_flag = 0; + bool funcdef_flag = false; bool funcdef_syntax = false; int size_varies = 0; tree decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; int array_parm_static = 0; + bool array_parm_vla_unspec_p = false; tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; struct c_arg_info *arg_info = 0; if (decl_context == FUNCDEF) - funcdef_flag = 1, decl_context = NORMAL; + funcdef_flag = true, decl_context = NORMAL; /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ @@ -3902,6 +4048,14 @@ grokdeclarator (const struct c_declarator *declarator, if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS) warn_deprecated_use (declspecs->type); + if ((decl_context == NORMAL || decl_context == FIELD) + && current_scope == file_scope + && variably_modified_type_p (type, NULL_TREE)) + { + error ("variably modified %qs at file scope", name); + type = integer_type_node; + } + typedef_type = type; size_varies = C_TYPE_VARIABLE_SIZE (type); @@ -3924,7 +4078,7 @@ grokdeclarator (const struct c_declarator *declarator, "signed". */ if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p && TREE_CODE (type) == INTEGER_TYPE) - type = c_common_unsigned_type (type); + type = unsigned_type_for (type); /* Figure out the type qualifiers for the declaration. There are two ways a declaration can become qualified. One is something @@ -4008,8 +4162,13 @@ grokdeclarator (const struct c_declarator *declarator, && !funcdef_flag) { /* 'extern' with initialization is invalid if not at file scope. */ - if (current_scope == file_scope) - warning (0, "%qs initialized and declared %", name); + if (current_scope == file_scope) + { + /* It is fine to have 'extern const' when compiling at C + and C++ intersection. */ + if (!(warn_cxx_compat && constp)) + warning (0, "%qs initialized and declared %", name); + } else error ("%qs has both % and initializer", name); } @@ -4112,29 +4271,30 @@ grokdeclarator (const struct c_declarator *declarator, array_ptr_quals = declarator->u.array.quals; array_ptr_attrs = declarator->u.array.attrs; array_parm_static = declarator->u.array.static_p; - + array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; + 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 (type == error_mark_node) continue; @@ -4147,16 +4307,16 @@ grokdeclarator (const struct c_declarator *declarator, /* 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); @@ -4166,31 +4326,27 @@ grokdeclarator (const struct c_declarator *declarator, size = integer_one_node; } } + else if ((decl_context == NORMAL || decl_context == FIELD) + && current_scope == file_scope) + { + error ("variably modified %qs at file scope", name); + size = integer_one_node; + } else { /* Make sure the array size remains visibly nonconstant even if it is (eg) a const variable with known value. */ size_varies = 1; - - if (!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); - } + warn_variable_length_array (orig_name, size); } 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. */ + /* 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 @@ -4210,7 +4366,7 @@ grokdeclarator (const struct c_declarator *declarator, convert (index_type, size_one_node)); - /* If that overflowed, the array is too big. ??? + /* 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 @@ -4224,7 +4380,7 @@ grokdeclarator (const struct c_declarator *declarator, type = error_mark_node; continue; } - + itype = build_index_type (itype); } } @@ -4237,26 +4393,79 @@ grokdeclarator (const struct c_declarator *declarator, identical to GCC's zero-length array extension. */ itype = build_range_type (sizetype, size_zero_node, NULL_TREE); } + else if (decl_context == PARM) + { + if (array_parm_vla_unspec_p) + { + if (! orig_name) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than a declaration"); + } + + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + size_varies = 1; + } + } + else if (decl_context == TYPENAME) + { + if (array_parm_vla_unspec_p) + { + /* The error is printed elsewhere. We use this to + avoid messing up with incomplete array types of + the same type, that would otherwise be modified + below. */ + itype = build_range_type (sizetype, size_zero_node, + NULL_TREE); + } + } /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) { error ("array type has incomplete element type"); - type = error_mark_node; + type = error_mark_node; } else + /* When itype is NULL, a shared incomplete array type is + returned for all array of a given type. Elsewhere we + make sure we don't complete that type before copying + it, but here we want to make sure we don't ever + modify the shared type, so we gcc_assert (itype) + below. */ type = build_array_type (type, itype); - if (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)) + if (type != error_mark_node) { - TYPE_SIZE (type) = bitsize_zero_node; - TYPE_SIZE_UNIT (type) = size_zero_node; + if (size_varies) + { + /* It is ok to modify type here even if itype is + NULL: if size_varies, we're in a + multi-dimensional array and the inner type has + variable size, so the enclosing shared array type + must too. */ + if (size && TREE_CODE (size) == INTEGER_CST) + type + = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + C_TYPE_VARIABLE_SIZE (type) = 1; + } + + /* The GCC extension for zero-length arrays differs from + ISO flexible array members in that sizeof yields + zero. */ + if (size && integer_zerop (size)) + { + gcc_assert (itype); + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + } + if (array_parm_vla_unspec_p) + { + gcc_assert (itype); + /* The type is complete. C99 6.7.5.2p4 */ + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + } } if (decl_context != PARM @@ -4290,7 +4499,7 @@ grokdeclarator (const struct c_declarator *declarator, type for the function to return. */ if (type == error_mark_node) continue; - + size_varies = 0; /* Warn about some types functions can't return. */ @@ -4309,12 +4518,14 @@ grokdeclarator (const struct c_declarator *declarator, inner layer of declarator. */ arg_info = declarator->u.arg_info; arg_types = grokparms (arg_info, really_funcdef); + if (really_funcdef) + put_pending_sizes (arg_info->pending_sizes); /* 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 + /* 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 @@ -4325,20 +4536,20 @@ grokdeclarator (const struct c_declarator *declarator, else warning (OPT_Wreturn_type, "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. */ { tree link; - + for (link = arg_info->tags; link; link = TREE_CHAIN (link)) @@ -4358,8 +4569,42 @@ grokdeclarator (const struct c_declarator *declarator, type = c_build_qualified_type (type, type_quals); size_varies = 0; + /* When the pointed-to type involves components of variable size, + care must be taken to ensure that the size evaluation code is + emitted early enough to dominate all the possible later uses + and late enough for the variables on which it depends to have + been assigned. + + This is expected to happen automatically when the pointed-to + type has a name/declaration of it's own, but special attention + is required if the type is anonymous. + + We handle the NORMAL and FIELD contexts here by attaching an + artificial TYPE_DECL to such pointed-to type. This forces the + sizes evaluation at a safe point and ensures it is not deferred + until e.g. within a deeper conditional context. + + We expect nothing to be needed here for PARM or TYPENAME. + Pushing a TYPE_DECL at this point for TYPENAME would actually + be incorrect, as we might be in the middle of an expression + with side effects on the pointed-to type size "arguments" prior + to the pointer declaration point and the fake TYPE_DECL in the + enclosing context would force the size evaluation prior to the + side effects. */ + + if (!TYPE_NAME (type) + && (decl_context == NORMAL || decl_context == FIELD) + && variably_modified_type_p (type, NULL_TREE)) + { + tree decl = build_decl (TYPE_DECL, NULL_TREE, type); + DECL_ARTIFICIAL (decl) = 1; + pushdecl (decl); + finish_decl (decl, NULL_TREE, NULL_TREE); + TYPE_NAME (type) = decl; + } + type = build_pointer_type (type); - + /* Process type qualifiers (such as const or volatile) that were given inside the `*'. */ type_quals = declarator->u.pointer_quals; @@ -4383,8 +4628,8 @@ grokdeclarator (const struct c_declarator *declarator, if (TREE_CODE (type) == ARRAY_TYPE && COMPLETE_TYPE_P (type) - && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && TREE_OVERFLOW (TYPE_SIZE (type))) + && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST + && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) { error ("size of array %qs is too large", name); /* If we proceed with the array type as it is, we'll eventually @@ -4411,21 +4656,6 @@ grokdeclarator (const struct c_declarator *declarator, return decl; } - /* Detect the case of an array type of unspecified size - which came, as such, direct from a typedef name. - We must copy the type, so that each identifier gets - a distinct type, so that each identifier's size can be - controlled separately by its own initializer. */ - - if (type != 0 && typedef_type != 0 - && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0 - && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)) - { - type = build_array_type (TREE_TYPE (type), 0); - if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; - } - /* If this is a type name (such as, in a cast or sizeof), compute the type and return it now. */ @@ -4444,6 +4674,13 @@ grokdeclarator (const struct c_declarator *declarator, return type; } + if (pedantic && decl_context == FIELD + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.2.1p8 */ + pedwarn ("a member of a structure or union cannot have a variably modified type"); + } + /* Aside from typedefs and type names (handle above), `void' at top level (not within pointer) is allowed only in public variables. @@ -4538,7 +4775,7 @@ grokdeclarator (const struct c_declarator *declarator, type = build_pointer_type (type); } else if (TREE_CODE (type) != ERROR_MARK - && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type)) + && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type)) { error ("field %qs has incomplete type", name); type = error_mark_node; @@ -4546,6 +4783,8 @@ grokdeclarator (const struct c_declarator *declarator, type = c_build_qualified_type (type, type_quals); decl = build_decl (FIELD_DECL, declarator->u.id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; + if (bitfield && !declarator->u.id) + TREE_NO_WARNING (decl) = 1; if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; @@ -4570,8 +4809,8 @@ grokdeclarator (const struct c_declarator *declarator, } else if (storage_class == csc_static) { - error ("invalid storage class for function %qs", name); - if (funcdef_flag) + error ("invalid storage class for function %qs", name); + if (funcdef_flag) storage_class = declspecs->storage_class = csc_none; else return 0; @@ -4599,8 +4838,16 @@ grokdeclarator (const struct c_declarator *declarator, GCC to signify a forward declaration of a nested function. */ if (storage_class == csc_auto && current_scope != file_scope) DECL_EXTERNAL (decl) = 0; + /* In C99, a function which is declared 'inline' with 'extern' + is not an external reference (which is confusing). It + means that the later definition of the function must be output + in this file, C99 6.7.4p6. In GNU C89, a function declared + 'extern inline' is an external reference. */ + else if (declspecs->inline_p && storage_class != csc_static) + DECL_EXTERNAL (decl) = ((storage_class == csc_extern) + == flag_gnu89_inline); else - DECL_EXTERNAL (decl) = 1; + DECL_EXTERNAL (decl) = !initialized; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) @@ -4630,11 +4877,7 @@ grokdeclarator (const struct c_declarator *declarator, the abstract origin pointing between the declarations, which will confuse dwarf2out. */ if (initialized) - { - DECL_INLINE (decl) = 1; - if (storage_class == csc_extern) - current_extern_inline = 1; - } + DECL_INLINE (decl) = 1; } /* If -finline-functions, assume it can be inlined. This does two things: let the function be deferred until it is actually @@ -4685,11 +4928,10 @@ grokdeclarator (const struct c_declarator *declarator, /* At file scope, the presence of a `static' or `register' storage class specifier, or the absence of all storage class specifiers makes this declaration a definition (perhaps tentative). Also, - the absence of both `static' and `register' makes it public. */ + the absence of `static' makes it public. */ if (current_scope == file_scope) { - TREE_PUBLIC (decl) = !(storage_class == csc_static - || storage_class == csc_register); + TREE_PUBLIC (decl) = storage_class != csc_static; TREE_STATIC (decl) = !extern_ref; } /* Not at file scope, only `static' makes a static definition. */ @@ -4700,14 +4942,14 @@ grokdeclarator (const struct c_declarator *declarator, } if (threadp) - { - if (targetm.have_tls) - DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); - else - /* A mere warning is sure to result in improper semantics - at runtime. Don't bother to allow this to compile. */ - error ("thread-local storage not supported for this target"); - } + DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + } + + if (storage_class == csc_extern + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.5.2p2 */ + error ("object with variably modified type must have no linkage"); } /* Record `register' declaration for warnings on & @@ -4751,7 +4993,7 @@ grokdeclarator (const struct c_declarator *declarator, } /* Decode the parameter-list info for a function type or function definition. - The argument is the value returned by `get_parm_info' (or made in parse.y + The argument is the value returned by `get_parm_info' (or made in c-parse.c if there is an identifier list instead of a parameter decl list). These two functions are separate because when a function returns or receives functions then each is called multiple times but the order @@ -4769,6 +5011,13 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) { tree arg_types = arg_info->types; + if (funcdef_flag && arg_info->had_vla_unspec) + { + /* A function definition isn't function prototype scope C99 6.2.1p4. */ + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + } + if (arg_types == 0 && !funcdef_flag && !in_system_header) warning (OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -4865,6 +5114,8 @@ get_parm_info (bool ellipsis) arg_info->tags = 0; arg_info->types = 0; arg_info->others = 0; + arg_info->pending_sizes = 0; + arg_info->had_vla_unspec = current_scope->had_vla_unspec; /* The bindings in this scope must not get put into a block. We will take care of deleting the binding nodes. */ @@ -4879,7 +5130,7 @@ get_parm_info (bool ellipsis) (by 'const' or 'volatile'), or has a storage class specifier ('register'), then the behavior is undefined; issue an error. Typedefs for 'void' are OK (see DR#157). */ - if (b->prev == 0 /* one binding */ + if (b->prev == 0 /* one binding */ && TREE_CODE (b->decl) == PARM_DECL /* which is a parameter */ && !DECL_NAME (b->decl) /* anonymous */ && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */ @@ -5019,6 +5270,7 @@ get_parm_info (bool ellipsis) arg_info->tags = tags; arg_info->types = types; arg_info->others = others; + arg_info->pending_sizes = get_pending_sizes (); return arg_info; } @@ -5104,24 +5356,27 @@ start_struct (enum tree_code code, tree name) if (ref && TREE_CODE (ref) == code) { if (TYPE_SIZE (ref)) - { + { if (code == UNION_TYPE) error ("redefinition of %", name); - else + else error ("redefinition of %", name); } else if (C_TYPE_BEING_DEFINED (ref)) { if (code == UNION_TYPE) error ("nested redefinition of %", name); - else + else error ("nested redefinition of %", name); + /* Don't create structures that contain themselves. */ + ref = NULL_TREE; } } - else - { - /* Otherwise create a forward-reference just so the tag is in scope. */ + /* Otherwise create a forward-reference just so the tag is in scope. */ + + if (ref == NULL_TREE || TREE_CODE (ref) != code) + { ref = make_node (code); pushtag (name, ref); } @@ -5194,7 +5449,7 @@ grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs, } value = grokdeclarator (declarator, declspecs, FIELD, false, - width ? &width : NULL); + width ? &width : NULL, DEPRECATED_NORMAL); finish_decl (value, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; @@ -5312,8 +5567,13 @@ finish_struct (tree t, tree fieldlist, tree attributes) saw_named_field = 0; for (x = fieldlist; x; x = TREE_CHAIN (x)) { + if (TREE_TYPE (x) == error_mark_node) + continue; + DECL_CONTEXT (x) = t; - DECL_PACKED (x) |= TYPE_PACKED (t); + + if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT) + DECL_PACKED (x) = 1; /* If any field is const, the structure type is pseudo-const. */ if (TREE_READONLY (x)) @@ -5421,46 +5681,46 @@ finish_struct (tree t, tree fieldlist, tree attributes) for (x = fieldlist; x; x = TREE_CHAIN (x)) { - if (len > 15 || DECL_NAME (x) == NULL) - break; - len += 1; + if (len > 15 || DECL_NAME (x) == NULL) + break; + len += 1; } if (len > 15) { - tree *field_array; - struct lang_type *space; - struct sorted_fields_type *space2; + tree *field_array; + struct lang_type *space; + struct sorted_fields_type *space2; - len += list_length (x); + len += list_length (x); - /* Use the same allocation policy here that make_node uses, to - ensure that this lives as long as the rest of the struct decl. - All decls in an inline function need to be saved. */ + /* Use the same allocation policy here that make_node uses, to + ensure that this lives as long as the rest of the struct decl. + All decls in an inline function need to be saved. */ - space = GGC_CNEW (struct lang_type); - space2 = GGC_NEWVAR (struct sorted_fields_type, + space = GGC_CNEW (struct lang_type); + space2 = GGC_NEWVAR (struct sorted_fields_type, sizeof (struct sorted_fields_type) + len * sizeof (tree)); - len = 0; + len = 0; space->s = space2; field_array = &space2->elts[0]; - for (x = fieldlist; x; x = TREE_CHAIN (x)) - { - field_array[len++] = x; - - /* If there is anonymous struct or union, break out of the loop. */ - if (DECL_NAME (x) == NULL) - break; - } - /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ - if (x == NULL) - { - TYPE_LANG_SPECIFIC (t) = space; - TYPE_LANG_SPECIFIC (t)->s->len = len; - field_array = TYPE_LANG_SPECIFIC (t)->s->elts; - qsort (field_array, len, sizeof (tree), field_decl_cmp); - } + for (x = fieldlist; x; x = TREE_CHAIN (x)) + { + field_array[len++] = x; + + /* If there is anonymous struct or union, break out of the loop. */ + if (DECL_NAME (x) == NULL) + break; + } + /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ + if (x == NULL) + { + TYPE_LANG_SPECIFIC (t) = space; + TYPE_LANG_SPECIFIC (t)->s->len = len; + field_array = TYPE_LANG_SPECIFIC (t)->s->elts; + qsort (field_array, len, sizeof (tree), field_decl_cmp); + } } } @@ -5468,8 +5728,6 @@ finish_struct (tree t, tree fieldlist, tree attributes) { TYPE_FIELDS (x) = TYPE_FIELDS (t); TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); - TYPE_ALIGN (x) = TYPE_ALIGN (t); - TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t); C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t); C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t); C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t); @@ -5512,7 +5770,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) /* 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)) + if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE)) add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t))); return t; @@ -5535,7 +5793,7 @@ layout_array_type (tree t) may be used to declare the individual values as they are read. */ tree -start_enum (tree name) +start_enum (struct c_enum_contents *the_enum, tree name) { tree enumtype = 0; @@ -5567,8 +5825,8 @@ start_enum (tree name) TYPE_VALUES (enumtype) = 0; } - enum_next_value = integer_zero_node; - enum_overflow = 0; + the_enum->enum_next_value = integer_zero_node; + the_enum->enum_overflow = 0; if (flag_short_enums) TYPE_PACKED (enumtype) = 1; @@ -5721,7 +5979,7 @@ finish_enum (tree enumtype, tree values, tree attributes) Assignment of sequential values by default is handled here. */ tree -build_enumerator (tree name, tree value) +build_enumerator (struct c_enum_contents *the_enum, tree name, tree value) { tree decl, type; @@ -5751,8 +6009,8 @@ build_enumerator (tree name, tree value) in the default. */ if (value == 0) { - value = enum_next_value; - if (enum_overflow) + value = the_enum->enum_next_value; + if (the_enum->enum_overflow) error ("overflow in enumeration values"); } @@ -5765,8 +6023,9 @@ build_enumerator (tree name, tree value) } /* Set basis for default for next value. */ - enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0); - enum_overflow = tree_int_cst_lt (enum_next_value, value); + the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value, + integer_one_node, 0); + the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value); /* Now create a declaration for the enum value name. */ @@ -5810,7 +6069,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, current_function_returns_null = 0; current_function_returns_abnormally = 0; warn_about_return_type = 0; - current_extern_inline = 0; c_switch_stack = NULL; nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se); @@ -5831,7 +6089,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, error message in c_finish_bc_stmt. */ c_break_label = c_cont_label = size_zero_node; - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL); + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL, + DEPRECATED_NORMAL); /* If the declarator is not suitable for a function definition, cause a syntax error. */ @@ -5850,6 +6109,16 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, warning (OPT_Wattributes, "inline function %q+D given attribute noinline", decl1); + /* Handle gnu_inline attribute. */ + if (declspecs->inline_p + && !flag_gnu89_inline + && TREE_CODE (decl1) == FUNCTION_DECL + && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))) + { + if (declspecs->storage_class != csc_static) + DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1); + } + announce_function (decl1); if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1)))) @@ -5871,6 +6140,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, /* If this definition isn't a prototype and we had a prototype declaration before, copy the arg type info from that prototype. */ old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope); + if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL) + old_decl = 0; current_function_prototype_locus = UNKNOWN_LOCATION; current_function_prototype_built_in = false; current_function_prototype_arg_types = NULL_TREE; @@ -5960,12 +6231,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, warning (OPT_Wmissing_declarations, "%q+D was used with no declaration before its definition", decl1); - /* This is a definition, not a reference. - So normally clear DECL_EXTERNAL. - However, `extern inline' acts like a declaration - except for defining how to inline. So set DECL_EXTERNAL in that case. */ - DECL_EXTERNAL (decl1) = current_extern_inline; - /* This function exists in static storage. (This does not mean `static' in the C sense!) */ TREE_STATIC (decl1) = 1; @@ -5985,54 +6250,11 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, /* Warn for unlikely, improbable, or stupid declarations of `main'. */ if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1))) { - tree args; - int argct = 0; - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) != integer_type_node) pedwarn ("return type of %q+D is not %", decl1); - for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; - args = TREE_CHAIN (args)) - { - tree type = args ? TREE_VALUE (args) : 0; - - if (type == void_type_node) - break; - - ++argct; - switch (argct) - { - case 1: - if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn ("first argument of %q+D should be %", decl1); - break; - - case 2: - if (TREE_CODE (type) != POINTER_TYPE - || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) - != char_type_node)) - pedwarn ("second argument of %q+D should be %", - decl1); - break; - - case 3: - if (TREE_CODE (type) != POINTER_TYPE - || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) - != char_type_node)) - pedwarn ("third argument of %q+D should probably be " - "%", decl1); - break; - } - } - - /* It is intentional that this message does not mention the third - argument because it's only mentioned in an appendix of the - standard. */ - if (argct > 0 && (argct < 2 || argct > 3)) - pedwarn ("%q+D takes only zero or two arguments", decl1); + check_main_parameter_types(decl1); if (!TREE_PUBLIC (decl1)) pedwarn ("%q+D is normally a non-static function", decl1); @@ -6196,8 +6418,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) if (flag_isoc99) pedwarn ("type of %q+D defaults to %", decl); - else if (extra_warnings) - warning (OPT_Wextra, "type of %q+D defaults to %", decl); + else + warning (OPT_Wmissing_parameter_type, "type of %q+D defaults to %", decl); } TREE_PURPOSE (parm) = decl; @@ -6264,8 +6486,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) tree type; for (parm = DECL_ARGUMENTS (fndecl), type = current_function_prototype_arg_types; - parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) - != void_type_node)); + parm || (type && TREE_VALUE (type) != error_mark_node + && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node)); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) { if (parm == 0 || type == 0 @@ -6447,21 +6669,25 @@ store_parm_decls (void) cfun->x_dont_save_pending_sizes_p = 1; } -/* Handle attribute((warn_unused_result)) on FNDECL and all its nested - functions. */ +/* Emit diagnostics that require gimple input for detection. Operate on + FNDECL and all its nested functions. */ static void -c_warn_unused_result_recursively (tree fndecl) +c_gimple_diagnostics_recursively (tree fndecl) { struct cgraph_node *cgn; /* Handle attribute((warn_unused_result)). Relies on gimple input. */ c_warn_unused_result (&DECL_SAVED_TREE (fndecl)); + /* Notice when OpenMP structured block constraints are violated. */ + if (flag_openmp) + diagnose_omp_structured_block_errors (fndecl); + /* Finalize all nested functions now. */ cgn = cgraph_node (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) - c_warn_unused_result_recursively (cgn->decl); + c_gimple_diagnostics_recursively (cgn->decl); } /* Finish up a function declaration and compile that function @@ -6483,12 +6709,12 @@ finish_function (void) { tree args = DECL_ARGUMENTS (fndecl); for (; args; args = TREE_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = integer_type_node; - } + { + tree type = TREE_TYPE (args); + if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (args) = integer_type_node; + } } if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) @@ -6556,26 +6782,10 @@ finish_function (void) TREE_NO_WARNING (fndecl) = 1; } - /* With just -Wextra, complain only if function returns both with - and without a value. */ - if (extra_warnings - && current_function_returns_value - && current_function_returns_null) - warning (OPT_Wextra, "this function may return with or without a value"); - /* Store the end of the function, so that we get good line number info for the epilogue. */ cfun->function_end_locus = input_location; - /* If we don't have ctors/dtors sections, and this is a static - constructor or destructor, it must be recorded now. */ - if (DECL_STATIC_CONSTRUCTOR (fndecl) - && !targetm.have_ctors_dtors) - static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); - if (DECL_STATIC_DESTRUCTOR (fndecl) - && !targetm.have_ctors_dtors) - static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); - /* Finalize the ELF visibility for the function. */ c_determine_visibility (fndecl); @@ -6587,9 +6797,9 @@ finish_function (void) && !undef_nested_function) { if (!decl_function_context (fndecl)) - { - c_genericize (fndecl); - c_warn_unused_result_recursively (fndecl); + { + c_genericize (fndecl); + c_gimple_diagnostics_recursively (fndecl); /* ??? Objc emits functions after finalizing the compilation unit. This should be cleaned up later and this conditional removed. */ @@ -6600,14 +6810,14 @@ finish_function (void) } cgraph_finalize_function (fndecl, false); - } + } else - { - /* Register this function with cgraph just far enough to get it - added to our parent's nested function list. Handy, since the - C front end doesn't have such a list. */ - (void) cgraph_node (fndecl); - } + { + /* Register this function with cgraph just far enough to get it + added to our parent's nested function list. Handy, since the + C front end doesn't have such a list. */ + (void) cgraph_node (fndecl); + } } if (!decl_function_context (fndecl)) @@ -6619,35 +6829,17 @@ finish_function (void) cfun = NULL; current_function_decl = NULL; } - -/* Generate the RTL for the body of FNDECL. */ - -void -c_expand_body (tree fndecl) -{ - - if (!DECL_INITIAL (fndecl) - || DECL_INITIAL (fndecl) == error_mark_node) - return; - - tree_rest_of_compilation (fndecl); - - if (DECL_STATIC_CONSTRUCTOR (fndecl) - && targetm.have_ctors_dtors) - targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0), - DEFAULT_INIT_PRIORITY); - if (DECL_STATIC_DESTRUCTOR (fndecl) - && targetm.have_ctors_dtors) - targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0), - DEFAULT_INIT_PRIORITY); -} /* Check the declarations given in a for-loop for satisfying the C99 - constraints. */ -void + constraints. If exactly one such decl is found, return it. */ + +tree check_for_loop_decls (void) { struct c_binding *b; + tree one_decl = NULL_TREE; + int n_decls = 0; + if (!flag_isoc99) { @@ -6655,7 +6847,7 @@ check_for_loop_decls (void) the C99 for loop scope. This doesn't make much sense, so don't allow it. */ error ("% loop initial declaration used outside C99 mode"); - return; + return NULL_TREE; } /* C99 subclause 6.8.5 paragraph 3: @@ -6706,7 +6898,12 @@ check_for_loop_decls (void) error ("declaration of non-variable %q+D in % loop " "initial declaration", decl); } + + n_decls++; + one_decl = decl; } + + return n_decls == 1 ? one_decl : NULL_TREE; } /* Save and reinitialize the variables @@ -6728,7 +6925,6 @@ c_push_function_context (struct function *f) p->returns_null = current_function_returns_null; p->returns_abnormally = current_function_returns_abnormally; p->warn_about_return_type = warn_about_return_type; - p->extern_inline = current_extern_inline; } /* Restore the variables used during compilation of a C function. */ @@ -6757,7 +6953,6 @@ c_pop_function_context (struct function *f) current_function_returns_null = p->returns_null; current_function_returns_abnormally = p->returns_abnormally; warn_about_return_type = p->warn_about_return_type; - current_extern_inline = p->extern_inline; f->language = NULL; } @@ -7054,6 +7249,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_float) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->long_p = true; break; @@ -7077,6 +7281,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->short_p = true; break; @@ -7097,6 +7310,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->signed_p = true; break; @@ -7117,6 +7339,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->unsigned_p = true; break; @@ -7130,6 +7361,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_bool) error ("both % and %<_Bool%> in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->complex_p = true; break; @@ -7235,6 +7475,47 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else specs->typespec_word = cts_double; return specs; + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + { + const char *str; + if (i == RID_DFLOAT32) + str = "_Decimal32"; + else if (i == RID_DFLOAT64) + str = "_Decimal64"; + else + str = "_Decimal128"; + if (specs->long_long_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + if (specs->long_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->short_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->signed_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->unsigned_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->complex_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (i == RID_DFLOAT32) + specs->typespec_word = cts_dfloat32; + else if (i == RID_DFLOAT64) + specs->typespec_word = cts_dfloat64; + else + specs->typespec_word = cts_dfloat128; + } + if (!targetm.decimal_float_supported_p ()) + error ("decimal floating point not supported for this target"); + if (pedantic) + pedwarn ("ISO C does not support decimal floating point"); + return specs; default: /* ObjC reserved word "id", handled below. */ break; @@ -7298,8 +7579,9 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec) gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (scspec)); i = C_RID_CODE (scspec); - if (extra_warnings && specs->non_sc_seen_p) - warning (OPT_Wextra, "%qE is not at beginning of declaration", scspec); + if (specs->non_sc_seen_p) + warning (OPT_Wold_style_declaration, + "%qE is not at beginning of declaration", scspec); switch (i) { case RID_INLINE: @@ -7512,6 +7794,18 @@ finish_declspecs (struct c_declspecs *specs) : double_type_node); } break; + case cts_dfloat32: + case cts_dfloat64: + case cts_dfloat128: + gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p && !specs->complex_p); + if (specs->typespec_word == cts_dfloat32) + specs->type = dfloat32_type_node; + else if (specs->typespec_word == cts_dfloat64) + specs->type = dfloat64_type_node; + else + specs->type = dfloat128_type_node; + break; default: gcc_unreachable (); } @@ -7519,38 +7813,19 @@ finish_declspecs (struct c_declspecs *specs) return specs; } -/* Synthesize a function which calls all the global ctors or global - dtors in this file. This is only used for targets which do not - support .ctors/.dtors sections. FIXME: Migrate into cgraph. */ -static void -build_cdtor (int method_type, tree cdtors) -{ - tree body = 0; - - if (!cdtors) - return; - - for (; cdtors; cdtors = TREE_CHAIN (cdtors)) - append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0), - &body); - - cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY); -} +/* A subroutine of c_write_global_declarations. Perform final processing + on one file scope's declarations (or the external scope's declarations), + GLOBALS. */ -/* Perform final processing on one file scope's declarations (or the - external scope's declarations), GLOBALS. */ static void c_write_global_declarations_1 (tree globals) { - size_t len = list_length (globals); - tree *vec = XNEWVEC (tree, len); - size_t i; tree decl; + bool reconsider; /* Process the decls in the order they were written. */ - for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) + for (decl = globals; decl; decl = TREE_CHAIN (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. */ @@ -7563,18 +7838,41 @@ c_write_global_declarations_1 (tree globals) pedwarn ("%q+F used but never defined", decl); TREE_NO_WARNING (decl) = 1; } + + wrapup_global_declaration_1 (decl); + } + + do + { + reconsider = false; + for (decl = globals; decl; decl = TREE_CHAIN (decl)) + reconsider |= wrapup_global_declaration_2 (decl); } + while (reconsider); + + for (decl = globals; decl; decl = TREE_CHAIN (decl)) + check_global_declaration_1 (decl); +} + +/* A subroutine of c_write_global_declarations Emit debug information for each + of the declarations in GLOBALS. */ - wrapup_global_declarations (vec, len); - check_global_declarations (vec, len); +static void +c_write_global_declarations_2 (tree globals) +{ + tree decl; - free (vec); + for (decl = globals; decl ; decl = TREE_CHAIN (decl)) + debug_hooks->global_decl (decl); } +/* Preserve the external declarations scope across a garbage collect. */ +static GTY(()) tree ext_block; + void c_write_global_declarations (void) { - tree ext_block, t; + tree t; /* We don't want to do this if generating a PCH. */ if (pch_file) @@ -7590,32 +7888,40 @@ c_write_global_declarations (void) external_scope = 0; gcc_assert (!current_scope); - /* Process all file scopes in this compilation, and the external_scope, - through wrapup_global_declarations and check_global_declarations. */ - for (t = all_translation_units; t; t = TREE_CHAIN (t)) - c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); if (ext_block) { tree tmp = BLOCK_VARS (ext_block); int flags; FILE * stream = dump_begin (TDI_tu, &flags); if (stream && tmp) - { - dump_node (tmp, flags & ~TDF_SLIM, stream); - dump_end (TDI_tu, stream); - } + { + dump_node (tmp, flags & ~TDF_SLIM, stream); + dump_end (TDI_tu, stream); + } } - c_write_global_declarations_1 (BLOCK_VARS (ext_block)); - /* Generate functions to call static constructors and destructors - for targets that do not support .ctors/.dtors sections. These - functions have magic names which are detected by collect2. */ - build_cdtor ('I', static_ctors); static_ctors = 0; - build_cdtor ('D', static_dtors); static_dtors = 0; + /* Process all file scopes in this compilation, and the external_scope, + through wrapup_global_declarations and check_global_declarations. */ + for (t = all_translation_units; t; t = TREE_CHAIN (t)) + c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); + c_write_global_declarations_1 (BLOCK_VARS (ext_block)); /* We're done parsing; proceed to optimize and emit assembly. FIXME: shouldn't be the front end's responsibility to call this. */ cgraph_optimize (); + + /* After cgraph has had a chance to emit everything that's going to + be emitted, output debug information for globals. */ + if (errorcount == 0 && sorrycount == 0) + { + timevar_push (TV_SYMOUT); + for (t = all_translation_units; t; t = TREE_CHAIN (t)) + c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); + c_write_global_declarations_2 (BLOCK_VARS (ext_block)); + timevar_pop (TV_SYMOUT); + } + + ext_block = NULL; } #include "gt-c-decl.h"