diff mbox

[C] Tidy up pedwarn_c90 (take 2)

Message ID 20140812094804.GJ2436@redhat.com
State New
Headers show

Commit Message

Marek Polacek Aug. 12, 2014, 9:48 a.m. UTC
This then is the version with both issues fixed (and new test).

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2014-08-12  Marek Polacek  <polacek@redhat.com>

gcc/c-family/
	* c-opts.c (sanitize_cpp_opts): Make warn_long_long be set according
	to warn_c90_c99_compat.
	* c.opt (Wc90-c99-compat, Wdeclaration-after-statement): Initialize
	to -1.
gcc/c/
	* c-decl.c (warn_variable_length_array): Pass OPT_Wvla unconditionally
	to pedwarn_c90.
	* c-errors.c: Include "opts.h".
	(pedwarn_c90): Rewrite to handle -Wno-c90-c99-compat better.
	* c-parser.c (disable_extension_diagnostics): Handle negative value
	of warn_c90_c99_compat, too.
	(restore_extension_diagnostics): Likewise.
	(c_parser_compound_statement_nostart): Pass
	OPT_Wdeclaration_after_statement unconditionally to pedwarn_c90.
gcc/testsuite/
	* gcc.dg/Wc90-c99-compat-4.c: Remove all dg-warnings.
	* gcc.dg/Wc90-c99-compat-5.c: Remove all dg-errors.
	* gcc.dg/Wc90-c99-compat-7.c: New test.
	* gcc.dg/Wc90-c99-compat-8.c: New test.
	* gcc.dg/Wdeclaration-after-statement-4.c: New test.
libcpp/
	* charset.c (_cpp_valid_ucn): Warn only if -Wc90-c99-compat.
	* lex.c (_cpp_lex_direct): Likewise.
	* macro.c (replace_args): Likewise.
	(parse_params): Likewise.
	* include/cpplib.h (cpp_options): Change cpp_warn_c90_c99_compat
	to char.


	Marek

Comments

Joseph Myers Aug. 18, 2014, 10:06 p.m. UTC | #1
On Tue, 12 Aug 2014, Marek Polacek wrote:

> This then is the version with both issues fixed (and new test).
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> 2014-08-12  Marek Polacek  <polacek@redhat.com>
> 
> gcc/c-family/
> 	* c-opts.c (sanitize_cpp_opts): Make warn_long_long be set according
> 	to warn_c90_c99_compat.
> 	* c.opt (Wc90-c99-compat, Wdeclaration-after-statement): Initialize
> 	to -1.
> gcc/c/
> 	* c-decl.c (warn_variable_length_array): Pass OPT_Wvla unconditionally
> 	to pedwarn_c90.
> 	* c-errors.c: Include "opts.h".
> 	(pedwarn_c90): Rewrite to handle -Wno-c90-c99-compat better.
> 	* c-parser.c (disable_extension_diagnostics): Handle negative value
> 	of warn_c90_c99_compat, too.
> 	(restore_extension_diagnostics): Likewise.
> 	(c_parser_compound_statement_nostart): Pass
> 	OPT_Wdeclaration_after_statement unconditionally to pedwarn_c90.
> gcc/testsuite/
> 	* gcc.dg/Wc90-c99-compat-4.c: Remove all dg-warnings.
> 	* gcc.dg/Wc90-c99-compat-5.c: Remove all dg-errors.
> 	* gcc.dg/Wc90-c99-compat-7.c: New test.
> 	* gcc.dg/Wc90-c99-compat-8.c: New test.
> 	* gcc.dg/Wdeclaration-after-statement-4.c: New test.
> libcpp/
> 	* charset.c (_cpp_valid_ucn): Warn only if -Wc90-c99-compat.
> 	* lex.c (_cpp_lex_direct): Likewise.
> 	* macro.c (replace_args): Likewise.
> 	(parse_params): Likewise.
> 	* include/cpplib.h (cpp_options): Change cpp_warn_c90_c99_compat
> 	to char.

OK.
Manuel López-Ibáñez Aug. 29, 2014, 5:16 p.m. UTC | #2
On 19 August 2014 00:06, Joseph S. Myers <joseph@codesourcery.com> wrote:
> On Tue, 12 Aug 2014, Marek Polacek wrote:
>
>> This then is the version with both issues fixed (and new test).
>>
>> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>>
>> 2014-08-12  Marek Polacek  <polacek@redhat.com>
>>
>> gcc/c-family/
>>       * c-opts.c (sanitize_cpp_opts): Make warn_long_long be set according
>>       to warn_c90_c99_compat.
>>       * c.opt (Wc90-c99-compat, Wdeclaration-after-statement): Initialize
>>       to -1.

To be honest, I consider this a small step back towards encoding all
the options dependencies in the *.opt files.

If I understand correctly, the reason for initializing
Wdeclaration-after-statement to -1 is to detect whether the option has
been enabled/disabled explicitly and, if not, then only emit the
warning if Wpedantic or Wc90-c99-compat has been given, This is
precisely what LangEnabledBy was designed for. The problem in this
case is that we only want to enable Wdeclaration-after-statement when
given Wpedantic if !flag_isoc99 and currently there is not way to
encode this with LangEnabledBy.

Perhaps we need a LangEnabledByIf(C ObjC,Wpedantic,!flag_isoc99). I
see two difficulties for implementing this:

* We would need to handle warning options after -std=.
* We would need to have access to flag_isoc99 in the generated file
options.c. I think this flag is not encoded in global_opts, thus we
could pass it as an argument to C_handle_option_auto.

Is this the direction we want to move towards? Perhaps it is not worth
the trouble just for the handful of options that would require such
LangEnabledByIf().

Cheers,

Manuel.
Marek Polacek Sept. 8, 2014, 7:03 a.m. UTC | #3
On Fri, Aug 29, 2014 at 07:16:55PM +0200, Manuel López-Ibáñez wrote:
> On 19 August 2014 00:06, Joseph S. Myers <joseph@codesourcery.com> wrote:
> > On Tue, 12 Aug 2014, Marek Polacek wrote:
> >
> >> This then is the version with both issues fixed (and new test).
> >>
> >> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> >>
> >> 2014-08-12  Marek Polacek  <polacek@redhat.com>
> >>
> >> gcc/c-family/
> >>       * c-opts.c (sanitize_cpp_opts): Make warn_long_long be set according
> >>       to warn_c90_c99_compat.
> >>       * c.opt (Wc90-c99-compat, Wdeclaration-after-statement): Initialize
> >>       to -1.

Sorry for the delay.

> To be honest, I consider this a small step back towards encoding all
> the options dependencies in the *.opt files.
> 
> If I understand correctly, the reason for initializing
> Wdeclaration-after-statement to -1 is to detect whether the option has
> been enabled/disabled explicitly and, if not, then only emit the
> warning if Wpedantic or Wc90-c99-compat has been given, This is
> precisely what LangEnabledBy was designed for. The problem in this
> case is that we only want to enable Wdeclaration-after-statement when
> given Wpedantic if !flag_isoc99 and currently there is not way to
> encode this with LangEnabledBy.

Yeah, this is my understanding.
 
> Perhaps we need a LangEnabledByIf(C ObjC,Wpedantic,!flag_isoc99). I
> see two difficulties for implementing this:
> 
> * We would need to handle warning options after -std=.
> * We would need to have access to flag_isoc99 in the generated file
> options.c. I think this flag is not encoded in global_opts, thus we
> could pass it as an argument to C_handle_option_auto.
> 
> Is this the direction we want to move towards? Perhaps it is not worth
> the trouble just for the handful of options that would require such
> LangEnabledByIf().

I'd say it's not worth it.  As you say, we only have a few of those
and I'm not sure the gain would offset the cost.

	Marek
diff mbox

Patch

diff --git gcc/gcc/c-family/c-opts.c gcc/gcc/c-family/c-opts.c
index 43a8b9d..b0cad20 100644
--- gcc/gcc/c-family/c-opts.c
+++ gcc/gcc/c-family/c-opts.c
@@ -1299,10 +1299,13 @@  sanitize_cpp_opts (void)
 
   /* Wlong-long is disabled by default. It is enabled by:
       [-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or
-      [-Wpedantic | -Wtraditional] -std=non-c99 .
+      [-Wpedantic | -Wtraditional] -std=non-c99 ; or
+      -Wc90-c99-compat, if specified.
 
       Either -Wlong-long or -Wno-long-long override any other settings.  */
-  if (warn_long_long == -1)
+  if (warn_long_long == -1 && warn_c90_c99_compat != -1)
+    warn_long_long = warn_c90_c99_compat;
+  else if (warn_long_long == -1)
     warn_long_long = ((pedantic || warn_traditional)
 		      && (c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99));
   cpp_opts->cpp_warn_long_long = warn_long_long;
diff --git gcc/gcc/c-family/c.opt gcc/gcc/c-family/c.opt
index 356a79f..087eabd 100644
--- gcc/gcc/c-family/c.opt
+++ gcc/gcc/c-family/c.opt
@@ -292,7 +292,7 @@  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
+C ObjC Var(warn_c90_c99_compat) Init(-1) Warning
 Warn about features not present in ISO C90, but present in ISO C99
 
 Wc++-compat
@@ -344,7 +344,7 @@  C++ ObjC++ Var(warn_ctor_dtor_privacy) Warning
 Warn when all constructors and destructors are private
 
 Wdeclaration-after-statement
-C ObjC Var(warn_declaration_after_statement) Warning
+C ObjC Var(warn_declaration_after_statement) Init(-1) Warning
 Warn when a declaration is found after a statement
 
 Wdelete-incomplete
diff --git gcc/gcc/c/c-decl.c gcc/gcc/c/c-decl.c
index 7ba35bf..138b014 100644
--- gcc/gcc/c/c-decl.c
+++ gcc/gcc/c/c-decl.c
@@ -4920,27 +4920,23 @@  check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
 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 (const_size)
+  if (TREE_CONSTANT (size))
     {
       if (name)
-	pedwarn_c90 (input_location, opt,
+	pedwarn_c90 (input_location, OPT_Wvla,
 		     "ISO C90 forbids array %qE whose size "
 		     "can%'t be evaluated", name);
       else
-	pedwarn_c90 (input_location, opt, "ISO C90 forbids array "
+	pedwarn_c90 (input_location, OPT_Wvla, "ISO C90 forbids array "
 		     "whose size can%'t be evaluated");
     }
   else
     {
       if (name)
-	pedwarn_c90 (input_location, opt,
+	pedwarn_c90 (input_location, OPT_Wvla,
 		     "ISO C90 forbids variable length array %qE", name);
       else
-	pedwarn_c90 (input_location, opt, "ISO C90 forbids variable "
+	pedwarn_c90 (input_location, OPT_Wvla, "ISO C90 forbids variable "
 		     "length array");
     }
 }
diff --git gcc/gcc/c/c-errors.c gcc/gcc/c/c-errors.c
index 5a95b88..89393b9 100644
--- gcc/gcc/c/c-errors.c
+++ gcc/gcc/c/c-errors.c
@@ -27,6 +27,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "flags.h"
 #include "diagnostic.h"
+#include "opts.h"
 
 /* Issue an ISO C99 pedantic warning MSGID.  */
 
@@ -56,26 +57,44 @@  pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
-  bool warned = false;
 
   va_start (ap, gmsgid);
-  if (pedantic && !flag_isoc99)
+  /* Warnings such as -Wvla are the most specific ones.  */
+  if (opt != OPT_Wpedantic)
     {
-      diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
-      diagnostic.option_index = opt;
-      warned = report_diagnostic (&diagnostic);
+      int opt_var = *(int *) option_flag_var (opt, &global_options);
+      if (opt_var == 0)
+        goto out;
+      else if (opt_var > 0)
+	{
+	  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+			       (pedantic && !flag_isoc99)
+			       ? DK_PEDWARN : DK_WARNING);
+	  diagnostic.option_index = opt;
+	  report_diagnostic (&diagnostic);
+	  goto out;
+	}
     }
-  else if (opt != OPT_Wpedantic)
+  /* Maybe we want to issue the C90/C99 compat warning, which is more
+     specific than -pedantic.  */
+  if (warn_c90_c99_compat > 0)
     {
-      diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING);
-      diagnostic.option_index = opt;
-      warned = report_diagnostic (&diagnostic);
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+			   (pedantic && !flag_isoc99)
+			   ? DK_PEDWARN : DK_WARNING);
+      diagnostic.option_index = OPT_Wc90_c99_compat;
+      report_diagnostic (&diagnostic);
     }
-  if (warn_c90_c99_compat && !warned)
+  /* -Wno-c90-c99-compat suppresses the pedwarns.  */
+  else if (warn_c90_c99_compat == 0)
+    ;
+  /* For -pedantic outside C99, issue a pedwarn.  */
+  else if (pedantic && !flag_isoc99)
     {
-      diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING);
-      diagnostic.option_index = OPT_Wc90_c99_compat;
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
+      diagnostic.option_index = opt;
       report_diagnostic (&diagnostic);
     }
+out:
   va_end (ap);
 }
diff --git gcc/gcc/c/c-parser.c gcc/gcc/c/c-parser.c
index ca8577c..e1201f9 100644
--- gcc/gcc/c/c-parser.c
+++ gcc/gcc/c/c-parser.c
@@ -1073,7 +1073,10 @@  disable_extension_diagnostics (void)
 	     | (warn_long_long << 4)
 	     | (warn_cxx_compat << 5)
 	     | (warn_overlength_strings << 6)
-	     | (warn_c90_c99_compat << 7));
+	     /* warn_c90_c99_compat has three states: -1/0/1, so we must
+		play tricks to properly restore it.  */
+	     | ((warn_c90_c99_compat == 1) << 7)
+	     | ((warn_c90_c99_compat == -1) << 8));
   cpp_opts->cpp_pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->cpp_warn_traditional = warn_traditional = 0;
@@ -1098,7 +1101,8 @@  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;
+  /* See above for why is this needed.  */
+  warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -4570,9 +4574,7 @@  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, OPT_Wdeclaration_after_statement,
 			 "ISO C90 forbids mixed declarations and code");
 	  last_stmt = false;
 	}
@@ -4600,9 +4602,7 @@  c_parser_compound_statement_nostart (c_parser *parser)
 		 disable this diagnostic.  */
 	      restore_extension_diagnostics (ext);
 	      if (last_stmt)
-		pedwarn_c90 (loc, (pedantic && !flag_isoc99)
-				  ? OPT_Wpedantic
-				  : OPT_Wdeclaration_after_statement,
+		pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
 			     "ISO C90 forbids mixed declarations and code");
 	      last_stmt = false;
 	    }
diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c
index e8d2f03..97ee84c 100644
--- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c
+++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-4.c
@@ -1,48 +1,46 @@ 
 /* { 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." } */
+_Bool b;
+_Complex double c = __builtin_complex (0.0, 0.0);
+long long l;
+struct A { int i; char a[]; };
+struct { long int b: 2; } s;
+const const int i;
+volatile volatile int v;
 
 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, };
 
-enum { E, }; /* { dg-warning "comma at end of enumerator list" } */
-
-void fn1 (char [*]); /* { dg-warning "ISO C90 does not support .\\\[\\\*\\\]. array declarators" } */
+void fn1 (char [*]);
 
 void
-fn2 (char x[static 4]) /* { dg-warning "ISO C90 does not support .static. or type qualifiers" } */
+fn2 (char x[static 4])
 {
-  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" } */
+  int i = (int) { 1 };
+  struct A a = { .i = 3 };
 }
 
 void
 fn3 (int n)
 {
   n = 3;
-  int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */
+  int i;
 }
 
 void
 fn4 (int n)
 {
   n = 3;
-  __extension__ int i; /* { dg-warning "ISO C90 forbids mixed declarations and code" } */
+  __extension__ int i;
 }
 
 void
 fn5 (void)
 {
-  (foo ()).a[0]; /* { dg-warning "ISO C90 forbids subscripting non-lvalue array" } */
+  (foo ()).a[0];
 }
 
 #define F(a) a
@@ -50,7 +48,7 @@  fn5 (void)
 void
 fn6 (void)
 {
-  F(); /* { dg-warning "invoking macro F argument" } */
+  F();
 }
 
-void fn7 (int n, int a[n]); /* { dg-warning "ISO C90 forbids variable length array .a." } */
+void fn7 (int n, int a[n]);
diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c
index 1344ae8..f41e960 100644
--- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c
+++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-5.c
@@ -1,48 +1,46 @@ 
 /* { 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." } */
+_Bool b;
+_Complex double c = __builtin_complex (0.0, 0.0);
+long long l;
+struct A { int i; char a[]; };
+struct { long int b: 2; } s;
+const const int i;
+volatile volatile int v;
 
 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, };
 
-enum { E, }; /* { dg-error "comma at end of enumerator list" } */
-
-void fn1 (char [*]); /* { dg-error "ISO C90 does not support .\\\[\\\*\\\]. array declarators" } */
+void fn1 (char [*]);
 
 void
-fn2 (char x[static 4]) /* { dg-error "ISO C90 does not support .static. or type qualifiers" } */
+fn2 (char x[static 4])
 {
-  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" } */
+  int i = (int) { 1 };
+  struct A a = { .i = 3 };
 }
 
 void
 fn3 (int n)
 {
   n = 3;
-  int i; /* { dg-error "ISO C90 forbids mixed declarations and code" } */
+  int i;
 }
 
 void
 fn4 (int n)
 {
   n = 3;
-  __extension__ int i; /* { dg-error "ISO C90 forbids mixed declarations and code" } */
+  __extension__ int i;
 }
 
 void
 fn5 (void)
 {
-  (foo ()).a[0]; /* { dg-error "ISO C90 forbids subscripting non-lvalue array" } */
+  (foo ()).a[0];
 }
 
 #define F(a) a
@@ -50,7 +48,7 @@  fn5 (void)
 void
 fn6 (void)
 {
-  F(); /* { dg-error "invoking macro F argument" } */
+  F();
 }
 
-void fn7 (int n, int a[n]); /* { dg-error "ISO C90 forbids variable length array .a." } */
+void fn7 (int n, int a[n]);
diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-7.c gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-7.c
index e69de29..fbf0b0d 100644
--- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-7.c
+++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-7.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90 -Wpedantic -Wc90-c99-compat -Wno-long-long -Wno-declaration-after-statement -Wno-vla" } */
+
+long long l;
+
+void
+fn3 (int n)
+{
+  n = 3;
+  int i;
+}
+
+void fn7 (int n, int a[n]);
diff --git gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-8.c gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-8.c
index e69de29..5e7a572 100644
--- gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-8.c
+++ gcc/gcc/testsuite/gcc.dg/Wc90-c99-compat-8.c
@@ -0,0 +1,56 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90 -pedantic-errors -Wc90-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 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/Wdeclaration-after-statement-4.c gcc/gcc/testsuite/gcc.dg/Wdeclaration-after-statement-4.c
index e69de29..c01d8bc 100644
--- gcc/gcc/testsuite/gcc.dg/Wdeclaration-after-statement-4.c
+++ gcc/gcc/testsuite/gcc.dg/Wdeclaration-after-statement-4.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=c90 -pedantic -Wno-declaration-after-statement" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  int i = 0;
+  if (i != 0)
+    abort ();
+  i++;
+  if (i != 1)
+    abort ();
+  int j = i;
+  if (j != 1)
+    abort ();
+  struct foo { int i0; } k = { 4 };
+  if (k.i0 != 4)
+    abort ();
+  exit (0);
+}
diff --git gcc/libcpp/charset.c gcc/libcpp/charset.c
index fa46f92..07a594d 100644
--- gcc/libcpp/charset.c
+++ gcc/libcpp/charset.c
@@ -995,7 +995,7 @@  _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)
+  else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
 	   && !CPP_OPTION (pfile, cplusplus))
     cpp_error (pfile, CPP_DL_WARNING,
 	       "C99's universal character names are incompatible with C90");
diff --git gcc/libcpp/include/cpplib.h gcc/libcpp/include/cpplib.h
index 4cd66cd..b89ba20 100644
--- gcc/libcpp/include/cpplib.h
+++ gcc/libcpp/include/cpplib.h
@@ -467,7 +467,7 @@  struct cpp_options
   bool restore_pch_deps;
 
   /* True if warn about differences between C90 and C99.  */
-  bool cpp_warn_c90_c99_compat;
+  char cpp_warn_c90_c99_compat;
 
   /* Dependency generation.  */
   struct
diff --git gcc/libcpp/lex.c gcc/libcpp/lex.c
index 5cc2224..0713f65 100644
--- gcc/libcpp/lex.c
+++ gcc/libcpp/lex.c
@@ -2337,7 +2337,7 @@  _cpp_lex_direct (cpp_reader *pfile)
 	      buffer->warned_cplusplus_comments = 1;
 	    }
 	  /* Or if specifically desired via -Wc90-c99-compat.  */
-	  else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat)
+	  else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
 		   && ! buffer->warned_cplusplus_comments)
 	    {
 	      cpp_error (pfile, CPP_DL_WARNING,
diff --git gcc/libcpp/macro.c gcc/libcpp/macro.c
index ff6685c..a1ba137 100644
--- gcc/libcpp/macro.c
+++ gcc/libcpp/macro.c
@@ -1787,7 +1787,7 @@  replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
 		       " in ISO C++98",
 		       NODE_NAME (node),
 		       src->val.macro_arg.arg_no);
-	  else
+	  else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat))
 	    cpp_error (pfile, CPP_DL_PEDWARN,
 		       "invoking macro %s argument %d: "
 		       "empty macro arguments are undefined"
@@ -1795,7 +1795,7 @@  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)
+      else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
 	       && ! macro->syshdr
 	       && ! cpp_in_system_header (pfile)
 	       && ! CPP_OPTION (pfile, cplusplus))
@@ -2858,7 +2858,7 @@  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)
+	      else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
 		       && ! CPP_OPTION (pfile, cplusplus))
 		cpp_error (pfile, CPP_DL_WARNING,
 			   "anonymous variadic macros were introduced in C99");