diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gcc/c-decl.c | 1401 |
1 files changed, 453 insertions, 948 deletions
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index 636f272..cba3fe5 100644 --- a/contrib/gcc/c-decl.c +++ b/contrib/gcc/c-decl.c @@ -39,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "output.h" #include "expr.h" #include "c-tree.h" -#include "c-lex.h" #include "toplev.h" #include "ggc.h" #include "tm_p.h" @@ -49,6 +48,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "timevar.h" #include "c-common.h" #include "c-pragma.h" +#include "libfuncs.h" +#include "except.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -106,26 +107,21 @@ static int current_function_prototype_line; /* The current statement tree. */ -static struct stmt_tree_s c_stmt_tree; +static GTY(()) struct stmt_tree_s c_stmt_tree; /* The current scope statement stack. */ -static tree c_scope_stmt_stack; +static GTY(()) tree c_scope_stmt_stack; /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function that have names. Here so we can clear out their names' definitions at the end of the function. */ -static tree named_labels; +static GTY(()) tree named_labels; /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ -static tree shadowed_labels; - -/* Nonzero when store_parm_decls is called indicates a varargs function. - Value not meaningful after store_parm_decls. */ - -static int c_function_varargs; +static GTY(()) tree shadowed_labels; /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ @@ -167,7 +163,7 @@ static int current_extern_inline; /* Note that the information in the `names' component of the global contour is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ -struct binding_level +struct binding_level GTY(()) { /* A chain of _DECL nodes for all variables, constants, functions, and typedef types. These are in the reverse of the order supplied. @@ -218,9 +214,9 @@ struct binding_level /* Nonzero means make a BLOCK if this level has any subblocks. */ char keep_if_subblocks; - /* Number of decls in `names' that have incomplete - structure or union types. */ - int n_incomplete; + /* List of decls in `names' that have incomplete structure or + union types. */ + tree incomplete_list; /* A list of decls giving the (reversed) specified order of parms, not including any forward-decls in the parmlist. @@ -232,22 +228,22 @@ struct binding_level /* The binding level currently in effect. */ -static struct binding_level *current_binding_level; +static GTY(()) struct binding_level *current_binding_level; /* A chain of binding_level structures awaiting reuse. */ -static struct binding_level *free_binding_level; +static GTY((deletable (""))) struct binding_level *free_binding_level; /* The outermost binding level, for names of file scope. This is created when the compiler is started and exists through the entire run. */ -static struct binding_level *global_binding_level; +static GTY(()) struct binding_level *global_binding_level; /* Binding level structures are initialized by copying this one. */ static struct binding_level clear_binding_level - = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0, + = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL, NULL}; /* Nonzero means unconditionally make a BLOCK for the next level pushed. */ @@ -265,7 +261,7 @@ static int keep_next_if_subblocks; saved values of named_labels and shadowed_labels for a label binding level outside the current one. */ -static struct binding_level *label_level_chain; +static GTY(()) struct binding_level *label_level_chain; /* Functions called automatically at the beginning and end of execution. */ @@ -274,7 +270,7 @@ tree static_ctors, static_dtors; /* Forward declarations. */ static struct binding_level * make_binding_level PARAMS ((void)); -static void mark_binding_level PARAMS ((void *)); +static void pop_binding_level PARAMS ((struct binding_level **)); static void clear_limbo_values PARAMS ((tree)); static int duplicate_decls PARAMS ((tree, tree, int)); static int redeclaration_error_message PARAMS ((tree, tree)); @@ -290,172 +286,9 @@ static void layout_array_type PARAMS ((tree)); static tree c_make_fname_decl PARAMS ((tree, int)); static void c_expand_body PARAMS ((tree, int, int)); static void warn_if_shadowing PARAMS ((tree, tree)); +static bool flexible_array_type_p PARAMS ((tree)); +static tree set_save_expr_context PARAMS ((tree *, int *, void *)); -/* C-specific option variables. */ - -/* Nonzero means allow type mismatches in conditional expressions; - just make their values `void'. */ - -int flag_cond_mismatch; - -/* Nonzero means don't recognize the keyword `asm'. */ - -int flag_no_asm; - -/* Nonzero means do some things the same way PCC does. */ - -int flag_traditional; - -/* Nonzero means enable C89 Amendment 1 features. */ - -int flag_isoc94 = 0; - -/* Nonzero means use the ISO C99 dialect of C. */ - -int flag_isoc99 = 0; - -/* Nonzero means allow the BSD kernel printf enhancments. */ - -int flag_bsd_format = 0; - -/* Nonzero means that we have builtin functions, and main is an int */ - -int flag_hosted = 1; - -/* Nonzero means add default format_arg attributes for functions not - in ISO C. */ - -int flag_noniso_default_format_attributes = 1; - -/* Nonzero means to allow single precision math even if we're generally - being traditional. */ -int flag_allow_single_precision = 0; - -/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ - -int flag_signed_bitfields = 1; -int explicit_flag_signed_bitfields = 0; - -/* Nonzero means warn about use of implicit int. */ - -int warn_implicit_int; - -/* Nonzero means warn about usage of long long when `-pedantic'. */ - -int warn_long_long = 1; - -/* Nonzero means message about use of implicit function declarations; - 1 means warning; 2 means error. */ - -int mesg_implicit_function_declaration = -1; - -/* Nonzero means give string constants the type `const char *' - to get extra warnings from them. These warnings will be too numerous - to be useful, except in thoroughly ANSIfied programs. */ - -int flag_const_strings; - -/* Nonzero means warn about pointer casts that can drop a type qualifier - from the pointer target type. */ - -int warn_cast_qual; - -/* Nonzero means warn when casting a function call to a type that does - not match the return type (e.g. (float)sqrt() or (anything*)malloc() - when there is no previous declaration of sqrt or malloc. */ - -int warn_bad_function_cast; - -/* Warn about functions which might be candidates for format attributes. */ - -int warn_missing_format_attribute; - -/* Warn about traditional constructs whose meanings changed in ANSI C. */ - -int warn_traditional; - -/* Nonzero means warn about sizeof(function) or addition/subtraction - of function pointers. */ - -int warn_pointer_arith; - - -/* Nonzero means do not warn that K&R style main() is not a function prototype. */ - -int flag_bsd_no_warn_kr_main; - -/* Nonzero means warn for non-prototype function decls - or non-prototyped defs without previous prototype. */ - -int warn_strict_prototypes; - -/* Nonzero means warn for any global function def - without separate previous prototype decl. */ - -int warn_missing_prototypes; - -/* Nonzero means warn for any global function def - without separate previous decl. */ - -int warn_missing_declarations; - -/* Nonzero means warn about multiple (redundant) decls for the same single - variable or function. */ - -int warn_redundant_decls = 0; - -/* Nonzero means warn about extern declarations of objects not at - file-scope level and about *all* declarations of functions (whether - extern or static) not at file-scope level. Note that we exclude - implicit function declarations. To get warnings about those, use - -Wimplicit. */ - -int warn_nested_externs = 0; - -/* Warn about a subscript that has type char. */ - -int warn_char_subscripts = 0; - -/* Warn if a type conversion is done that might have confusing results. */ - -int warn_conversion; - -/* Warn if adding () is suggested. */ - -int warn_parentheses; - -/* Warn if initializer is not completely bracketed. */ - -int warn_missing_braces; - -/* Warn if main is suspicious. */ - -int warn_main; - -/* Warn about #pragma directives that are not recognised. */ - -int warn_unknown_pragmas = 0; /* Tri state variable. */ - -/* Warn about comparison of signed and unsigned values. - If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */ - -int warn_sign_compare = -1; - -/* Warn about testing equality of floating point numbers. */ - -int warn_float_equal = 0; - -/* Nonzero means warn about use of multicharacter literals. */ - -int warn_multichar = 1; - -/* Nonzero means `$' can be in an identifier. */ - -#ifndef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 1 -#endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; - /* States indicating how grokdeclarator() should handle declspecs marked with __attribute__((deprecated)). An object declared as __attribute__((deprecated)) suppresses warnings of uses of other @@ -468,379 +301,6 @@ enum deprecated_states { static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; -/* Decode the string P as a language-specific option for C. - Return the number of strings consumed. Should not complain - if it does not recognise the option. */ - -int -c_decode_option (argc, argv) - int argc ATTRIBUTE_UNUSED; - char **argv; -{ - int strings_processed; - char *p = argv[0]; - - strings_processed = cpp_handle_option (parse_in, argc, argv, 0); - - if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) - { - warning ("-traditional is deprecated and may be removed"); - flag_traditional = 1; - flag_writable_strings = 1; - } - else if (!strcmp (p, "-fallow-single-precision")) - flag_allow_single_precision = 1; - else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding")) - { - flag_hosted = 1; - flag_no_builtin = 0; - } - else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted")) - { - flag_hosted = 0; - flag_no_builtin = 1; - /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ - if (warn_main == 2) - warn_main = 0; - } - else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional")) - { - flag_traditional = 0; - flag_writable_strings = 0; - } - else if (!strncmp (p, "-std=", 5)) - { - /* Select the appropriate language standard. We currently - recognize: - -std=iso9899:1990 same as -ansi - -std=iso9899:199409 ISO C as modified in amend. 1 - -std=iso9899:1999 ISO C 99 - -std=c89 same as -std=iso9899:1990 - -std=c99 same as -std=iso9899:1999 - -std=gnu89 default, iso9899:1990 + gnu extensions - -std=gnu99 iso9899:1999 + gnu extensions - -std=bsd iso9899:1999 + BSD kernel printf extensions - */ - const char *const argstart = &p[5]; - - if (!strcmp (argstart, "iso9899:1990") - || !strcmp (argstart, "c89")) - { - iso_1990: - flag_isoc94 = 0; - iso_1994: - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_noniso_default_format_attributes = 0; - flag_isoc99 = 0; - flag_bsd_format = 0; - flag_bsd_no_warn_kr_main = 0; - } - else if (!strcmp (argstart, "iso9899:199409")) - { - flag_isoc94 = 1; - goto iso_1994; - } - else if (!strcmp (argstart, "iso9899:199x") - || !strcmp (argstart, "iso9899:1999") - || !strcmp (argstart, "c9x") - || !strcmp (argstart, "c99")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_noniso_default_format_attributes = 0; - flag_isoc99 = 1; - flag_isoc94 = 1; - flag_bsd_format = 0; - flag_bsd_no_warn_kr_main = 0; - } - else if (!strcmp (argstart, "gnu89")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_noniso_default_format_attributes = 1; - flag_isoc99 = 0; - flag_isoc94 = 0; - flag_bsd_format = 0; - flag_bsd_no_warn_kr_main = 0; - } - else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_noniso_default_format_attributes = 1; - flag_isoc99 = 1; - flag_isoc94 = 1; - flag_bsd_format = 0; - flag_bsd_no_warn_kr_main = 0; - } - else if (!strcmp (argstart, "bsd")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_noniso_default_format_attributes = 1; - flag_isoc99 = 0; - flag_isoc94 = 0; - flag_isoc94 = 0; - flag_bsd_format = 1; - flag_bsd_no_warn_kr_main = 1; - } - else - error ("unknown C standard `%s'", argstart); - } - else if (!strcmp (p, "-fdollars-in-identifiers")) - dollars_in_ident = 1; - else if (!strcmp (p, "-fno-dollars-in-identifiers")) - dollars_in_ident = 0; - else if (!strcmp (p, "-fsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-funsigned-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-signed-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-unsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-fsigned-bitfields") - || !strcmp (p, "-fno-unsigned-bitfields")) - { - flag_signed_bitfields = 1; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-funsigned-bitfields") - || !strcmp (p, "-fno-signed-bitfields")) - { - flag_signed_bitfields = 0; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-fshort-enums")) - flag_short_enums = 1; - else if (!strcmp (p, "-fno-short-enums")) - flag_short_enums = 0; - else if (!strcmp (p, "-fshort-wchar")) - flag_short_wchar = 1; - else if (!strcmp (p, "-fno-short-wchar")) - flag_short_wchar = 0; - else if (!strcmp (p, "-fcond-mismatch")) - flag_cond_mismatch = 1; - else if (!strcmp (p, "-fno-cond-mismatch")) - flag_cond_mismatch = 0; - else if (!strcmp (p, "-fshort-double")) - flag_short_double = 1; - else if (!strcmp (p, "-fno-short-double")) - flag_short_double = 0; - else if (!strcmp (p, "-fasm")) - flag_no_asm = 0; - else if (!strcmp (p, "-fno-asm")) - flag_no_asm = 1; - else if (!strcmp (p, "-fbuiltin")) - flag_no_builtin = 0; - else if (!strcmp (p, "-fno-builtin")) - flag_no_builtin = 1; - else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-"))) - disable_builtin_function (p + strlen ("-fno-builtin-")); - else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2)) - ; - else if (!strcmp (p, "-ansi")) - goto iso_1990; - else if (!strcmp (p, "-Werror-implicit-function-declaration")) - mesg_implicit_function_declaration = 2; - else if (!strcmp (p, "-Wimplicit-function-declaration")) - mesg_implicit_function_declaration = 1; - else if (!strcmp (p, "-Wno-implicit-function-declaration")) - mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wimplicit-int")) - warn_implicit_int = 1; - else if (!strcmp (p, "-Wno-implicit-int")) - warn_implicit_int = 0; - else if (!strcmp (p, "-Wimplicit")) - { - warn_implicit_int = 1; - if (mesg_implicit_function_declaration != 2) - mesg_implicit_function_declaration = 1; - } - else if (!strcmp (p, "-Wno-implicit")) - warn_implicit_int = 0, mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wlong-long")) - warn_long_long = 1; - else if (!strcmp (p, "-Wno-long-long")) - warn_long_long = 0; - else if (!strcmp (p, "-Wwrite-strings")) - flag_const_strings = 1; - else if (!strcmp (p, "-Wno-write-strings")) - flag_const_strings = 0; - else if (!strcmp (p, "-Wcast-qual")) - warn_cast_qual = 1; - else if (!strcmp (p, "-Wno-cast-qual")) - warn_cast_qual = 0; - else if (!strcmp (p, "-Wbad-function-cast")) - warn_bad_function_cast = 1; - else if (!strcmp (p, "-Wno-bad-function-cast")) - warn_bad_function_cast = 0; - else if (!strcmp (p, "-Wno-missing-noreturn")) - warn_missing_noreturn = 0; - else if (!strcmp (p, "-Wmissing-format-attribute")) - warn_missing_format_attribute = 1; - else if (!strcmp (p, "-Wno-missing-format-attribute")) - warn_missing_format_attribute = 0; - else if (!strcmp (p, "-Wpointer-arith")) - warn_pointer_arith = 1; - else if (!strcmp (p, "-Wno-pointer-arith")) - warn_pointer_arith = 0; - else if (!strcmp (p, "-Wstrict-prototypes")) - warn_strict_prototypes = 1; - else if (!strcmp (p, "-Wno-strict-prototypes")) - warn_strict_prototypes = 0; - else if (!strcmp (p, "-Wmissing-prototypes")) - warn_missing_prototypes = 1; - else if (!strcmp (p, "-Wno-missing-prototypes")) - warn_missing_prototypes = 0; - else if (!strcmp (p, "-Wmissing-declarations")) - warn_missing_declarations = 1; - else if (!strcmp (p, "-Wno-missing-declarations")) - warn_missing_declarations = 0; - else if (!strcmp (p, "-Wredundant-decls")) - warn_redundant_decls = 1; - else if (!strcmp (p, "-Wno-redundant-decls")) - warn_redundant_decls = 0; - else if (!strcmp (p, "-Wnested-externs")) - warn_nested_externs = 1; - else if (!strcmp (p, "-Wno-nested-externs")) - warn_nested_externs = 0; - else if (!strcmp (p, "-Wtraditional")) - warn_traditional = 1; - else if (!strcmp (p, "-Wno-traditional")) - warn_traditional = 0; - else if (!strncmp (p, "-Wformat=", 9)) - set_Wformat (atoi (p + 9)); - else if (!strcmp (p, "-Wformat")) - set_Wformat (1); - else if (!strcmp (p, "-Wno-format")) - set_Wformat (0); - else if (!strcmp (p, "-Wformat-y2k")) - warn_format_y2k = 1; - else if (!strcmp (p, "-Wno-format-y2k")) - warn_format_y2k = 0; - else if (!strcmp (p, "-Wformat-extra-args")) - warn_format_extra_args = 1; - else if (!strcmp (p, "-Wno-format-extra-args")) - warn_format_extra_args = 0; - else if (!strcmp (p, "-Wformat-nonliteral")) - warn_format_nonliteral = 1; - else if (!strcmp (p, "-Wno-format-nonliteral")) - warn_format_nonliteral = 0; - else if (!strcmp (p, "-Wformat-security")) - warn_format_security = 1; - else if (!strcmp (p, "-Wno-format-security")) - warn_format_security = 0; - else if (!strcmp (p, "-Wchar-subscripts")) - warn_char_subscripts = 1; - else if (!strcmp (p, "-Wno-char-subscripts")) - warn_char_subscripts = 0; - else if (!strcmp (p, "-Wconversion")) - warn_conversion = 1; - else if (!strcmp (p, "-Wno-conversion")) - warn_conversion = 0; - else if (!strcmp (p, "-Wparentheses")) - warn_parentheses = 1; - else if (!strcmp (p, "-Wno-parentheses")) - warn_parentheses = 0; - else if (!strcmp (p, "-Wreturn-type")) - warn_return_type = 1; - else if (!strcmp (p, "-Wno-return-type")) - warn_return_type = 0; - else if (!strcmp (p, "-Wsequence-point")) - warn_sequence_point = 1; - else if (!strcmp (p, "-Wno-sequence-point")) - warn_sequence_point = 0; - else if (!strcmp (p, "-Wcomment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wcomments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wtrigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-trigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wundef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-undef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wimport")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-import")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wmissing-braces")) - warn_missing_braces = 1; - else if (!strcmp (p, "-Wno-missing-braces")) - warn_missing_braces = 0; - else if (!strcmp (p, "-Wmain")) - warn_main = 1; - else if (!strcmp (p, "-Wno-main")) - warn_main = -1; - else if (!strcmp (p, "-Wsign-compare")) - warn_sign_compare = 1; - else if (!strcmp (p, "-Wno-sign-compare")) - warn_sign_compare = 0; - else if (!strcmp (p, "-Wfloat-equal")) - warn_float_equal = 1; - else if (!strcmp (p, "-Wno-float-equal")) - warn_float_equal = 0; - else if (!strcmp (p, "-Wmultichar")) - warn_multichar = 1; - else if (!strcmp (p, "-Wno-multichar")) - warn_multichar = 0; - else if (!strcmp (p, "-Wdiv-by-zero")) - warn_div_by_zero = 1; - else if (!strcmp (p, "-Wno-div-by-zero")) - warn_div_by_zero = 0; - else if (!strcmp (p, "-Wunknown-pragmas")) - /* Set to greater than 1, so that even unknown pragmas in system - headers will be warned about. */ - warn_unknown_pragmas = 2; - else if (!strcmp (p, "-Wno-unknown-pragmas")) - warn_unknown_pragmas = 0; - else if (!strcmp (p, "-Wall")) - { - /* We save the value of warn_uninitialized, since if they put - -Wuninitialized on the command line, we need to generate a - warning about not using it without also specifying -O. */ - if (warn_uninitialized != 1) - warn_uninitialized = 2; - warn_implicit_int = 1; - mesg_implicit_function_declaration = 1; - warn_return_type = 1; - set_Wunused (1); - warn_switch = 1; - set_Wformat (1); - warn_char_subscripts = 1; - warn_parentheses = 1; - warn_sequence_point = 1; - warn_missing_braces = 1; - /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn - it off only if it's not explicit. */ - warn_main = 2; - /* Only warn about unknown pragmas that are not in system headers. */ - warn_unknown_pragmas = 1; - } - else - return strings_processed; - - return 1; -} - void c_print_identifier (file, node, indent) FILE *file; @@ -867,7 +327,7 @@ c_print_identifier (file, node, indent) for a top-level tentative array defn that wasn't complete before. */ void -finish_incomplete_decl (decl) +c_finish_incomplete_decl (decl) tree decl; { if (TREE_CODE (decl) == VAR_DECL) @@ -887,13 +347,33 @@ finish_incomplete_decl (decl) } } -/* Create a new `struct binding_level'. */ +/* Reuse or create a struct for this binding level. */ static struct binding_level * make_binding_level () { - /* NOSTRICT */ - return (struct binding_level *) xmalloc (sizeof (struct binding_level)); + if (free_binding_level) + { + struct binding_level *result = free_binding_level; + free_binding_level = result->level_chain; + return result; + } + else + return (struct binding_level *) ggc_alloc (sizeof (struct binding_level)); +} + +/* Remove a binding level from a list and add it to the level chain. */ + +static void +pop_binding_level (lp) + struct binding_level **lp; +{ + struct binding_level *l = *lp; + *lp = l->level_chain; + + memset (l, 0, sizeof (struct binding_level)); + l->level_chain = free_binding_level; + free_binding_level = l; } /* Nonzero if we are currently in the global binding level. */ @@ -961,17 +441,7 @@ pushlevel (tag_transparent) named_labels = 0; } - /* Reuse or create a struct for this binding level. */ - - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; - } - else - { - newlevel = make_binding_level (); - } + newlevel = make_binding_level (); /* Add this level to the front of the chain (stack) of levels that are active. */ @@ -1192,13 +662,7 @@ poplevel (keep, reverse, functionbody) /* Pop the current level, and free the structure for reuse. */ - { - struct binding_level *level = current_binding_level; - current_binding_level = current_binding_level->level_chain; - - level->level_chain = free_binding_level; - free_binding_level = level; - } + pop_binding_level (¤t_binding_level); /* Dispose of the block that we just made inside some higher level. */ if (functionbody) @@ -1277,17 +741,7 @@ push_label_level () { struct binding_level *newlevel; - /* Reuse or create a struct for this binding level. */ - - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; - } - else - { - newlevel = make_binding_level (); - } + newlevel = make_binding_level (); /* Add this level to the front of the chain (stack) of label levels. */ @@ -1349,9 +803,7 @@ pop_label_level () shadowed_labels = level->shadowed; /* Pop the current level, and free the structure for reuse. */ - label_level_chain = label_level_chain->level_chain; - level->level_chain = free_binding_level; - free_binding_level = level; + pop_binding_level (&label_level_chain); } /* Push a definition or a declaration of struct, union or enum tag "name". @@ -1516,14 +968,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level) match enough. Ultimately, copy most of the information from the new decl to the old one, and keep using the old one. */ - if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL - && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl - && DECL_INITIAL (olddecl) == 0) - /* If -traditional, avoid error for redeclaring fcn - after implicit decl. */ - ; - else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl)) + if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl)) { /* A function declaration for a built-in function. */ if (!TREE_PUBLIC (newdecl)) @@ -1690,7 +1135,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level) break; } - if (simple_type_promotes_to (type) != NULL_TREE) + if (c_type_promotes_to (type) != type) { error ("an argument type that has a default promotion can't match an empty parameter name list declaration"); break; @@ -1698,6 +1143,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level) } } error_with_decl (olddecl, "previous declaration of `%s'"); + + /* This is safer because the initializer might contain references + to variables that were declared between olddecl and newdecl. This + will make the initializer invalid for olddecl in case it gets + assigned to olddecl below. */ + if (TREE_CODE (newdecl) == VAR_DECL) + DECL_INITIAL (newdecl) = 0; + } + /* TLS cannot follow non-TLS declaration. */ + else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL + && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl)) + { + error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration"); + error_with_decl (olddecl, "previous declaration of `%s'"); + } + /* non-TLS declaration cannot follow TLS declaration. */ + else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL + && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl)) + { + error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration"); + error_with_decl (olddecl, "previous declaration of `%s'"); } else { @@ -1772,12 +1238,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level) } /* Type for passing arg must be consistent with that declared for the arg. */ - if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)) - /* If -traditional, allow `unsigned int' instead of `int' - in the prototype. */ - && (! (flag_traditional - && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node - && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))) + if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))) { error_with_decl (newdecl, "prototype for `%s' follows and argument %d doesn't match", @@ -1912,11 +1373,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level) COPY_DECL_RTL (olddecl, newdecl); /* Merge the type qualifiers. */ - if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) - && ! TREE_THIS_VOLATILE (newdecl)) - TREE_THIS_VOLATILE (write_olddecl) = 0; - if (TREE_READONLY (newdecl)) TREE_READONLY (write_olddecl) = 1; @@ -2230,10 +1686,7 @@ pushdecl (x) IDENTIFIER_POINTER (name)); t = lookup_name_current_level (name); - /* Don't type check externs here when -traditional. This is so that - code with conflicting declarations inside blocks will get warnings - not errors. X11 for instance depends on this. */ - if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) + if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { t = IDENTIFIER_GLOBAL_VALUE (name); /* Type decls at global scope don't conflict with externs declared @@ -2252,9 +1705,8 @@ pushdecl (x) } /* If this decl is `static' and an implicit decl was seen previously, - warn. But don't complain if -traditional, - since traditional compilers don't complain. */ - if (! flag_traditional && TREE_PUBLIC (name) + warn. */ + if (TREE_PUBLIC (name) /* Don't test for DECL_EXTERNAL, because grokdeclarator sets this for all functions. */ && ! TREE_PUBLIC (x) @@ -2286,7 +1738,7 @@ pushdecl (x) } /* If we are processing a typedef statement, generate a whole new - ..._TYPE node (which will be just an variant of the existing + ..._TYPE node (which will be just a variant of the existing ..._TYPE node with identical properties) and then install the TYPE_DECL node generated to represent the typedef name as the TYPE_NAME of this brand new (duplicate) ..._TYPE node. @@ -2348,9 +1800,6 @@ pushdecl (x) } /* Multiple external decls of the same identifier ought to match. - Check against both global declarations (when traditional) and out of - scope (limbo) block level declarations. - We get warnings about inline functions where they are defined. Avoid duplicate warnings where they are used. */ if (TREE_PUBLIC (x) @@ -2358,11 +1807,7 @@ pushdecl (x) { tree decl; - if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0 - && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) - || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))) - decl = IDENTIFIER_GLOBAL_VALUE (name); - else if (IDENTIFIER_LIMBO_VALUE (name) != 0) + if (IDENTIFIER_LIMBO_VALUE (name) != 0) /* Decls in limbo are always extern, so no need to check that. */ decl = IDENTIFIER_LIMBO_VALUE (name); else @@ -2392,39 +1837,6 @@ pushdecl (x) "previous implicit declaration of `%s'"); } - /* In PCC-compatibility mode, extern decls of vars with no current decl - take effect at top level no matter where they are. */ - if (flag_traditional && DECL_EXTERNAL (x) - && lookup_name (name) == 0) - { - tree type = TREE_TYPE (x); - - /* But don't do this if the type contains temporary nodes. */ - while (type) - { - if (type == error_mark_node) - break; - if (TYPE_CONTEXT (type)) - { - warning_with_decl (x, "type of external `%s' is not global"); - /* By exiting the loop early, we leave TYPE nonzero, - and thus prevent globalization of the decl. */ - break; - } - else if (TREE_CODE (type) == FUNCTION_TYPE - && TYPE_ARG_TYPES (type) != 0) - /* The types might not be truly local, - but the list of arg types certainly is temporary. - Since prototypes are nontraditional, - ok not to do the traditional thing. */ - break; - type = TREE_TYPE (type); - } - - if (type == 0) - b = global_binding_level; - } - /* This name is new in its binding level. Install the new declaration and return it. */ if (b == global_binding_level) @@ -2581,7 +1993,7 @@ pushdecl (x) b->shadowed = tree_cons (name, oldlocal, b->shadowed); } - /* Keep count of variables in this level with incomplete type. + /* Keep list of variables in this level with incomplete type. If the input is erroneous, we can have error_mark in the type slot (e.g. "f(void a, ...)") - that doesn't count as an incomplete type. */ @@ -2594,7 +2006,7 @@ pushdecl (x) element = TREE_TYPE (element); if (TREE_CODE (element) == RECORD_TYPE || TREE_CODE (element) == UNION_TYPE) - ++b->n_incomplete; + b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list); } } @@ -2658,12 +2070,12 @@ implicitly_declare (functionid) IDENTIFIER_IMPLICIT_DECL (functionid) = decl; /* ANSI standard says implicit declarations are in the innermost block. - So we record the decl in the standard fashion. - If flag_traditional is set, pushdecl does it top-level. */ + So we record the decl in the standard fashion. */ pushdecl (decl); - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (flag_objc) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, 0, 0); @@ -2707,17 +2119,8 @@ redeclaration_error_message (newdecl, olddecl) { if (TREE_CODE (newdecl) == TYPE_DECL) { - if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl)) - return 0; - /* pushdecl creates distinct types for TYPE_DECLs by calling - build_type_copy, so the above comparison generally fails. We do - another test against the TYPE_MAIN_VARIANT of the olddecl, which - is equivalent to what this code used to do before the build_type_copy - call. The variant type distinction should not matter for traditional - code, because it doesn't have type qualifiers. */ - if (flag_traditional - && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl)) - return 0; + /* Do not complain about type redeclarations where at least one + declaration was in a system header. */ if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl)) return 0; return 1; @@ -3063,25 +2466,6 @@ lookup_name_current_level (name) return t; } -/* Mark ARG for GC. */ - -static void -mark_binding_level (arg) - void *arg; -{ - struct binding_level *level = *(struct binding_level **) arg; - - for (; level != 0; level = level->level_chain) - { - ggc_mark_tree (level->names); - ggc_mark_tree (level->tags); - ggc_mark_tree (level->shadowed); - ggc_mark_tree (level->blocks); - ggc_mark_tree (level->this_block); - ggc_mark_tree (level->parm_order); - } -} - /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. @@ -3135,22 +2519,6 @@ c_init_decl_processing () make_fname_decl = c_make_fname_decl; start_fname_decls (); - - incomplete_decl_finalize_hook = finish_incomplete_decl; - - /* Record our roots. */ - - ggc_add_tree_root (c_global_trees, CTI_MAX); - ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree); - ggc_add_tree_root (&c_scope_stmt_stack, 1); - ggc_add_tree_root (&named_labels, 1); - ggc_add_tree_root (&shadowed_labels, 1); - ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level, - mark_binding_level); - ggc_add_root (&label_level_chain, 1, sizeof label_level_chain, - mark_binding_level); - ggc_add_tree_root (&static_ctors, 1); - ggc_add_tree_root (&static_dtors, 1); } /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the @@ -3199,24 +2567,21 @@ c_make_fname_decl (id, type_dep) 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. */ + 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 (name, type, function_code, class, library_name) +builtin_function (name, type, function_code, class, library_name, attrs) const char *name; tree type; int function_code; enum built_in_class class; const char *library_name; + tree attrs; { tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; - /* If -traditional, permit redefining a builtin function any way you like. - (Though really, if the program redefines these functions, - it probably won't work right unless compiled with -fno-builtin.) */ - if (flag_traditional && name[0] != '_') - DECL_BUILT_IN_NONANSI (decl) = 1; if (library_name) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); make_decl_rtl (decl, NULL); @@ -3224,17 +2589,16 @@ builtin_function (name, type, function_code, class, library_name) DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = function_code; - /* The return builtins leave the current function. */ - if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN) - TREE_THIS_VOLATILE (decl) = 1; - /* Warn if a function in the namespace for users is used without an occasion to consider it declared. */ if (name[0] != '_' || name[1] != '_') C_DECL_ANTICIPATED (decl) = 1; /* Possibly apply some default attributes to this built-in function. */ - decl_attributes (&decl, NULL_TREE, 0); + if (attrs) + decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN); + else + decl_attributes (&decl, NULL_TREE, 0); return decl; } @@ -3243,7 +2607,7 @@ builtin_function (name, type, function_code, class, library_name) attributes. */ void -insert_default_attributes (decl) +c_insert_default_attributes (decl) tree decl; { if (!TREE_PUBLIC (decl)) @@ -3340,8 +2704,8 @@ shadow_tag_warned (declspecs, warned) /* 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 - non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P - is non-zero is the array is [*], a VLA of unspecified length which is + nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P + is nonzero is the array is [*], a VLA of unspecified length which is nevertheless a complete type (not currently implemented by GCC), zero otherwise. The declarator is constructed as an ARRAY_REF (to be decoded by grokdeclarator), whose operand 0 is what's on the @@ -3363,9 +2727,9 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p) if (pedantic && !flag_isoc99) { if (static_p || quals != NULL_TREE) - pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators"); + pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators"); if (vla_unspec_p) - pedwarn ("ISO C89 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"); @@ -3374,7 +2738,7 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p) /* 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 non-zero if it is an + 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. */ @@ -3550,9 +2914,19 @@ start_decl (declarator, declspecs, initialized, attributes) /* ANSI specifies that a tentative definition which is not merged with a non-tentative definition behaves exactly like a definition with an initializer equal to zero. (Section 3.7.2) - -fno-common gives strict ANSI behavior. Usually you don't want it. - This matters only for variables with external linkage. */ - if (! flag_no_common || ! TREE_PUBLIC (decl)) + + -fno-common gives strict ANSI behavior, though this tends to break + a large body of code that grew up without this rule. + + Thread-local variables are never common, since there's no entrenched + body of code to break, and it allows more efficient variable references + in the presense of dynamic linking. */ + + if (TREE_CODE (decl) == VAR_DECL + && !initialized + && TREE_PUBLIC (decl) + && !DECL_THREAD_LOCAL (decl) + && !flag_no_common) DECL_COMMON (decl) = 1; /* Set attributes here so if duplicate decl, will have proper attributes. */ @@ -3723,8 +3097,9 @@ finish_decl (decl, init, asmspec_tree) if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (flag_objc) + objc_check_decl (decl); if (!DECL_CONTEXT (decl)) { @@ -3786,8 +3161,9 @@ finish_decl (decl, init, asmspec_tree) if (TREE_CODE (decl) == TYPE_DECL) { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (flag_objc) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0); } @@ -3796,17 +3172,41 @@ finish_decl (decl, init, asmspec_tree) computing them in the following function definition. */ if (current_binding_level == global_binding_level) get_pending_sizes (); -} -/* If DECL has a cleanup, build and return that cleanup here. - This is a callback called by expand_expr. */ + /* Install a cleanup (aka destructor) if one was given. */ + if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)) + { + tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl)); + if (attr) + { + static bool eh_initialized_p; -tree -maybe_build_cleanup (decl) - tree decl ATTRIBUTE_UNUSED; -{ - /* There are no cleanups in C. */ - return NULL_TREE; + tree cleanup_id = TREE_VALUE (TREE_VALUE (attr)); + tree cleanup_decl = lookup_name (cleanup_id); + tree cleanup; + + /* Build "cleanup(&decl)" for the destructor. */ + cleanup = build_unary_op (ADDR_EXPR, decl, 0); + cleanup = build_tree_list (NULL_TREE, cleanup); + cleanup = build_function_call (cleanup_decl, cleanup); + + /* Don't warn about decl unused; the cleanup uses it. */ + TREE_USED (decl) = 1; + + /* Initialize EH, if we've been told to do so. */ + if (flag_exceptions && !eh_initialized_p) + { + eh_initialized_p = true; + eh_personality_libfunc + = init_one_libfunc (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + using_eh_for_cleanups (); + } + + add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); + } + } } /* Given a parsed parameter declaration, @@ -3991,6 +3391,40 @@ complete_array_type (type, initial_value, do_default) return value; } +/* Determine whether TYPE is a structure with a flexible array member, + or a union containing such a structure (possibly recursively). */ + +static bool +flexible_array_type_p (type) + tree type; +{ + tree x; + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + x = TYPE_FIELDS (type); + if (x == NULL_TREE) + return false; + while (TREE_CHAIN (x) != NULL_TREE) + x = TREE_CHAIN (x); + if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE + && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE + && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) + return true; + return false; + case UNION_TYPE: + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x)) + { + if (flexible_array_type_p (TREE_TYPE (x))) + return true; + } + return false; + default: + return false; + } +} + /* Given declspecs and a declarator, determine the name and type of the object declared and construct a ..._DECL node for it. @@ -4142,7 +3576,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) enum rid i = C_RID_CODE (id); if ((int) i <= (int) RID_LAST_MODIFIER) { - if (i == RID_LONG && (specbits & (1 << (int) i))) + if (i == RID_LONG && (specbits & (1 << (int) RID_LONG))) { if (longlong) error ("`long long long' is too long for GCC"); @@ -4150,12 +3584,33 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { if (pedantic && !flag_isoc99 && ! in_system_header && warn_long_long) - pedwarn ("ISO C89 does not support `long long'"); + pedwarn ("ISO C90 does not support `long long'"); longlong = 1; } } else if (specbits & (1 << (int) i)) - pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + { + if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT) + { + if (!flag_isoc99) + pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + else + error ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + + /* Diagnose "__thread extern". Recall that this list + is in the reverse order seen in the text. */ + if (i == RID_THREAD + && (specbits & (1 << (int) RID_EXTERN + | 1 << (int) RID_STATIC))) + { + if (specbits & 1 << (int) RID_EXTERN) + error ("`__thread' before `extern'"); + else + error ("`__thread' before `static'"); + } + specbits |= 1 << (int) i; goto found; } @@ -4275,12 +3730,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else { ok = 1; - if (!explicit_int && !defaulted_int && !explicit_char && pedantic) + if (!explicit_int && !defaulted_int && !explicit_char) { - pedwarn ("long, short, signed or unsigned used invalidly for `%s'", - name); - if (flag_pedantic_errors) - ok = 0; + error ("long, short, signed or unsigned used invalidly for `%s'", + name); + ok = 0; } } @@ -4303,9 +3757,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Decide whether an integer type is signed or not. Optionally treat bitfields as signed by default. */ if (specbits & 1 << (int) RID_UNSIGNED - /* Traditionally, all bitfields are unsigned. */ - || (bitfield && flag_traditional - && (! explicit_flag_signed_bitfields || !flag_signed_bitfields)) || (bitfield && ! flag_signed_bitfields && (explicit_int || defaulted_int || explicit_char /* A typedef for plain `int' without `signed' @@ -4324,7 +3775,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else if (type == char_type_node) type = unsigned_char_type_node; else if (typedef_decl) - type = unsigned_type (type); + type = c_common_unsigned_type (type); else type = unsigned_type_node; } @@ -4341,7 +3792,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (specbits & 1 << (int) RID_COMPLEX) { if (pedantic && !flag_isoc99) - pedwarn ("ISO C89 does not support complex types"); + 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 @@ -4408,6 +3859,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) 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.). */ @@ -4417,7 +3874,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) && (specbits & ((1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) - | (1 << (int) RID_TYPEDEF)))) + | (1 << (int) RID_TYPEDEF) + | (1 << (int) RID_THREAD)))) { if (specbits & 1 << (int) RID_AUTO && (pedantic || current_binding_level == global_binding_level)) @@ -4426,8 +3884,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) 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_AUTO) | (1 << (int) RID_THREAD)); } else if (decl_context != NORMAL && nclasses > 0) { @@ -4450,7 +3910,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC) - | (1 << (int) RID_EXTERN)); + | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD)); } } else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag) @@ -4461,12 +3921,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else error ("`%s' has both `extern' and initializer", name); } - else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag - && current_binding_level != global_binding_level) - error ("nested function `%s' declared `extern'", name); - else if (current_binding_level == global_binding_level - && specbits & (1 << (int) RID_AUTO)) - error ("top-level declaration of `%s' specifies `auto'", name); + else if (current_binding_level == global_binding_level) + { + if (specbits & 1 << (int) RID_AUTO) + error ("top-level 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. @@ -4534,7 +4007,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) tree itype = NULL_TREE; tree size = TREE_OPERAND (declarator, 1); /* The index is a signed object `sizetype' bits wide. */ - tree index_type = signed_type (sizetype); + tree index_type = c_common_signed_type (sizetype); array_ptr_quals = TREE_TYPE (declarator); array_parm_static = TREE_STATIC (declarator); @@ -4555,6 +4028,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) type = error_mark_node; } + if (pedantic && flexible_array_type_p (type)) + pedwarn ("invalid use of structure with flexible array member"); + if (size == error_mark_node) type = error_mark_node; @@ -4597,10 +4073,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (!flag_isoc99 && pedantic) { if (TREE_CONSTANT (size)) - pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated", + pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated", name); else - pedwarn ("ISO C89 forbids variable-size array `%s'", + pedwarn ("ISO C90 forbids variable-size array `%s'", name); } } @@ -4636,14 +4112,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } if (size_varies) - itype = variable_size (itype); + { + /* We must be able to distinguish the + SAVE_EXPR_CONTEXT for the variably-sized type + so that we can set it correctly in + set_save_expr_context. The convention is + that all SAVE_EXPRs that need to be reset + have NULL_TREE for their SAVE_EXPR_CONTEXT. */ + tree cfd = current_function_decl; + if (decl_context == PARM) + current_function_decl = NULL_TREE; + itype = variable_size (itype); + if (decl_context == PARM) + current_function_decl = cfd; + } itype = build_index_type (itype); } } else if (decl_context == FIELD) { if (pedantic && !flag_isoc99 && !in_system_header) - pedwarn ("ISO C89 does not support flexible array members"); + pedwarn ("ISO C90 does not support flexible array members"); /* ISO C99 Flexible array members are effectively identical to GCC's zero-length array extension. */ @@ -4715,13 +4204,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) type = integer_type_node; } -#ifndef TRADITIONAL_RETURN_FLOAT - /* Traditionally, declaring return type float means double. */ - - if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) - type = double_type_node; -#endif /* TRADITIONAL_RETURN_FLOAT */ - /* Construct the function type and go to the next inner layer of declarator. */ @@ -5009,11 +4491,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (type == error_mark_node) promoted_type = type; else - { - promoted_type = simple_type_promotes_to (type); - if (! promoted_type) - promoted_type = type; - } + promoted_type = c_type_promotes_to (type); DECL_ARG_TYPE (decl) = promoted_type; DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; @@ -5065,6 +4543,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) 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 top level. Storage classes other than `extern' are not allowed and `extern' makes no difference. */ @@ -5124,6 +4604,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) needed, and let dwarf2 know that the function is inlinable. */ else if (flag_inline_trees == 2 && initialized) { + if (!DECL_INLINE (decl)) + DID_INLINE_FUNC (decl) = 1; DECL_INLINE (decl) = 1; DECL_DECLARED_INLINE_P (decl) = 0; } @@ -5157,22 +4639,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) pedwarn_with_decl (decl, "variable `%s' declared `inline'"); DECL_EXTERNAL (decl) = extern_ref; + /* At top level, 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. */ if (current_binding_level == global_binding_level) { - TREE_PUBLIC (decl) - = !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))); - TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); + TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) + | (1 << (int) RID_REGISTER))); + TREE_STATIC (decl) = !extern_ref; } /* Not at top level, only `static' makes a static definition. */ else { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; - TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); + TREE_PUBLIC (decl) = extern_ref; + } + + if (specbits & 1 << (int) RID_THREAD) + { + if (targetm.have_tls) + DECL_THREAD_LOCAL (decl) = 1; + else + /* A mere warning is sure to result in improper semantics + at runtime. Don't bother to allow this to compile. */ + error ("thread-local storage not supported for this target"); } } @@ -5189,7 +4681,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) Otherwise, the fact that those components are volatile will be ignored, and would even crash the compiler. */ if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))) - mark_addressable (decl); + c_mark_addressable (decl); decl_attributes (&decl, returned_attrs, 0); @@ -5524,25 +5016,22 @@ start_struct (code, name) ref = lookup_tag (code, name, current_binding_level, 1); if (ref && TREE_CODE (ref) == code) { - C_TYPE_BEING_DEFINED (ref) = 1; - TYPE_PACKED (ref) = flag_pack_struct; if (TYPE_FIELDS (ref)) { if (code == UNION_TYPE) - error ("redefinition of `union %s'", - IDENTIFIER_POINTER (name)); + error ("redefinition of `union %s'", IDENTIFIER_POINTER (name)); else - error ("redefinition of `struct %s'", - IDENTIFIER_POINTER (name)); + error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name)); } - - return ref; } + 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. */ - - ref = make_node (code); - pushtag (name, ref); + ref = make_node (code); + pushtag (name, ref); + } + C_TYPE_BEING_DEFINED (ref) = 1; TYPE_PACKED (ref) = flag_pack_struct; return ref; @@ -5566,15 +5055,44 @@ grokfield (filename, line, declarator, declspecs, width) if (declarator == NULL_TREE && width == NULL_TREE) { - /* This is an unnamed decl. We only support unnamed - structs/unions, so check for other things and refuse them. */ + /* This is an unnamed decl. + + If we have something of the form "union { list } ;" then this + is the anonymous union extension. Similarly for struct. + + If this is something of the form "struct foo;", then + If MS extensions are enabled, this is handled as an + anonymous struct. + Otherwise this is a forward declaration of a structure tag. + + If this is something of the form "foo;" and foo is a TYPE_DECL, then + If MS extensions are enabled and foo names a structure, then + again this is an anonymous struct. + Otherwise this is an error. + + Oh what a horrid tangled web we weave. I wonder if MS consiously + 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); - if (TREE_CODE (type) == TYPE_DECL) + 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 (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) { - error ("unnamed fields of type other than struct or union are not allowed"); + if (flag_ms_extensions) + ; /* ok */ + else if (flag_iso) + goto warn_unnamed_field; + else if (TYPE_NAME (type) == NULL) + ; /* ok */ + else + goto warn_unnamed_field; + } + else + { + warn_unnamed_field: + warning ("declaration does not declare anything"); return NULL_TREE; } } @@ -5584,7 +5102,8 @@ grokfield (filename, line, declarator, declspecs, width) finish_decl (value, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; - maybe_objc_check_decl (value); + if (flag_objc) + objc_check_decl (value); return value; } @@ -5617,7 +5136,7 @@ finish_struct (t, fieldlist, attributes) if (pedantic) pedwarn ("%s defined inside parms", TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure")); - else if (! flag_traditional) + else warning ("%s defined inside parms", TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure")); } @@ -5760,18 +5279,6 @@ finish_struct (t, fieldlist, attributes) } } - else if (TREE_TYPE (x) != error_mark_node) - { - unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT - : TYPE_ALIGN (TREE_TYPE (x))); - - /* Non-bit-fields are aligned for their type, except packed - fields which require only BITS_PER_UNIT alignment. */ - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align); - if (! DECL_PACKED (x)) - DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x)); - } - DECL_INITIAL (x) = 0; /* Detect flexible array member in an invalid context. */ @@ -5787,6 +5294,11 @@ finish_struct (t, fieldlist, attributes) else if (! saw_named_field) error_with_decl (x, "flexible array member in otherwise empty struct"); } + + if (pedantic && TREE_CODE (t) == RECORD_TYPE + && flexible_array_type_p (TREE_TYPE (x))) + pedwarn_with_decl (x, "invalid use of structure with flexible array member"); + if (DECL_NAME (x)) saw_named_field = 1; } @@ -5860,22 +5372,29 @@ finish_struct (t, fieldlist, attributes) /* If this structure or union completes the type of any previous variable declaration, lay it out and output its rtl. */ - if (current_binding_level->n_incomplete != 0) + if (current_binding_level->incomplete_list != NULL_TREE) { - tree decl; - for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) - { + tree prev = NULL_TREE; + + for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x)) + { + tree decl = TREE_VALUE (x); + if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t) && TREE_CODE (decl) != TYPE_DECL) { layout_decl (decl, 0); - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (flag_objc) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, toplevel, 0); if (! toplevel) expand_decl (decl); - if (--current_binding_level->n_incomplete == 0) - break; + /* Unlink X from the incomplete list. */ + if (prev) + TREE_CHAIN (prev) = TREE_CHAIN (x); + else + current_binding_level->incomplete_list = TREE_CHAIN (x); } else if (!COMPLETE_TYPE_P (TREE_TYPE (decl)) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) @@ -5889,13 +5408,17 @@ finish_struct (t, fieldlist, attributes) if (TREE_CODE (decl) != TYPE_DECL) { layout_decl (decl, 0); - maybe_objc_check_decl (decl); + if (flag_objc) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, toplevel, 0); if (! toplevel) expand_decl (decl); } - if (--current_binding_level->n_incomplete == 0) - break; + /* Unlink X from the incomplete list. */ + if (prev) + TREE_CHAIN (prev) = TREE_CHAIN (x); + else + current_binding_level->incomplete_list = TREE_CHAIN (x); } } } @@ -6012,7 +5535,7 @@ finish_enum (enumtype, values, attributes) min_precision (maxnode, unsign)); if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) { - tree narrowest = type_for_size (precision, unsign); + tree narrowest = c_common_type_for_size (precision, unsign); if (narrowest == 0) { warning ("enumeration values exceed range of largest integer"); @@ -6025,7 +5548,7 @@ finish_enum (enumtype, values, attributes) precision = TYPE_PRECISION (integer_type_node); if (precision == TYPE_PRECISION (integer_type_node)) - enum_value_type = type_for_size (precision, 0); + enum_value_type = c_common_type_for_size (precision, 0); else enum_value_type = enumtype; @@ -6153,11 +5676,11 @@ build_enumerator (name, value) /* Now create a declaration for the enum value name. */ type = TREE_TYPE (value); - type = type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - ((flag_traditional - || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)) - && TREE_UNSIGNED (type))); + type = c_common_type_for_size (MAX (TYPE_PRECISION (type), + TYPE_PRECISION (integer_type_node)), + (TYPE_PRECISION (type) + >= TYPE_PRECISION (integer_type_node) + && TREE_UNSIGNED (type))); decl = build_decl (CONST_DECL, name, type); DECL_INITIAL (decl) = convert (type, value); @@ -6192,7 +5715,6 @@ start_function (declspecs, declarator, attributes) current_function_returns_abnormally = 0; warn_about_return_type = 0; current_extern_inline = 0; - c_function_varargs = 0; named_labels = 0; shadowed_labels = 0; @@ -6391,12 +5913,10 @@ start_function (declspecs, declarator, attributes) /* Promote the value to int before returning it. */ if (c_promoting_integer_type_p (restype)) { - /* It retains unsignedness if traditional - or if not really getting wider. */ + /* It retains unsignedness if not really getting wider. */ if (TREE_UNSIGNED (restype) - && (flag_traditional - || (TYPE_PRECISION (restype) - == TYPE_PRECISION (integer_type_node)))) + && (TYPE_PRECISION (restype) + == TYPE_PRECISION (integer_type_node))) restype = unsigned_type_node; else restype = integer_type_node; @@ -6415,16 +5935,6 @@ start_function (declspecs, declarator, attributes) return 1; } - -/* Record that this function is going to be a varargs function. - This is called before store_parm_decls, which is too early - to call mark_varargs directly. */ - -void -c_mark_varargs () -{ - c_function_varargs = 1; -} /* Store the parameter declarations into the current function declaration. This is called after parsing the parameter declarations, before @@ -6615,15 +6125,6 @@ store_parm_decls () layout_decl (found, 0); } - /* Traditionally, a parm declared float is actually a double. */ - if (found && flag_traditional - && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node) - { - TREE_TYPE (found) = double_type_node; - DECL_ARG_TYPE (found) = double_type_node; - layout_decl (found, 0); - } - /* If no declaration found, default to int. */ if (!found) { @@ -6757,11 +6258,7 @@ store_parm_decls () "prototype declaration"); } } - /* If -traditional, allow `int' argument to match - `unsigned' prototype. */ - else if (! (flag_traditional - && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node - && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)) + else { error ("argument `%s' doesn't match prototype", IDENTIFIER_POINTER (DECL_NAME (parm))); @@ -6896,13 +6393,6 @@ finish_function (nested, can_defer_p) DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; - /* Obey `register' declarations if `setjmp' is called in this fn. */ - if (flag_traditional && current_function_calls_setjmp) - { - setjmp_protect (DECL_INITIAL (fndecl)); - setjmp_protect_args (); - } - if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted) { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) @@ -6959,7 +6449,7 @@ finish_function (nested, can_defer_p) /* Let the error reporting routines know that we're outside a function. For a nested function, this value is used in - pop_c_function_context and then reset via pop_function_context. */ + c_pop_function_context and then reset via pop_function_context. */ current_function_decl = NULL; } } @@ -6979,7 +6469,27 @@ c_expand_deferred_function (fndecl) } } -/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero, +/* Called to move the SAVE_EXPRs for parameter declarations in a + nested function into the nested function. DATA is really the + nested FUNCTION_DECL. */ + +static tree +set_save_expr_context (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees; + void *data; +{ + if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp)) + SAVE_EXPR_CONTEXT (*tp) = (tree) data; + /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause + circularity. */ + else if (DECL_P (*tp)) + *walk_subtrees = 0; + + return NULL_TREE; +} + +/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero, then we are already in the process of generating RTL for another function. If can_defer_p is zero, we won't attempt to defer the generation of RTL. */ @@ -6990,12 +6500,19 @@ c_expand_body (fndecl, nested_p, can_defer_p) int nested_p, can_defer_p; { int uninlinable = 1; + int saved_lineno; + const char *saved_input_filename; /* There's no reason to do any of the work here if we're only doing semantic analysis; this code just generates RTL. */ if (flag_syntax_only) return; + saved_lineno = lineno; + saved_input_filename = input_filename; + lineno = DECL_SOURCE_LINE (fndecl); + input_filename = DECL_SOURCE_FILE (fndecl); + if (flag_inline_trees) { /* First, cache whether the current function is inlinable. Some @@ -7013,6 +6530,8 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Let the back-end know that this function exists. */ (*debug_hooks->deferred_inline_function) (fndecl); timevar_pop (TV_INTEGRATION); + lineno = saved_lineno; + input_filename = saved_input_filename; return; } @@ -7034,7 +6553,6 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Initialize the RTL code for the function. */ current_function_decl = fndecl; - input_filename = DECL_SOURCE_FILE (fndecl); init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl)); /* This function is being processed in whole-function mode. */ @@ -7047,13 +6565,18 @@ c_expand_body (fndecl, nested_p, can_defer_p) immediate_size_expand = 0; cfun->x_dont_save_pending_sizes_p = 1; - /* If this is a varargs function, inform function.c. */ - if (c_function_varargs) - mark_varargs (); - /* Set up parameters and prepare for return, for the function. */ expand_function_start (fndecl, 0); + /* If the function has a variably modified type, there may be + SAVE_EXPRs in the parameter types. Their context must be set to + refer to this function; they cannot be expanded in the containing + function. */ + if (decl_function_context (fndecl) + && variably_modified_type_p (TREE_TYPE (fndecl))) + walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl, + NULL); + /* If this function is `main', emit a call to `__main' to run global initializers, etc. */ if (DECL_NAME (fndecl) @@ -7063,7 +6586,9 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Generate the RTL for this function. */ expand_stmt (DECL_SAVED_TREE (fndecl)); - if (uninlinable) + + /* Keep the function body if it's needed for inlining or dumping. */ + if (uninlinable && !dump_enabled_p (TDI_all)) { /* Allow the body of the function to be garbage collected. */ DECL_SAVED_TREE (fndecl) = NULL_TREE; @@ -7134,7 +6659,7 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Stop pointing to the local nodes about to be freed. But DECL_INITIAL must remain nonzero so we know this was an actual function definition. - For a nested function, this is done in pop_c_function_context. + For a nested function, this is done in c_pop_function_context. If rest_of_compilation set this to 0, leave it 0. */ if (DECL_INITIAL (fndecl) != 0) DECL_INITIAL (fndecl) = error_mark_node; @@ -7164,6 +6689,9 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Return to the enclosing function. */ pop_function_context (); timevar_pop (TV_EXPAND); + + lineno = saved_lineno; + input_filename = saved_input_filename; } /* Check the declarations given in a for-loop for satisfying the C99 @@ -7228,9 +6756,9 @@ check_for_loop_decls () that keep track of the progress of compilation of the current function. Used for nested functions. */ -struct c_language_function +struct language_function GTY(()) { - struct language_function base; + struct c_language_function base; tree named_labels; tree shadowed_labels; int returns_value; @@ -7245,13 +6773,13 @@ struct c_language_function used during compilation of a C function. */ void -push_c_function_context (f) +c_push_function_context (f) struct function *f; { - struct c_language_function *p; - p = ((struct c_language_function *) - xmalloc (sizeof (struct c_language_function))); - f->language = (struct language_function *) p; + struct language_function *p; + p = ((struct language_function *) + ggc_alloc (sizeof (struct language_function))); + f->language = p; p->base.x_stmt_tree = c_stmt_tree; p->base.x_scope_stmt_stack = c_scope_stmt_stack; @@ -7268,11 +6796,10 @@ push_c_function_context (f) /* Restore the variables used during compilation of a C function. */ void -pop_c_function_context (f) +c_pop_function_context (f) struct function *f; { - struct c_language_function *p - = (struct c_language_function *) f->language; + struct language_function *p = f->language; tree link; /* Bring back all the labels that were shadowed. */ @@ -7302,32 +6829,13 @@ pop_c_function_context (f) current_extern_inline = p->extern_inline; current_binding_level = p->binding_level; - free (p); - f->language = 0; -} - -/* Mark the language specific parts of F for GC. */ - -void -mark_c_function_context (f) - struct function *f; -{ - struct c_language_function *p - = (struct c_language_function *) f->language; - - if (p == 0) - return; - - mark_c_language_function (&p->base); - ggc_mark_tree (p->shadowed_labels); - ggc_mark_tree (p->named_labels); - mark_binding_level (&p->binding_level); + f->language = NULL; } -/* Copy the DECL_LANG_SPECIFIC data associated with NODE. */ +/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */ void -copy_lang_decl (decl) +c_dup_lang_specific_decl (decl) tree decl; { struct lang_decl *ld; @@ -7341,38 +6849,12 @@ copy_lang_decl (decl) DECL_LANG_SPECIFIC (decl) = ld; } -/* Mark the language specific bits in T for GC. */ - -void -lang_mark_tree (t) - tree t; -{ - if (TREE_CODE (t) == IDENTIFIER_NODE) - { - struct lang_identifier *i = (struct lang_identifier *) t; - ggc_mark_tree (i->global_value); - ggc_mark_tree (i->local_value); - ggc_mark_tree (i->label_value); - ggc_mark_tree (i->implicit_decl); - ggc_mark_tree (i->error_locus); - ggc_mark_tree (i->limbo_value); - } - else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t)) - ggc_mark (TYPE_LANG_SPECIFIC (t)); - else if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) - { - ggc_mark (DECL_LANG_SPECIFIC (t)); - c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base); - ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes); - } -} - /* The functions below are required for functionality of doing function at once processing in the C front end. Currently these functions are not called from anywhere in the C front end, but as these changes continue, that will change. */ -/* Returns non-zero if the current statement is a full expression, +/* Returns nonzero if the current statement is a full expression, i.e. temporaries created during that statement should be destroyed at the end of the statement. */ @@ -7481,3 +6963,26 @@ build_void_list_node () tree t = build_tree_list (NULL_TREE, void_type_node); return t; } + +/* 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. + + We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST, + if attributes are present) and whose type is the modifier list. */ + +tree +make_pointer_declarator (type_quals_attrs, target) + tree type_quals_attrs, target; +{ + 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); +} + +#include "gt-c-decl.h" |