X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-decl.c;h=dba2737182eb02c9a2f6825b45d1793fdf1ca43f;hb=d10cfa8dc0e0c46fb4ebdcbb957029727bc8fe21;hp=61cafffdeef895f0f8acd9486370feea72b877d6;hpb=8a007b43216d680ce214e65284a165d490804102;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 61cafffdeef..dba2737182e 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -282,151 +282,8 @@ 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)); -/* 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 enable C89 Amendment 1 features. */ - -int flag_isoc94 = 0; - -/* Nonzero means use the ISO C99 dialect of C. */ - -int flag_isoc99 = 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 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 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 `$' 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 @@ -439,268 +296,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]; - - static const struct { - /* The name of the option. */ - const char *option; - /* A pointer to a flag variable to set to 0 or 1. */ - int *flag; - } warn_options[] = { - /* This list is in alphabetical order. Keep it like that. */ - { "bad-function-cast", &warn_bad_function_cast }, - { "cast-qual", &warn_cast_qual }, - { "char-subscripts", &warn_char_subscripts }, - { "conversion", &warn_conversion }, - { "div-by-zero", &warn_div_by_zero }, - { "float-equal", &warn_float_equal }, - { "format-extra-args", &warn_format_extra_args }, - { "format-zero-length", &warn_format_zero_length }, - { "format-nonliteral", &warn_format_nonliteral }, - { "format-security", &warn_format_security }, - { "format-y2k", &warn_format_y2k }, - { "implicit-function-declaration", &mesg_implicit_function_declaration }, - { "implicit-int", &warn_implicit_int }, - { "long-long", &warn_long_long }, - { "main", &warn_main }, - { "missing-braces", &warn_missing_braces }, - { "missing-declarations", &warn_missing_declarations }, - { "missing-format-attribute", &warn_missing_format_attribute }, - { "missing-prototypes", &warn_missing_prototypes }, - { "multichar", &warn_multichar }, - { "nested-externs", &warn_nested_externs }, - { "nonnull", &warn_nonnull }, - { "parentheses", &warn_parentheses }, - { "pointer-arith", &warn_pointer_arith }, - { "redundant-decls", &warn_redundant_decls }, - { "return-type", &warn_return_type }, - { "sequence-point", &warn_sequence_point }, - { "sign-compare", &warn_sign_compare }, - { "strict-prototypes", &warn_strict_prototypes }, - { "traditional", &warn_traditional }, - { "write-strings", &flag_const_strings } - }; - - strings_processed = cpp_handle_option (parse_in, argc, argv); - - 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 (!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 - */ - const char *const argstart = &p[5]; - - if (!strcmp (argstart, "iso9899:1990") - || !strcmp (argstart, "c89")) - { - iso_1990: - flag_isoc94 = 0; - iso_1994: - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_noniso_default_format_attributes = 0; - flag_isoc99 = 0; - flag_iso = 1; - } - 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_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_iso = 1; - } - else if (!strcmp (argstart, "gnu89")) - { - 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; - } - else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99")) - { - 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; - } - else if (!strcmp (argstart, "c++98")) - ; /* Handled by cpplib. */ - 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, "-fms-extensions")) - flag_ms_extensions = 1; - else if (!strcmp (p, "-fno-ms-extensions")) - flag_ms_extensions = 0; - 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, "-undef")) - flag_undef = 1; - else if (!strcmp (p, "-Werror-implicit-function-declaration")) - mesg_implicit_function_declaration = 2; - 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, "-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, "-Wno-main")) - warn_main = -1; - 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 if (!strcmp (p, "-E")) - flag_preprocess_only = 1; - else - { - size_t i; - for (i = 0; i < ARRAY_SIZE (warn_options); i++) - if (strncmp (p, "-W", 2) == 0 - && (strcmp (p+2, warn_options[i].option) == 0 - || (strncmp (p+2, "no-", 3) == 0 - && strcmp (p+5, warn_options[i].option) == 0))) - { - *(warn_options[i].flag) = strncmp (p+2, "no-", 3) != 0; - return 1; - } - return strings_processed; - } - - return 1; -} - void c_print_identifier (file, node, indent) FILE *file; @@ -1544,6 +1139,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level) } error_with_decl (olddecl, "previous declaration of `%s'"); } + /* 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 { errmsg = redeclaration_error_message (newdecl, olddecl); @@ -2451,8 +2060,9 @@ implicitly_declare (functionid) 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); @@ -3081,8 +2691,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 @@ -3115,7 +2725,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. */ @@ -3489,8 +3099,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)) { @@ -3552,8 +3163,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); } @@ -3746,6 +3358,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. @@ -3910,7 +3556,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } } else if (specbits & (1 << (int) i)) - pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + error ("duplicate `%s'", IDENTIFIER_POINTER (id)); /* Diagnose "__thread extern". Recall that this list is in the reverse order seen in the text. */ @@ -4043,12 +3689,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; } } @@ -4342,6 +3987,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; @@ -5401,7 +5049,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; } @@ -5604,6 +5253,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; } @@ -5689,8 +5343,9 @@ finish_struct (t, fieldlist, attributes) && 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); @@ -5712,7 +5367,8 @@ 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); @@ -6770,7 +6426,7 @@ c_expand_deferred_function (fndecl) } } -/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero, +/* 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. */ @@ -7113,7 +6769,7 @@ c_dup_lang_specific_decl (decl) 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. */