diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 36619f1b1a1..2bf03efb557 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-08-10 Marek Polacek + + PR c/51849 + * gcc/doc/invoke.texi: Document -Wc90-c99-compat. + 2014-08-09 Jan Hubicka * ipa-devirt.c (get_dynamic_type): Handle case when instance is in diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 803eb7b4019..e71f6edd2b8 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2014-08-10 Marek Polacek + + PR c/51849 + * c-opts.c (sanitize_cpp_opts): Pass warn_c90_c99_compat to libcpp. + * c.opt (Wc90-c99-compat): Add option. + 2014-08-07 Trevor Saunders * c-gimplify.c, cilk.c: Remove includes of pointer-set.h. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 3f8e6e6f677..43a8b9db62d 100644 --- a/gcc/c-family/c-opts.c +++ b/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 a/gcc/c-family/c.opt b/gcc/c-family/c.opt index c3be6222015..356a79fe358 100644 --- a/gcc/c-family/c.opt +++ b/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 a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 3dcd81f9c45..154768b2a49 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,29 @@ +2014-08-10 Marek Polacek + + PR c/51849 + * 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. + 2014-08-07 Trevor Saunders * c-typeck.c: Remove include of pointer-set.h. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 050ddffa343..7ba35bf7e09 100644 --- a/gcc/c/c-decl.c +++ b/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 % 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 %"); - if (restrictp > 1) - pedwarn (loc, OPT_Wpedantic, "duplicate %"); - if (volatilep > 1) - pedwarn (loc, OPT_Wpedantic, "duplicate %"); - if (atomicp > 1) - pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>"); - - } + if (constp > 1) + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %"); + if (restrictp > 1) + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %"); + if (volatilep > 1) + pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %"); + 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. */ @@ -9136,8 +9102,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; } @@ -9381,9 +9347,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 % and %<__auto_type%> in " @@ -9599,9 +9565,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 % and %<_Bool%> in " diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c index 92136e7466d..5a95b88925a 100644 --- a/gcc/c/c-errors.c +++ b/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 + a 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 a/gcc/c/c-parser.c b/gcc/c/c-parser.c index e32bf04187e..ca8577cd63a 100644 --- a/gcc/c/c-parser.c +++ b/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 a/gcc/c/c-tree.h b/gcc/c/c-tree.h index f97d0d5ba9b..55e71dcb31b 100644 --- a/gcc/c/c-tree.h +++ b/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 a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index f8a231617ae..0ed92c699f7 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2510,7 +2510,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) @@ -2518,9 +2518,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 % 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 a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 35820350d6c..fdb0b8494db 100644 --- a/gcc/doc/invoke.texi +++ b/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 @@ -4517,6 +4518,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 a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f0a9757a459..55884e4230f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2014-08-10 Marek Polacek + + PR c/51849 + * 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. + 2014-08-10 Thomas Koenig PR fortran/61999 diff --git a/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-1.c new file mode 100644 index 00000000000..15e71e8f8da --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-2.c new file mode 100644 index 00000000000..d00f0df89fe --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-3.c new file mode 100644 index 00000000000..78f012c48aa --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c new file mode 100644 index 00000000000..e8d2f03457a --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c new file mode 100644 index 00000000000..1344ae86665 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c b/gcc/testsuite/gcc.dg/Wc90-c99-compat-6.c new file mode 100644 index 00000000000..8728cd9be98 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/wvla-1.c b/gcc/testsuite/gcc.dg/wvla-1.c index c8f21078be9..d2e3cb57d4f 100644 --- a/gcc/testsuite/gcc.dg/wvla-1.c +++ b/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 a/gcc/testsuite/gcc.dg/wvla-2.c b/gcc/testsuite/gcc.dg/wvla-2.c index d811a112f07..92c67ed639f 100644 --- a/gcc/testsuite/gcc.dg/wvla-2.c +++ b/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 a/gcc/testsuite/gcc.dg/wvla-4.c b/gcc/testsuite/gcc.dg/wvla-4.c index 8c15292edac..ae2e0b064a9 100644 --- a/gcc/testsuite/gcc.dg/wvla-4.c +++ b/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 a/gcc/testsuite/gcc.dg/wvla-6.c b/gcc/testsuite/gcc.dg/wvla-6.c index f21435b02a8..694a4cc16ca 100644 --- a/gcc/testsuite/gcc.dg/wvla-6.c +++ b/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 a/libcpp/ChangeLog b/libcpp/ChangeLog index e550d177c26..54581dd3b67 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,12 @@ +2014-08-10 Marek Polacek + + PR c/51849 + * 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. + 2014-07-27 Marek Polacek PR c/61861 diff --git a/libcpp/charset.c b/libcpp/charset.c index a3c24d68626..fa46f9226d7 100644 --- a/libcpp/charset.c +++ b/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 a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index a83452b9145..4cd66cdceaf 100644 --- a/libcpp/include/cpplib.h +++ b/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 a/libcpp/lex.c b/libcpp/lex.c index 7e2db64db09..5cc2224329e 100644 --- a/libcpp/lex.c +++ b/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 a/libcpp/macro.c b/libcpp/macro.c index 556628ba7c7..ff6685c2665 100644 --- a/libcpp/macro.c +++ b/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))