Ping. On Thu, Jul 31, 2014 at 09:39:21AM +0200, Marek Polacek wrote: > One of the prerequisites to moving the default from gnu89 to gnu11 > is that we need both -Wc90-c99-compat and -Wc99-c11-compat options. > This patch implements the former. Its purpose is similar to > -Wtraditional - that people who build code in C99/C11 mode can easily > check whether the code uses something outside C90. Since > __extension__ disables this warning, features that are properly > conditioned are fine and not warned about. > > As I said privately, it turned out to be convenient to reuse > pedwarn_c90 - the patch now mostly removes code. Earlier I defined > a special function, but that rendered pedwarn_c90 unused. Another > benefit I see is that if we ever add pedwarn_c90, we have > -Wc90-c99-compat handled for free. And obviously, defining yet > another warn/pedwarn function would be confusing. > > A few issues: currently we don't warn (in -std=c90 -pedantic mode) > about the usage of __func__ and _Pragma (possible others - va_copy?). > I'm hoping this is not that important though. For restrict/inline, > in GNU90 mode we just don't compile the code at all (unless we use > __restrict and similar), and -Wc90-c99-compat does not warn about those. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2014-07-31 Marek Polacek <pola...@redhat.com> > > PR c/51849 > gcc/ > * gcc/doc/invoke.texi: Document -Wc90-c99-compat. > gcc/c-family/ > * c-opts.c (sanitize_cpp_opts): Pass warn_c90_c99_compat to libcpp. > * c.opt (Wc90-c99-compat): Add option. > gcc/c/ > * c-decl.c (build_array_declarator): Remove check for !flag_isoc99. > Call pedwarn_c90 instead of pedwarn. > (check_bitfield_type_and_width): Likewise. > (declspecs_add_qual): Likewise. > (declspecs_add_type): Likewise. > (warn_variable_length_array): Unify function for -pedantic and -Wvla. > Adjust to only call pedwarn_c90. > (grokdeclarator): Remove pedantic && !flag_isoc99 check. Call > pedwarn_c90 instead of pedwarn. > * c-errors.c (pedwarn_c90): Handle -Wc90-c99-compat. > * c-parser.c (disable_extension_diagnostics): Handle > warn_c90_c99_compat. > (restore_extension_diagnostics): Likewise. > (c_parser_enum_specifier): Remove check for !flag_isoc99. Call > pedwarn_c90 instead of pedwarn. > (c_parser_initelt): Likewise. > (c_parser_postfix_expression): Likewise. > (c_parser_postfix_expression_after_paren_type): Likewise. > (c_parser_compound_statement_nostart): Remove check for !flag_isoc99. > * c-tree.h: Fix formatting. > * c-typeck.c (build_array_ref): Remove check for !flag_isoc99. Call > pedwarn_c90 instead of pedwarn. > gcc/testsuite/ > * gcc.dg/Wc90-c99-compat-1.c: New test. > * gcc.dg/Wc90-c99-compat-2.c: New test. > * gcc.dg/Wc90-c99-compat-3.c: New test. > * gcc.dg/Wc90-c99-compat-4.c: New test. > * gcc.dg/Wc90-c99-compat-5.c: New test. > * gcc.dg/Wc90-c99-compat-6.c: New test. > * gcc.dg/wvla-1.c: Adjust dg-warning. > * gcc.dg/wvla-2.c: Adjust dg-warning. > * gcc.dg/wvla-4.c: Adjust dg-warning. > * gcc.dg/wvla-6.c: Adjust dg-warning. > libcpp/ > * lex.c (_cpp_lex_direct): Warn when -Wc90-c99-compat is in effect. > * charset.c (_cpp_valid_ucn): Likewise. > * include/cpplib.h (cpp_options): Add cpp_warn_c90_c99_compat. > * macro.c (replace_args): Warn when -Wc90-c99-compat is in effect. > (parse_params): Likewise. > > diff --git gcc/gcc/c-family/c-opts.c gcc/gcc/c-family/c-opts.c > index 3f8e6e6..43a8b9d 100644 > --- gcc/gcc/c-family/c-opts.c > +++ gcc/gcc/c-family/c-opts.c > @@ -1295,6 +1295,7 @@ sanitize_cpp_opts (void) > cpp_opts->unsigned_char = !flag_signed_char; > cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS; > cpp_opts->warn_date_time = cpp_warn_date_time; > + cpp_opts->cpp_warn_c90_c99_compat = warn_c90_c99_compat; > > /* Wlong-long is disabled by default. It is enabled by: > [-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or > diff --git gcc/gcc/c-family/c.opt gcc/gcc/c-family/c.opt > index f427da1..b62bac1 100644 > --- gcc/gcc/c-family/c.opt > +++ gcc/gcc/c-family/c.opt > @@ -291,6 +291,10 @@ Wbuiltin-macro-redefined > C ObjC C++ ObjC++ Warning > Warn when a built-in preprocessor macro is undefined or redefined > > +Wc90-c99-compat > +C ObjC Var(warn_c90_c99_compat) Warning > +Warn about features not present in ISO C90, but present in ISO C99 > + > Wc++-compat > C ObjC Var(warn_cxx_compat) Warning > Warn about C constructs that are not in the common subset of C and C++ > diff --git gcc/gcc/c/c-decl.c gcc/gcc/c/c-decl.c > index 2a4b439..b1c5862 100644 > --- gcc/gcc/c/c-decl.c > +++ gcc/gcc/c/c-decl.c > @@ -3968,16 +3968,13 @@ build_array_declarator (location_t loc, > } > declarator->u.array.static_p = static_p; > declarator->u.array.vla_unspec_p = vla_unspec_p; > - if (!flag_isoc99) > - { > - if (static_p || quals != NULL) > - pedwarn (loc, OPT_Wpedantic, > + if (static_p || quals != NULL) > + pedwarn_c90 (loc, OPT_Wpedantic, > "ISO C90 does not support %<static%> or type " > "qualifiers in parameter array declarators"); > - if (vla_unspec_p) > - pedwarn (loc, OPT_Wpedantic, > + if (vla_unspec_p) > + pedwarn_c90 (loc, OPT_Wpedantic, > "ISO C90 does not support %<[*]%> array declarators"); > - } > if (vla_unspec_p) > { > if (!current_scope->parm_flag) > @@ -4891,10 +4888,9 @@ check_bitfield_type_and_width (tree *type, tree > *width, tree orig_name) > if (!in_system_header_at (input_location) > && type_mv != integer_type_node > && type_mv != unsigned_type_node > - && type_mv != boolean_type_node > - && !flag_isoc99) > - pedwarn (input_location, OPT_Wpedantic, > - "type of bit-field %qs is a GCC extension", name); > + && type_mv != boolean_type_node) > + pedwarn_c90 (input_location, OPT_Wpedantic, > + "type of bit-field %qs is a GCC extension", name); > > max_width = TYPE_PRECISION (*type); > > @@ -4925,52 +4921,27 @@ static void > warn_variable_length_array (tree name, tree size) > { > int const_size = TREE_CONSTANT (size); > + enum opt_code opt = (warn_vla == -1 && !warn_c90_c99_compat) > + ? OPT_Wpedantic : OPT_Wvla; > > - if (!flag_isoc99 && pedantic && warn_vla != 0) > + if (const_size) > { > - if (const_size) > - { > - if (name) > - pedwarn (input_location, OPT_Wvla, > + if (name) > + pedwarn_c90 (input_location, opt, > "ISO C90 forbids array %qE whose size " > - "can%'t be evaluated", > - name); > - else > - pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array whose > size " > - "can%'t be evaluated"); > - } > + "can%'t be evaluated", name); > else > - { > - if (name) > - pedwarn (input_location, OPT_Wvla, > - "ISO C90 forbids variable length array %qE", > - name); > - else > - pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length > array"); > - } > + pedwarn_c90 (input_location, opt, "ISO C90 forbids array " > + "whose size can%'t be evaluated"); > } > - else if (warn_vla > 0) > + else > { > - if (const_size) > - { > - if (name) > - warning (OPT_Wvla, > - "the size of array %qE can" > - "%'t be evaluated", name); > - else > - warning (OPT_Wvla, > - "the size of array can %'t be evaluated"); > - } > + if (name) > + pedwarn_c90 (input_location, opt, > + "ISO C90 forbids variable length array %qE", name); > else > - { > - if (name) > - warning (OPT_Wvla, > - "variable length array %qE is used", > - name); > - else > - warning (OPT_Wvla, > - "variable length array is used"); > - } > + pedwarn_c90 (input_location, opt, "ISO C90 forbids variable " > + "length array"); > } > } > > @@ -5186,18 +5157,14 @@ grokdeclarator (const struct c_declarator *declarator, > as2 = TYPE_ADDR_SPACE (element_type); > address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1; > > - if (pedantic && !flag_isoc99) > - { > - if (constp > 1) > - pedwarn (loc, OPT_Wpedantic, "duplicate %<const%>"); > - if (restrictp > 1) > - pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>"); > - if (volatilep > 1) > - pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>"); > - if (atomicp > 1) > - pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>"); > - > - } > + if (constp > 1) > + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<const%>"); > + if (restrictp > 1) > + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<restrict%>"); > + if (volatilep > 1) > + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>"); > + if (atomicp > 1) > + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>"); > > if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != > as2) > error_at (loc, "conflicting named address spaces (%s vs %s)", > @@ -5602,10 +5569,9 @@ grokdeclarator (const struct c_declarator *declarator, > flexible_array_member = (t->kind == cdk_id); > } > if (flexible_array_member > - && pedantic && !flag_isoc99 > && !in_system_header_at (input_location)) > - pedwarn (loc, OPT_Wpedantic, > - "ISO C90 does not support flexible array members"); > + pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not " > + "support flexible array members"); > > /* ISO C99 Flexible array members are effectively > identical to GCC's zero-length array extension. */ > @@ -9140,8 +9106,8 @@ declspecs_add_qual (source_location loc, > default: > gcc_unreachable (); > } > - if (dupe && !flag_isoc99) > - pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual); > + if (dupe) > + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %qE", qual); > return specs; > } > > @@ -9385,9 +9351,9 @@ declspecs_add_type (location_t loc, struct c_declspecs > *specs, > break; > case RID_COMPLEX: > dupe = specs->complex_p; > - if (!flag_isoc99 && !in_system_header_at (loc)) > - pedwarn (loc, OPT_Wpedantic, > - "ISO C90 does not support complex types"); > + if (!in_system_header_at (loc)) > + pedwarn_c90 (loc, OPT_Wpedantic, > + "ISO C90 does not support complex types"); > if (specs->typespec_word == cts_auto_type) > error_at (loc, > ("both %<complex%> and %<__auto_type%> in " > @@ -9603,9 +9569,9 @@ declspecs_add_type (location_t loc, struct c_declspecs > *specs, > } > return specs; > case RID_BOOL: > - if (!flag_isoc99 && !in_system_header_at (loc)) > - pedwarn (loc, OPT_Wpedantic, > - "ISO C90 does not support boolean types"); > + if (!in_system_header_at (loc)) > + pedwarn_c90 (loc, OPT_Wpedantic, > + "ISO C90 does not support boolean types"); > if (specs->long_p) > error_at (loc, > ("both %<long%> and %<_Bool%> in " > diff --git gcc/gcc/c/c-errors.c gcc/gcc/c/c-errors.c > index 92136e7..1cc1dbf 100644 > --- gcc/gcc/c/c-errors.c > +++ gcc/gcc/c/c-errors.c > @@ -44,21 +44,38 @@ pedwarn_c99 (location_t location, int opt, const char > *gmsgid, ...) > va_end (ap); > } > > -/* Issue an ISO C90 pedantic warning MSGID. This function is supposed to > - be used for matters that are allowed in ISO C99 but not supported in > - ISO C90, thus we explicitly don't pedwarn when C99 is specified. > - (There is no flag_c90.) */ > +/* Issue an ISO C90 pedantic warning MSGID if -pedantic outside C99 mode, > + otherwise issue warning MSGID if -Wc90-c99-compat is specified, or if > + specific option such as -Wlong-long is specified. > + This function is supposed to be used for matters that are allowed in > + ISO C99 but not supported in ISO C90, thus we explicitly don't pedwarn > + when C99 is specified. (There is no flag_c90.) */ > > void > pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...) > { > diagnostic_info diagnostic; > va_list ap; > + bool warned = false; > > va_start (ap, gmsgid); > - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, > - flag_isoc99 ? DK_WARNING : DK_PEDWARN); > - diagnostic.option_index = opt; > - report_diagnostic (&diagnostic); > + if (pedantic && !flag_isoc99) > + { > + diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN); > + diagnostic.option_index = opt; > + warned = report_diagnostic (&diagnostic); > + } > + else if (opt != OPT_Wpedantic) > + { > + diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING); > + diagnostic.option_index = opt; > + warned = report_diagnostic (&diagnostic); > + } > + if (warn_c90_c99_compat && !warned) > + { > + diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING); > + diagnostic.option_index = OPT_Wc90_c99_compat; > + report_diagnostic (&diagnostic); > + } > va_end (ap); > } > diff --git gcc/gcc/c/c-parser.c gcc/gcc/c/c-parser.c > index e32bf04..ca8577c 100644 > --- gcc/gcc/c/c-parser.c > +++ gcc/gcc/c/c-parser.c > @@ -1072,7 +1072,8 @@ disable_extension_diagnostics (void) > | (flag_iso << 3) > | (warn_long_long << 4) > | (warn_cxx_compat << 5) > - | (warn_overlength_strings << 6)); > + | (warn_overlength_strings << 6) > + | (warn_c90_c99_compat << 7)); > cpp_opts->cpp_pedantic = pedantic = 0; > warn_pointer_arith = 0; > cpp_opts->cpp_warn_traditional = warn_traditional = 0; > @@ -1080,6 +1081,7 @@ disable_extension_diagnostics (void) > cpp_opts->cpp_warn_long_long = warn_long_long = 0; > warn_cxx_compat = 0; > warn_overlength_strings = 0; > + warn_c90_c99_compat = 0; > return ret; > } > > @@ -1096,6 +1098,7 @@ restore_extension_diagnostics (int flags) > cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1; > warn_cxx_compat = (flags >> 5) & 1; > warn_overlength_strings = (flags >> 6) & 1; > + warn_c90_c99_compat = (flags >> 7) & 1; > } > > /* Possibly kinds of declarator to parse. */ > @@ -2545,8 +2548,9 @@ c_parser_enum_specifier (c_parser *parser) > } > if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) > { > - if (seen_comma && !flag_isoc99) > - pedwarn (comma_loc, OPT_Wpedantic, "comma at end of enumerator > list"); > + if (seen_comma) > + pedwarn_c90 (comma_loc, OPT_Wpedantic, > + "comma at end of enumerator list"); > c_parser_consume_token (parser); > break; > } > @@ -4348,9 +4352,9 @@ c_parser_initelt (c_parser *parser, struct obstack * > braced_init_obstack) > { > if (c_parser_next_token_is (parser, CPP_EQ)) > { > - if (!flag_isoc99) > - pedwarn (des_loc, OPT_Wpedantic, > - "ISO C90 forbids specifying subobject to initialize"); > + pedwarn_c90 (des_loc, OPT_Wpedantic, > + "ISO C90 forbids specifying subobject " > + "to initialize"); > c_parser_consume_token (parser); > } > else > @@ -4566,10 +4570,9 @@ c_parser_compound_statement_nostart (c_parser *parser) > c_parser_declaration_or_fndef (parser, true, true, true, true, > true, NULL, vNULL); > if (last_stmt) > - pedwarn_c90 (loc, > - (pedantic && !flag_isoc99) > - ? OPT_Wpedantic > - : OPT_Wdeclaration_after_statement, > + pedwarn_c90 (loc, (pedantic && !flag_isoc99) > + ? OPT_Wpedantic > + : OPT_Wdeclaration_after_statement, > "ISO C90 forbids mixed declarations and code"); > last_stmt = false; > } > @@ -4598,8 +4601,8 @@ c_parser_compound_statement_nostart (c_parser *parser) > restore_extension_diagnostics (ext); > if (last_stmt) > pedwarn_c90 (loc, (pedantic && !flag_isoc99) > - ? OPT_Wpedantic > - : OPT_Wdeclaration_after_statement, > + ? OPT_Wpedantic > + : OPT_Wdeclaration_after_statement, > "ISO C90 forbids mixed declarations and code"); > last_stmt = false; > } > @@ -7401,9 +7404,8 @@ c_parser_postfix_expression (c_parser *parser) > expr.value = error_mark_node; > break; > } > - if (!flag_isoc99) > - pedwarn (loc, OPT_Wpedantic, > - "ISO C90 does not support complex types"); > + pedwarn_c90 (loc, OPT_Wpedantic, > + "ISO C90 does not support complex types"); > expr.value = build2 (COMPLEX_EXPR, > build_complex_type > (TYPE_MAIN_VARIANT > @@ -7607,8 +7609,7 @@ c_parser_postfix_expression_after_paren_type (c_parser > *parser, > type = error_mark_node; > } > > - if (!flag_isoc99) > - pedwarn (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals"); > + pedwarn_c90 (start_loc, OPT_Wpedantic, "ISO C90 forbids compound > literals"); > non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR) > ? CONSTRUCTOR_NON_CONST (init.value) > : init.original_code == C_MAYBE_CONST_EXPR); > diff --git gcc/gcc/c/c-tree.h gcc/gcc/c/c-tree.h > index f97d0d5..55e71dc 100644 > --- gcc/gcc/c/c-tree.h > +++ gcc/gcc/c/c-tree.h > @@ -676,7 +676,9 @@ extern tree c_omp_reduction_lookup (tree, tree); > extern tree c_check_omp_declare_reduction_r (tree *, int *, void *); > > /* In c-errors.c */ > -extern void pedwarn_c90 (location_t, int opt, const char *, ...) > ATTRIBUTE_GCC_DIAG(3,4); > -extern void pedwarn_c99 (location_t, int opt, const char *, ...) > ATTRIBUTE_GCC_DIAG(3,4); > +extern void pedwarn_c90 (location_t, int opt, const char *, ...) > + ATTRIBUTE_GCC_DIAG(3,4); > +extern void pedwarn_c99 (location_t, int opt, const char *, ...) > + ATTRIBUTE_GCC_DIAG(3,4); > > #endif /* ! GCC_C_TREE_H */ > diff --git gcc/gcc/c/c-typeck.c gcc/gcc/c/c-typeck.c > index a938933..64c7a74 100644 > --- gcc/gcc/c/c-typeck.c > +++ gcc/gcc/c/c-typeck.c > @@ -2511,7 +2511,7 @@ build_array_ref (location_t loc, tree array, tree index) > return error_mark_node; > } > > - if (pedantic) > + if (pedantic || warn_c90_c99_compat) > { > tree foo = array; > while (TREE_CODE (foo) == COMPONENT_REF) > @@ -2519,9 +2519,10 @@ build_array_ref (location_t loc, tree array, tree > index) > if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo)) > pedwarn (loc, OPT_Wpedantic, > "ISO C forbids subscripting %<register%> array"); > - else if (!flag_isoc99 && !lvalue_p (foo)) > - pedwarn (loc, OPT_Wpedantic, > - "ISO C90 forbids subscripting non-lvalue array"); > + else if (!lvalue_p (foo)) > + pedwarn_c90 (loc, OPT_Wpedantic, > + "ISO C90 forbids subscripting non-lvalue " > + "array"); > } > > type = TREE_TYPE (TREE_TYPE (array)); > diff --git gcc/gcc/doc/invoke.texi gcc/gcc/doc/invoke.texi > index 51757f0..f48552b 100644 > --- gcc/gcc/doc/invoke.texi > +++ gcc/gcc/doc/invoke.texi > @@ -241,6 +241,7 @@ Objective-C and Objective-C++ Dialects}. > -w -Wextra -Wall -Waddress -Waggregate-return @gol > -Waggressive-loop-optimizations -Warray-bounds @gol > -Wno-attributes -Wno-builtin-macro-redefined @gol > +-Wc90-c99-compat @gol > -Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol > -Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol > -Wconversion -Wcoverage-mismatch -Wdate-time -Wdelete-incomplete -Wno-cpp > @gol > @@ -4497,6 +4498,15 @@ example, warn if an unsigned variable is compared > against zero with > Warn whenever a function call is cast to a non-matching type. > For example, warn if @code{int malloc()} is cast to @code{anything *}. > > +@item -Wc90-c99-compat @r{(C and Objective-C only)} > +@opindex Wc90-c99-compat > +@opindex Wno-c90-c99-compat > +Warn about features not present in ISO C90, but present in ISO C99. > +For instance, warn about use of variable length arrays, @code{long long} > +type, @code{bool} type, compound literals, designated initializers, and so > +on. This option is independent of the standards mode. Warnings are disabled > +in the expression that follows @code{__extension__}. > + > @item -Wc++-compat @r{(C and Objective-C only)} > Warn about ISO C constructs that are outside of the common subset of > ISO C and ISO C++, e.g.@: request for implicit conversion from > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c > index e69de29..15e71e8 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c > @@ -0,0 +1,56 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu90 -Wpedantic -Wc90-c99-compat" } */ > + > +_Bool b; /* { dg-warning "ISO C90 does not support boolean types" } */ > +_Complex double c = __builtin_complex (0.0, 0.0); /* { dg-warning "ISO C90 > does not support complex types" } */ > +long long l; /* { dg-warning "ISO C90 does not support .long long." } */ > +struct A { int i; char a[]; }; /* { dg-warning "ISO C90 does not support > flexible array members" } */ > +struct { long int b: 2; } s; /* { dg-warning "type of bit-field .b. is a GCC > extension" } */ > +const const int i; /* { dg-warning "duplicate .const." } */ > +volatile volatile v; /* { dg-warning "duplicate .volatile." } */ > + > +struct S { int a[2]; }; > +extern struct S foo (void); > + > +#define V(v, ...) (v, __VA_ARGS) /* { dg-warning "anonymous variadic macros > were introduced in C99" } */ > + > +enum { E, }; /* { dg-warning "comma at end of enumerator list" } */ > + > +void fn1 (char [*]); /* { dg-warning "ISO C90 does not support > .\\\[\\\*\\\]. array declarators" } */ > + > +void > +fn2 (char x[static 4]) /* { dg-warning "ISO C90 does not support .static. or > type qualifiers" } */ > +{ > + int i = (int) { 1 }; /* { dg-warning "ISO C90 forbids compound literals" } > */ > + struct A a = { .i = 3 }; /* { dg-warning "ISO C90 forbids specifying > subobject to initialize" } */ > +} > + > +void > +fn3 (int n) > +{ > + n = 3; > + int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */ > +} > + > +void > +fn4 (int n) > +{ > + n = 3; > + __extension__ int i; /* { dg-warning "ISO C90 forbids mixed declarations > and code" } */ > +} > + > +void > +fn5 (void) > +{ > + (foo ()).a[0]; /* { dg-warning "ISO C90 forbids subscripting non-lvalue > array" } */ > +} > + > +#define F(a) a > + > +void > +fn6 (void) > +{ > + F(); /* { dg-warning "invoking macro F argument" } */ > +} > + > +void fn7 (int n, int a[n]); /* { dg-warning "ISO C90 forbids variable length > array .a." } */ > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c > index e69de29..d00f0df 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c > @@ -0,0 +1,56 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu99 -Wc90-c99-compat -pedantic-errors" } */ > + > +_Bool b; /* { dg-warning "ISO C90 does not support boolean types" } */ > +_Complex double c = __builtin_complex (0.0, 0.0); /* { dg-warning "ISO C90 > does not support complex types" } */ > +long long l; /* { dg-warning "ISO C90 does not support .long long." } */ > +struct A { int i; char a[]; }; /* { dg-warning "ISO C90 does not support > flexible array members" } */ > +struct { long int b: 2; } s; /* { dg-warning "type of bit-field .b. is a GCC > extension" } */ > +const const int i; /* { dg-warning "duplicate .const." } */ > +volatile volatile int v; /* { dg-warning "duplicate .volatile." } */ > + > +struct S { int a[2]; }; > +extern struct S foo (void); > + > +#define V(v, ...) (v, __VA_ARGS) /* { dg-warning "anonymous variadic macros > were introduced in C99" } */ > + > +enum { E, }; /* { dg-warning "comma at end of enumerator list" } */ > + > +void fn1 (char [*]); /* { dg-warning "ISO C90 does not support > .\\\[\\\*\\\]. array declarators" } */ > + > +void > +fn2 (char x[static 4]) /* { dg-warning "ISO C90 does not support .static. or > type qualifiers" } */ > +{ > + int i = (int) { 1 }; /* { dg-warning "ISO C90 forbids compound literals" } > */ > + struct A a = { .i = 3 }; /* { dg-warning "ISO C90 forbids specifying > subobject to initialize" } */ > +} > + > +void > +fn3 (int n) > +{ > + n = 3; > + int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */ > +} > + > +void > +fn4 (int n) > +{ > + n = 3; > + __extension__ int i; /* { dg-warning "ISO C90 forbids mixed declarations > and code" } */ > +} > + > +void > +fn5 (void) > +{ > + (foo ()).a[0]; /* { dg-warning "ISO C90 forbids subscripting non-lvalue > array" } */ > +} > + > +#define F(a) a > + > +void > +fn6 (void) > +{ > + F(); /* { dg-warning "invoking macro F argument" } */ > +} > + > +void fn7 (int n, int a[n]); /* { dg-warning "ISO C90 forbids variable length > array .a." } */ > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c > index e69de29..78f012c 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c > @@ -0,0 +1,56 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu11 -Wc90-c99-compat -pedantic-errors" } */ > + > +_Bool b; /* { dg-warning "ISO C90 does not support boolean types" } */ > +_Complex double c = __builtin_complex (0.0, 0.0); /* { dg-warning "ISO C90 > does not support complex types" } */ > +long long l; /* { dg-warning "ISO C90 does not support .long long." } */ > +struct A { int i; char a[]; }; /* { dg-warning "ISO C90 does not support > flexible array members" } */ > +struct { long int b: 2; } s; /* { dg-warning "type of bit-field .b. is a GCC > extension" } */ > +const const int i; /* { dg-warning "duplicate .const." } */ > +volatile volatile int v; /* { dg-warning "duplicate .volatile." } */ > + > +struct S { int a[2]; }; > +extern struct S foo (void); > + > +#define V(v, ...) (v, __VA_ARGS) /* { dg-warning "anonymous variadic macros > were introduced in C99" } */ > + > +enum { E, }; /* { dg-warning "comma at end of enumerator list" } */ > + > +void fn1 (char [*]); /* { dg-warning "ISO C90 does not support > .\\\[\\\*\\\]. array declarators" } */ > + > +void > +fn2 (char x[static 4]) /* { dg-warning "ISO C90 does not support .static. or > type qualifiers" } */ > +{ > + int i = (int) { 1 }; /* { dg-warning "ISO C90 forbids compound literals" } > */ > + struct A a = { .i = 3 }; /* { dg-warning "ISO C90 forbids specifying > subobject to initialize" } */ > +} > + > +void > +fn3 (int n) > +{ > + n = 3; > + int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */ > +} > + > +void > +fn4 (int n) > +{ > + n = 3; > + __extension__ int i; /* { dg-warning "ISO C90 forbids mixed declarations > and code" } */ > +} > + > +void > +fn5 (void) > +{ > + (foo ()).a[0]; /* { dg-warning "ISO C90 forbids subscripting non-lvalue > array" } */ > +} > + > +#define F(a) a > + > +void > +fn6 (void) > +{ > + F(); /* { dg-warning "invoking macro F argument" } */ > +} > + > +void fn7 (int n, int a[n]); /* { dg-warning "ISO C90 forbids variable length > array .a." } */ > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c > index e69de29..e8d2f03 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c > @@ -0,0 +1,56 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu90 -Wpedantic -Wno-c90-c99-compat" } */ > + > +_Bool b; /* { dg-warning "ISO C90 does not support boolean types" } */ > +_Complex double c = __builtin_complex (0.0, 0.0); /* { dg-warning "ISO C90 > does not support complex types" } */ > +long long l; /* { dg-warning "ISO C90 does not support .long long." } */ > +struct A { int i; char a[]; }; /* { dg-warning "ISO C90 does not support > flexible array members" } */ > +struct { long int b: 2; } s; /* { dg-warning "type of bit-field .b. is a GCC > extension" } */ > +const const int i; /* { dg-warning "duplicate .const." } */ > +volatile volatile int v; /* { dg-warning "duplicate .volatile." } */ > + > +struct S { int a[2]; }; > +extern struct S foo (void); > + > +#define V(v, ...) (v, __VA_ARGS) /* { dg-warning "anonymous variadic macros > were introduced in C99" } */ > + > +enum { E, }; /* { dg-warning "comma at end of enumerator list" } */ > + > +void fn1 (char [*]); /* { dg-warning "ISO C90 does not support > .\\\[\\\*\\\]. array declarators" } */ > + > +void > +fn2 (char x[static 4]) /* { dg-warning "ISO C90 does not support .static. or > type qualifiers" } */ > +{ > + int i = (int) { 1 }; /* { dg-warning "ISO C90 forbids compound literals" } > */ > + struct A a = { .i = 3 }; /* { dg-warning "ISO C90 forbids specifying > subobject to initialize" } */ > +} > + > +void > +fn3 (int n) > +{ > + n = 3; > + int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */ > +} > + > +void > +fn4 (int n) > +{ > + n = 3; > + __extension__ int i; /* { dg-warning "ISO C90 forbids mixed declarations > and code" } */ > +} > + > +void > +fn5 (void) > +{ > + (foo ()).a[0]; /* { dg-warning "ISO C90 forbids subscripting non-lvalue > array" } */ > +} > + > +#define F(a) a > + > +void > +fn6 (void) > +{ > + F(); /* { dg-warning "invoking macro F argument" } */ > +} > + > +void fn7 (int n, int a[n]); /* { dg-warning "ISO C90 forbids variable length > array .a." } */ > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c > index e69de29..1344ae8 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c > @@ -0,0 +1,56 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu90 -pedantic-errors -Wno-c90-c99-compat" } */ > + > +_Bool b; /* { dg-error "ISO C90 does not support boolean types" } */ > +_Complex double c = __builtin_complex (0.0, 0.0); /* { dg-error "ISO C90 > does not support complex types" } */ > +long long l; /* { dg-error "ISO C90 does not support .long long." } */ > +struct A { int i; char a[]; }; /* { dg-error "ISO C90 does not support > flexible array members" } */ > +struct { long int b: 2; } s; /* { dg-error "type of bit-field .b. is a GCC > extension" } */ > +const const int i; /* { dg-error "duplicate .const." } */ > +volatile volatile int v; /* { dg-error "duplicate .volatile." } */ > + > +struct S { int a[2]; }; > +extern struct S foo (void); > + > +#define V(v, ...) (v, __VA_ARGS) /* { dg-error "anonymous variadic macros > were introduced in C99" } */ > + > +enum { E, }; /* { dg-error "comma at end of enumerator list" } */ > + > +void fn1 (char [*]); /* { dg-error "ISO C90 does not support .\\\[\\\*\\\]. > array declarators" } */ > + > +void > +fn2 (char x[static 4]) /* { dg-error "ISO C90 does not support .static. or > type qualifiers" } */ > +{ > + int i = (int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */ > + struct A a = { .i = 3 }; /* { dg-error "ISO C90 forbids specifying > subobject to initialize" } */ > +} > + > +void > +fn3 (int n) > +{ > + n = 3; > + int i; /* { dg-error "ISO C90 forbids mixed declarations and code" } */ > +} > + > +void > +fn4 (int n) > +{ > + n = 3; > + __extension__ int i; /* { dg-error "ISO C90 forbids mixed declarations and > code" } */ > +} > + > +void > +fn5 (void) > +{ > + (foo ()).a[0]; /* { dg-error "ISO C90 forbids subscripting non-lvalue > array" } */ > +} > + > +#define F(a) a > + > +void > +fn6 (void) > +{ > + F(); /* { dg-error "invoking macro F argument" } */ > +} > + > +void fn7 (int n, int a[n]); /* { dg-error "ISO C90 forbids variable length > array .a." } */ > diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c > gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c > index e69de29..8728cd9 100644 > --- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c > +++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c > @@ -0,0 +1,29 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu90 -Wc90-c99-compat" } */ > + > +__extension__ _Bool b; > +__extension__ _Complex double c = __builtin_complex (0.0, 0.0); > +__extension__ long long l; > +__extension__ struct A { int i; char a[]; }; > +__extension__ struct { long int b: 2; } s; > +__extension__ const const int i; > +__extension__ volatile volatile int v; > +__extension__ struct S { int a[2]; }; > +extern struct S foo (void); > +__extension__ enum { E, }; > +__extension__ void fn1 (char [*]); > + > +__extension__ void > +fn2 (char x[static 4]) > +{ > + int i = (int) { 1 }; > + struct A a = { .i = 3 }; > +} > + > +__extension__ void > +fn5 (void) > +{ > + (foo ()).a[0]; > +} > + > +__extension__ void fn7 (int n, int a[n]); > diff --git gcc/gcc/testsuite/gcc.dg/wvla-1.c gcc/gcc/testsuite/gcc.dg/wvla-1.c > index c8f2107..d2e3cb5 100644 > --- gcc/gcc/testsuite/gcc.dg/wvla-1.c > +++ gcc/gcc/testsuite/gcc.dg/wvla-1.c > @@ -2,4 +2,4 @@ > /* { dg-options "-std=c89 -Wvla" } */ > > extern void > -func (int i, int array[i]); /* { dg-warning "variable length array 'array' > is used" } */ > +func (int i, int array[i]); /* { dg-warning "ISO C90 forbids variable length > array 'array'" } */ > diff --git gcc/gcc/testsuite/gcc.dg/wvla-2.c gcc/gcc/testsuite/gcc.dg/wvla-2.c > index d811a11..92c67ed 100644 > --- gcc/gcc/testsuite/gcc.dg/wvla-2.c > +++ gcc/gcc/testsuite/gcc.dg/wvla-2.c > @@ -2,4 +2,4 @@ > /* { dg-options "-std=c99 -Wvla" } */ > > extern void > -func (int i, int array[i]); /* { dg-warning "variable length array 'array' > is used" } */ > +func (int i, int array[i]); /* { dg-warning "ISO C90 forbids variable length > array 'array'" } */ > diff --git gcc/gcc/testsuite/gcc.dg/wvla-4.c gcc/gcc/testsuite/gcc.dg/wvla-4.c > index 8c15292..ae2e0b0 100644 > --- gcc/gcc/testsuite/gcc.dg/wvla-4.c > +++ gcc/gcc/testsuite/gcc.dg/wvla-4.c > @@ -2,4 +2,4 @@ > /* { dg-options "-pedantic-errors -std=c99 -Wvla" } */ > > extern void > -func (int i, int array[i]); /* { dg-warning "variable length array 'array' > is used" } */ > +func (int i, int array[i]); /* { dg-warning "ISO C90 forbids variable length > array 'array'" } */ > diff --git gcc/gcc/testsuite/gcc.dg/wvla-6.c gcc/gcc/testsuite/gcc.dg/wvla-6.c > index f21435b..694a4cc 100644 > --- gcc/gcc/testsuite/gcc.dg/wvla-6.c > +++ gcc/gcc/testsuite/gcc.dg/wvla-6.c > @@ -2,4 +2,4 @@ > /* { dg-options "-std=c89 -Wvla" } */ > > extern void > -func (int i, int [i]); /* { dg-warning "variable length array is used" } */ > +func (int i, int [i]); /* { dg-warning "ISO C90 forbids variable length > array" } */ > diff --git gcc/libcpp/charset.c gcc/libcpp/charset.c > index a3c24d6..fa46f92 100644 > --- gcc/libcpp/charset.c > +++ gcc/libcpp/charset.c > @@ -995,6 +995,10 @@ _cpp_valid_ucn (cpp_reader *pfile, const uchar **pstr, > if (!CPP_OPTION (pfile, cplusplus) && !CPP_OPTION (pfile, c99)) > cpp_error (pfile, CPP_DL_WARNING, > "universal character names are only valid in C++ and C99"); > + else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > + && !CPP_OPTION (pfile, cplusplus)) > + cpp_error (pfile, CPP_DL_WARNING, > + "C99's universal character names are incompatible with C90"); > else if (CPP_WTRADITIONAL (pfile) && identifier_pos == 0) > cpp_warning (pfile, CPP_W_TRADITIONAL, > "the meaning of '\\%c' is different in traditional C", > diff --git gcc/libcpp/include/cpplib.h gcc/libcpp/include/cpplib.h > index a83452b..4cd66cd 100644 > --- gcc/libcpp/include/cpplib.h > +++ gcc/libcpp/include/cpplib.h > @@ -466,6 +466,9 @@ struct cpp_options > /* True if dependencies should be restored from a precompiled header. */ > bool restore_pch_deps; > > + /* True if warn about differences between C90 and C99. */ > + bool cpp_warn_c90_c99_compat; > + > /* Dependency generation. */ > struct > { > diff --git gcc/libcpp/lex.c gcc/libcpp/lex.c > index 7e2db64..5cc2224 100644 > --- gcc/libcpp/lex.c > +++ gcc/libcpp/lex.c > @@ -2325,7 +2325,7 @@ _cpp_lex_direct (cpp_reader *pfile) > else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments) > || cpp_in_system_header (pfile))) > { > - /* Warn about comments only if pedantically GNUC89, and not > + /* Warn about comments if pedantically GNUC89, and not > in system headers. */ > if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile) > && ! buffer->warned_cplusplus_comments) > @@ -2336,6 +2336,16 @@ _cpp_lex_direct (cpp_reader *pfile) > "(this will be reported only once per input file)"); > buffer->warned_cplusplus_comments = 1; > } > + /* Or if specifically desired via -Wc90-c99-compat. */ > + else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > + && ! buffer->warned_cplusplus_comments) > + { > + cpp_error (pfile, CPP_DL_WARNING, > + "C++ style comments are are incompatible with C90"); > + cpp_error (pfile, CPP_DL_WARNING, > + "(this will be reported only once per input file)"); > + buffer->warned_cplusplus_comments = 1; > + } > > if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments)) > cpp_warning (pfile, CPP_W_COMMENTS, "multi-line comment"); > diff --git gcc/libcpp/macro.c gcc/libcpp/macro.c > index 556628b..ff6685c 100644 > --- gcc/libcpp/macro.c > +++ gcc/libcpp/macro.c > @@ -1795,6 +1795,16 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, > cpp_macro *macro, > NODE_NAME (node), > src->val.macro_arg.arg_no); > } > + else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > + && ! macro->syshdr > + && ! cpp_in_system_header (pfile) > + && ! CPP_OPTION (pfile, cplusplus)) > + cpp_error (pfile, CPP_DL_WARNING, > + "invoking macro %s argument %d: " > + "empty macro arguments are undefined" > + " in ISO C90", > + NODE_NAME (node), > + src->val.macro_arg.arg_no); > > /* Avoid paste on RHS (even case count == 0). */ > if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)) > @@ -2848,6 +2858,10 @@ parse_params (cpp_reader *pfile, cpp_macro *macro) > (pfile, CPP_W_VARIADIC_MACROS, > "anonymous variadic macros were introduced in C99"); > } > + else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > + && ! CPP_OPTION (pfile, cplusplus)) > + cpp_error (pfile, CPP_DL_WARNING, > + "anonymous variadic macros were introduced in C99"); > } > else if (CPP_OPTION (pfile, cpp_pedantic) > && CPP_OPTION (pfile, warn_variadic_macros)) > > Marek
Marek