[RFC,diagnostics/fortran] Move gfc_warning (buffered) to the common diagnostics machinery
diff mbox

Message ID CAESRpQCGfALwFN_PgLxwkf7KCmByzBevrvGY634PhBFCXX6zVg@mail.gmail.com
State New
Headers show

Commit Message

Manuel López-Ibáñez Nov. 27, 2014, 5:25 p.m. UTC
This is just a RFC so no Changelog yet. It bootstraps and passes the
testsuite. I have three major questions:

* Dodji: Do the common diagnostics part look reasonable? I tried to be
as least invasive as possible. If you have comments or suggestions
they are very welcome.

* Fortran devs: Is this approach acceptable? The main idea is to have
an output_buffer called pp_warning_buffer with the flush_p bit unset
if we are buffering. When printing buffered warnings, use this
output_buffer in the global_dc->printer instead of the (unbuffered
one) used by the *_now variants. In principle this could support
several buffered diagnostics, but Fortran only seems to buffer at most
one.

The ugliest part is how to handle warningcount and werrorcount. I
could handle this in the common machinery in a better way by storing
DK_WERROR in the diagnostic->kind and checking it after printing. This
way we can first decrease both counters, then increase back the one
not changed and store the kind somewhere. then if the diagnostic is
canceled nothing is done, if it is flushed, then increase the
appropriate counter (perhaps calling into the common part for any post
action due to Wfatal-errors or -fmax-errors=).

I can also hide the output_buffer switching inside two helper
functions, but the helper function would need to use either a static
variable or a global one to save and restore the tmp_buffer. I'm not
sure that is better or worse (the current code uses a global pointer
&cur_error_buffer, so perhaps I should have used a similar approach).

* Fortran devs #2: The testsuite is testing that the warning is
eventually printed. However, I'm not sure it is testing when the
warning is buffered and then discarded, is it? If not, how can I
produce such a test?

Thanks,

Manuel.

Comments

Steve Kargl Nov. 27, 2014, 6:52 p.m. UTC | #1
On Thu, Nov 27, 2014 at 06:25:01PM +0100, Manuel López-Ibáñez wrote:
> 
> The ugliest part is how to handle warningcount and werrorcount. I
> could handle this in the common machinery in a better way by storing
> DK_WERROR in the diagnostic->kind and checking it after printing. This
> way we can first decrease both counters, then increase back the one
> not changed and store the kind somewhere. then if the diagnostic is
> canceled nothing is done, if it is flushed, then increase the
> appropriate counter (perhaps calling into the common part for any post
> action due to Wfatal-errors or -fmax-errors=).
> 
> I can also hide the output_buffer switching inside two helper
> functions, but the helper function would need to use either a static
> variable or a global one to save and restore the tmp_buffer. I'm not
> sure that is better or worse (the current code uses a global pointer
> &cur_error_buffer, so perhaps I should have used a similar approach).
> 

Hi Manuel,

First, thanks for all your work on the error/warning code in gfortran.

Second, I'm dredging through my memories from a decade or so ago.  Others
are encouraged to jump in and correct me.

The design of gfortran's warning/error code is largely unchanged from 
when g95 was originally imported into the tree.  There have been, of
course, some changes but the design was set.  My understanding of how
it all works(ed) is that gfortran's parsing runs a series of matchers
over the input.  A matcher may generate an error/warning, which is
written into a buffer.  But, instead of immediately reporting the issue
gfortran may continue to run a series of matchers to see if the input
is in fact validate.  gfortran will report the last buffered error/warning
message only after the last matcher fails.  In running the series of
matchers, there are times when a matcher may hit an error/warning
condition and it is, in fact, a problem and gfortran wants to report
the problem NOW.  This is the origin of the *_now variants.

I would need to go dredge through ChangeLogs, but I believe I may be
responsible for the counting of error messages. I know that I at least
set the default value for -fmax-error.  The origins to the counting
is that once gfortran encountered and reported an error, she would
discard the problematic statement and continue parsing the input.  This
often leads to a series of spurious run-on error messages, which are
all caused by the first error.  Thus, if one does -fmax-error=1 and
fixes the problem, then all the other problems disappear.

Finally, gfortran's error/warning mechanism isn't immediately available
at the start of execution.  However, errors can occur before the mechanism
is initialized.  This is one reason why one finds fatal_error() spinkled
throughout the code.

>
> * Fortran devs #2: The testsuite is testing that the warning is
> eventually printed. However, I'm not sure it is testing when the
> warning is buffered and then discarded, is it? If not, how can I
> produce such a test?
> 

I think that you can't check for a discarded buffered message.  In
fact, why bother?
Tobias Burnus Nov. 27, 2014, 7:28 p.m. UTC | #2
Manuel López-Ibáñez wrote:
> * Fortran devs: Is this approach acceptable? The main idea is to have
> an output_buffer called pp_warning_buffer with the flush_p bit unset
> if we are buffering. When printing buffered warnings, use this
> output_buffer in the global_dc->printer instead of the (unbuffered
> one) used by the *_now variants. In principle this could support
> several buffered diagnostics, but Fortran only seems to buffer at most
> one.

I think the approach is fine. As the _now version overrides the buffer, 
one might even do with a single buffer by clearing it, setting flush_p 
temporarily to true and printing the message. It only might collide with 
buffered warnings (for error_now) and errors (for warning_now), but I 
don't see whether that's an issue. For warnings/error_now it probably 
isn't, for errors/warning_now, it might. Thus, having two buffers is 
probably better.

> The ugliest part is how to handle warningcount and werrorcount. I
> could handle this in the common machinery in a better way by storing
> DK_WERROR in the diagnostic->kind and checking it after printing.

I'm missing the "but". Does it require more modifications in common code 
and thus you shy away? Or is there another reason?

> I can also hide the output_buffer switching inside two helper
> functions, but the helper function would need to use either a static
> variable or a global one to save and restore the tmp_buffer. I'm not
> sure that is better or worse (the current code uses a global pointer
> &cur_error_buffer, so perhaps I should have used a similar approach).

Me neither. The current approach is rather localized in error.c; thus, 
it doesn't really matter.

> * Fortran devs #2: The testsuite is testing that the warning is
> eventually printed. However, I'm not sure it is testing when the
> warning is buffered and then discarded, is it? If not, how can I
> produce such a test?

Well, for nearly every Fortran program, at least for one line multiple 
attempts have to be done by the parser. Thus, if you set a break point 
in gfc_error, you will see "syntax error" messages which never make it 
to the screen. As the test suite checks for excess errors, nearly every 
test-suite file tests this.

* * *

With the patch in place, plus its gfc_error cousin, and after the 
follow-up conversion work, only the following would remain:

* gfc_warning: a single occurence of two locations in the same error 
string (of ~120 calls)
* gfc_error: approx. 34 times two locations (of ~1630 calls)
* gfc_error_now_1: 11 times two locations

* In scanner.c:
- gfc_warning_now_1: 6 calls in scanner.c
- gfc_warning: 3
- fprintf: 2
- gfc_error: 0
Some of those can probably be simply converted, others either need to 
remain, or one has to setup a proper location (currently, using 
gfc_warning_now would ICE), or one creates a work around and constructs 
manually the error string (at least for the fprintf cases).

* * *

Regarding the use of libcpp: Currently, it is only used with explicit 
preprocessing ("-cpp", file extension) and it is used to output into a 
temporary file which is then read back. I experimented with
   token = cpp_get_token (cpp_in);
   const char *str = cpp_token_as_text (cpp_in, token);
which kind of works okay.

But I do not understand how one gets linebreaks and spacing correctly. 
For linebreaks, I can use "flags & BOL" or a callback. But I'm still 
trying to understand how one can get the number of spacings. "flags & 
PREV_WHITE" seems to record only a single one and seems to convert all 
of them (\t, \n and ' ') into a single type.

For fixed-form Fortran, spaces are essential. On punch cards,* only the 
first 72 characters were read; as (some?) punch cards had additional 8 
characters, those were used for comments (e.g. to enumerate the cards). 
Hence, there are codes out there, which assumes that everything beyond 
72 characters is ignored. Thus, the number of spaces is crucial – at 
least with -fpreprocessed, if one wants to always goes through libcpp.

Looking at the current code, it seems to use a line-break callback with 
SOURCE_COLUMN to reconstruct the indentation. I think saving the token 
src_column and the length of the token string and subtracting it from 
the new source location, will also work for mid-line spaces. However, 
that's really a kludge – and it still doesn't permit one to distiniguish 
between spaces and tabs.

Finally, the token handling seems to get in trouble with
   print *, "Hello &
       &world!"
where a single string extends over two lines.

Taking everything together, I think using libcpp for reading Fortran 
files is a topic for GCC 6. Any suggestion how to properly handle the 
spacing?

For the lexing itself, one probably needs a Fortran mode, which can 
recognize Fortran comments, continuation lines and some special 
properties about Fortran string. When implemented, one could then also 
turn of the traditional mode.

Tobias

* Disclaimer: I started with Fortran 95 and a rather object-oriented 
code. Hence, I might have gotten the fine print of the Fortran history 
wrong.
Manuel López-Ibáñez Nov. 27, 2014, 9:33 p.m. UTC | #3
On 27 November 2014 at 20:28, Tobias Burnus <burnus@net-b.de> wrote:
> I think the approach is fine. As the _now version overrides the buffer, one
> might even do with a single buffer by clearing it, setting flush_p
> temporarily to true and printing the message. It only might collide with
> buffered warnings (for error_now) and errors (for warning_now), but I don't
> see whether that's an issue. For warnings/error_now it probably isn't, for
> errors/warning_now, it might. Thus, having two buffers is probably better.

Oh, I didn't notice that the _now versions override the buffered
messages. Where do you see that? It seems that gfc_warning_1 saves and
restores buffer_flag but does not touch the buffers (it prints
directly to the stream).

However, as you say, I may still need two buffers, one for errors and
other for warnings. (If this were not necessary, it would be great! Is
it really?).

In fact, we will need more buffers, since there is gfc_push/pop_error.
This is why I didn't start with gfc_error, it is a bit more complex
than gfc_warning.

>> The ugliest part is how to handle warningcount and werrorcount. I
>> could handle this in the common machinery in a better way by storing
>> DK_WERROR in the diagnostic->kind and checking it after printing.
>
>
> I'm missing the "but". Does it require more modifications in common code and
> thus you shy away? Or is there another reason?

I was going to write "Exactly" and a long explanation. But now I
realize that in this particular case I can simply check DK_ERROR,
since within gfc_warning that can only come from a warning converted
to an error. That simplifies the function a bit:

+/* Issue a warning.  */
+
+bool
+gfc_warning_1 (int opt, const char *gmsgid, ...)
+{
+  va_list argp;
+  diagnostic_info diagnostic;
+  bool fatal_errors = global_dc->fatal_errors;
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+
+  if (!pp_warning_buffer.flush_p)
+    {
+      /* To prevent -fmax-errors= triggering.  */
+      --werrorcount;
+      pp->buffer = &pp_warning_buffer;
+      global_dc->fatal_errors = false;
+    }
+
+  va_start (argp, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+                      DK_WARNING);
+  diagnostic.option_index = opt;
+  bool ret = report_diagnostic (&diagnostic);
+
+  if (ret && !pp_warning_buffer.flush_p)
+    {
+      warningcount_buffered = 0;
+      werrorcount_buffered = 0;
+      /* Undo the above --werrorcount if not Werror, otherwise werrorcount is
+        correct already.  */
+      diagnostic.kind == DK_ERROR
+       ? (++werrorcount_buffered)
+       : (++werrorcount, --warningcount, ++warningcount_buffered);
+
+      pp->buffer = tmp_buffer;
+      global_dc->fatal_errors = fatal_errors;
+    }
+
+  va_end (argp);
+  return ret;
+}


> Well, for nearly every Fortran program, at least for one line multiple
> attempts have to be done by the parser. Thus, if you set a break point in
> gfc_error, you will see "syntax error" messages which never make it to the
> screen. As the test suite checks for excess errors, nearly every test-suite
> file tests this.

Sure, but I would like to test specifically triggering and discarding
the gfc_warning that I converted (or another single one that you
suggest), if this were possible.

> Some of those can probably be simply converted, others either need to
> remain, or one has to setup a proper location (currently, using
> gfc_warning_now would ICE), or one creates a work around and constructs
> manually the error string (at least for the fprintf cases).

Why does it ICE? At worst it should give a wrong location, but the
computation of the offset is fairly similar to what Fortran already
does. Could  you give me a patch+testcase that ICEs?

> Taking everything together, I think using libcpp for reading Fortran files
> is a topic for GCC 6. Any suggestion how to properly handle the spacing?

No idea. My knowledge of cpp is limited. I think you need to ask
Dodji, Tom or Joseph (in IRC or a new thread). I was hoping it was
going to be easier to lex Fortran with cpp since cpp can already
preprocess it.

Thanks for the comment. They are very helpful.

Cheers,

Manuel.
Manuel López-Ibáñez Nov. 27, 2014, 10 p.m. UTC | #4
On 27 November 2014 at 22:33, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
> On 27 November 2014 at 20:28, Tobias Burnus <burnus@net-b.de> wrote:
>> I think the approach is fine. As the _now version overrides the buffer, one
>> might even do with a single buffer by clearing it, setting flush_p
>> temporarily to true and printing the message. It only might collide with
>> buffered warnings (for error_now) and errors (for warning_now), but I don't
>> see whether that's an issue. For warnings/error_now it probably isn't, for
>> errors/warning_now, it might. Thus, having two buffers is probably better.
>
> Oh, I didn't notice that the _now versions override the buffered
> messages. Where do you see that? It seems that gfc_warning_1 saves and
> restores buffer_flag but does not touch the buffers (it prints
> directly to the stream).

I meant gfc_warning_now_1. However, gfc_error_now_1 does reset
error_buffer (and sets it as curr_buffer, why if without buffering it
is not used?) . Hum, if this is really necessary, I'm afraid I just
introduced a subtle bug, since the new gfc_error_now does not reset
error_buffer, thus, potentially it may give an error that should have
been discarded. Tobias, what do you think?
Dodji Seketeli Dec. 1, 2014, 8:22 a.m. UTC | #5
Manuel López-Ibáñez <lopezibanez@gmail.com> writes:

> * Dodji: Do the common diagnostics part look reasonable?

Yes they do.

I just have one minor comment nit:

[...]

> Index: gcc/pretty-print.h

[...]

> +
> +  /* Nonzero means that text should be flushed when
> +     appropriate. Otherwise, text is buffered until either
> +     pp_pp_really_flush or pp_clear_output_area are called. */

I think you wanted to say pp_really_flush, not pp_pp_realy_flush.

> +  bool flush_p;
>  };

[...]

Thanks!

Patch
diff mbox

Index: gcc/pretty-print.c
===================================================================
--- gcc/pretty-print.c	(revision 218090)
+++ gcc/pretty-print.c	(working copy)
@@ -40,7 +40,8 @@ 
     cur_chunk_array (),
     stream (stderr),
     line_length (),
-    digit_buffer ()
+    digit_buffer (),
+    flush_p (true)
 {
   obstack_init (&formatted_obstack);
   obstack_init (&chunk_obstack);
@@ -679,12 +680,25 @@ 
   pp_wrapping_mode (pp) = oldmode;
 }
 
-/* Flush the content of BUFFER onto the attached stream.  */
+/* Flush the content of BUFFER onto the attached stream.  This
+   function does nothing unless pp->output_buffer->flush_p.  */
 void
 pp_flush (pretty_printer *pp)
 {
+  pp_clear_state (pp);
+  if (!pp->buffer->flush_p)
+    return;
   pp_write_text_to_stream (pp);
+  fflush (pp_buffer (pp)->stream);
+}
+
+/* Flush the content of BUFFER onto the attached stream independently
+   of the value of pp->output_buffer->flush_p.  */
+void
+pp_really_flush (pretty_printer *pp)
+{
   pp_clear_state (pp);
+  pp_write_text_to_stream (pp);
   fflush (pp_buffer (pp)->stream);
 }
 
Index: gcc/pretty-print.h
===================================================================
--- gcc/pretty-print.h	(revision 218090)
+++ gcc/pretty-print.h	(working copy)
@@ -100,6 +100,11 @@ 
   /* This must be large enough to hold any printed integer or
      floating-point value.  */
   char digit_buffer[128];
+
+  /* Nonzero means that text should be flushed when
+     appropriate. Otherwise, text is buffered until either
+     pp_pp_really_flush or pp_clear_output_area are called. */
+  bool flush_p;
 };
 
 /* The type of pretty-printer flags passed to clients.  */
@@ -314,6 +319,7 @@ 
 extern void pp_verbatim (pretty_printer *, const char *, ...)
      ATTRIBUTE_GCC_PPDIAG(2,3);
 extern void pp_flush (pretty_printer *);
+extern void pp_really_flush (pretty_printer *);
 extern void pp_format (pretty_printer *, text_info *);
 extern void pp_output_formatted_text (pretty_printer *);
 extern void pp_format_verbatim (pretty_printer *, text_info *);
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 218090)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2443,7 +2443,6 @@ 
   int dump_fortran_optimized;
 
   int warn_aliasing;
-  int warn_ampersand;
   int warn_function_elimination;
   int warn_implicit_interface;
   int warn_implicit_procedure;
@@ -2691,6 +2690,7 @@ 
 const char *gfc_print_wide_char (gfc_char_t);
 
 void gfc_warning (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
+bool gfc_warning_1 (int opt, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
 void gfc_warning_now_1 (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
 bool gfc_warning_now (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
 bool gfc_warning_now (int opt, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
@@ -2719,7 +2719,7 @@ 
 void gfc_free_error (gfc_error_buf *);
 
 void gfc_get_errors (int *, int *);
-void gfc_errors_to_warnings (int);
+void gfc_errors_to_warnings (bool);
 
 /* arith.c */
 void gfc_arith_init_1 (void);
Index: gcc/fortran/error.c
===================================================================
--- gcc/fortran/error.c	(revision 218090)
+++ gcc/fortran/error.c	(working copy)
@@ -50,7 +50,11 @@ 
 
 static gfc_error_buf error_buffer, warning_buffer, *cur_error_buffer;
 
+static output_buffer pp_warning_buffer;
+static int warningcount_buffered, werrorcount_buffered;
 
+#include <new> /* For placement-new */
+
 /* Go one level deeper suppressing errors.  */
 
 void
@@ -122,6 +126,7 @@ 
 gfc_buffer_error (int flag)
 {
   buffer_flag = flag;
+  pp_warning_buffer.flush_p = !flag;
 }
 
 
@@ -833,6 +838,52 @@ 
 }
 
 
+/* Issue a warning.  */
+
+bool
+gfc_warning_1 (int opt, const char *gmsgid, ...)
+{
+  va_list argp;
+  diagnostic_info diagnostic;
+  bool ret;
+  bool fatal_errors = global_dc->fatal_errors;
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  int warningcount_saved = 0;
+  int werrorcount_saved = 0;
+
+  if (!pp_warning_buffer.flush_p)
+    {
+      warningcount_saved = warningcount;
+      werrorcount_saved = werrorcount;
+      /* To prevent -fmax-errors= triggering.  */
+      werrorcount--;
+      pp->buffer = &pp_warning_buffer;
+      global_dc->fatal_errors = false;
+    }
+
+  va_start (argp, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+		       DK_WARNING);
+  diagnostic.option_index = opt;
+  ret = report_diagnostic (&diagnostic);
+
+  if (!pp_warning_buffer.flush_p)
+    {
+      warningcount_buffered = warningcount - warningcount_saved;
+      warningcount = warningcount_saved;
+      werrorcount++; /* Undo the above werrorcount-- */
+      werrorcount_buffered = werrorcount - werrorcount_saved;
+      werrorcount = werrorcount_saved;
+
+      pp->buffer = tmp_buffer;
+      global_dc->fatal_errors = fatal_errors;
+    }
+  
+  va_end (argp);
+  return ret;
+}
+
 /* Whether, for a feature included in a given standard set (GFC_STD_*),
    we should issue an error or a warning, or be quiet.  */
 
@@ -1176,6 +1227,15 @@ 
 gfc_clear_warning (void)
 {
   warning_buffer.flag = 0;
+  
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  pp->buffer = &pp_warning_buffer;
+  pp_clear_output_area (pp);
+  pp->buffer = tmp_buffer;
+  pp_warning_buffer.flush_p = false;
+  warningcount_buffered = 0;
+  werrorcount_buffered = 0;
 }
 
 
@@ -1192,6 +1252,20 @@ 
 	fputs (warning_buffer.message, stderr);
       warning_buffer.flag = 0;
     }
+
+  /* This is for the new diagnostics machinery.  */
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  pp->buffer = &pp_warning_buffer;
+  if (pp_last_position_in_text (pp) != NULL)
+    {
+      pp_really_flush (pp);
+      pp_warning_buffer.flush_p = true;
+      warningcount += warningcount_buffered;
+      werrorcount += werrorcount_buffered;
+    }
+
+  pp->buffer = tmp_buffer;
 }
 
 
@@ -1395,9 +1469,9 @@ 
 /* Switch errors into warnings.  */
 
 void
-gfc_errors_to_warnings (int f)
+gfc_errors_to_warnings (bool f)
 {
-  warnings_not_errors = (f == 1) ? 1 : 0;
+  warnings_not_errors = f;
 }
 
 void
@@ -1407,6 +1481,7 @@ 
   diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer;
   diagnostic_format_decoder (global_dc) = gfc_format_decoder;
   global_dc->caret_char = '^';
+  new (&pp_warning_buffer) output_buffer ();
 }
 
 void
Index: gcc/fortran/lang.opt
===================================================================
--- gcc/fortran/lang.opt	(revision 218090)
+++ gcc/fortran/lang.opt	(working copy)
@@ -202,9 +202,13 @@ 
 Warn about alignment of COMMON blocks
 
 Wampersand
-Fortran Warning
+Fortran Warning Var(warn_ampersand) LangEnabledBy(Fortran, Wpedantic)
 Warn about missing ampersand in continued character constants
 
+Wampersand
+LangEnabledBy(Fortran, Wall)
+;
+
 Warray-temporaries
 Fortran Warning
 Warn about creation of array temporaries
Index: gcc/fortran/scanner.c
===================================================================
--- gcc/fortran/scanner.c	(revision 218090)
+++ gcc/fortran/scanner.c	(working copy)
@@ -1154,9 +1154,10 @@ 
 	  if (in_string)
 	    {
 	      gfc_current_locus.nextc--;
-	      if (gfc_option.warn_ampersand && in_string == INSTRING_WARN)
-		gfc_warning ("Missing '&' in continued character "
-			     "constant at %C");
+	      if (warn_ampersand && in_string == INSTRING_WARN)
+		gfc_warning_1 (OPT_Wampersand,
+			       "Missing %<&%> in continued character "
+			       "constant at %C");
 	    }
 	  /* Both !$omp and !$ -fopenmp continuation lines have & on the
 	     continuation line only optionally.  */
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 218090)
+++ gcc/fortran/resolve.c	(working copy)
@@ -2431,7 +2431,7 @@ 
 
       if (!pedantic && (gfc_option.allow_std & GFC_STD_GNU))
 	/* Turn erros into warnings with -std=gnu and -std=legacy.  */
-	gfc_errors_to_warnings (1);
+	gfc_errors_to_warnings (true);
 
       if (!gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1,
 				   reason, sizeof(reason), NULL, NULL))
@@ -2444,14 +2444,14 @@ 
       if (!pedantic
 	  || ((gfc_option.warn_std & GFC_STD_LEGACY)
 	      && !(gfc_option.warn_std & GFC_STD_GNU)))
-	gfc_errors_to_warnings (1);
+	gfc_errors_to_warnings (true);
 
       if (sym->attr.if_source != IFSRC_IFBODY)
 	gfc_procedure_use (def_sym, actual, where);
     }
 
 done:
-  gfc_errors_to_warnings (0);
+  gfc_errors_to_warnings (false);
 
   if (gsym->type == GSYM_UNKNOWN)
     {
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 218090)
+++ gcc/fortran/primary.c	(working copy)
@@ -951,7 +951,7 @@ 
 match_string_constant (gfc_expr **result)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1], peek;
-  int i, kind, length, warn_ampersand, ret;
+  int i, kind, length, warn_ampersand_saved, ret;
   locus old_locus, start_locus;
   gfc_symbol *sym;
   gfc_expr *e;
@@ -1071,8 +1071,8 @@ 
 
   /* We disable the warning for the following loop as the warning has already
      been printed in the loop above.  */
-  warn_ampersand = gfc_option.warn_ampersand;
-  gfc_option.warn_ampersand = 0;
+  warn_ampersand_saved = warn_ampersand;
+  warn_ampersand = false;
 
   p = e->value.character.string;
   for (i = 0; i < length; i++)
@@ -1091,7 +1091,7 @@ 
     }
 
   *p = '\0';	/* TODO: C-style string is for development/debug purposes.  */
-  gfc_option.warn_ampersand = warn_ampersand;
+  warn_ampersand = warn_ampersand_saved;
 
   next_string_char (delimiter, &ret);
   if (ret != -1)
Index: gcc/fortran/options.c
===================================================================
--- gcc/fortran/options.c	(revision 218090)
+++ gcc/fortran/options.c	(working copy)
@@ -94,7 +94,6 @@ 
   gfc_option.dump_fortran_optimized = 0;
 
   gfc_option.warn_aliasing = 0;
-  gfc_option.warn_ampersand = 0;
   gfc_option.warn_array_temp = 0;
   gfc_option.warn_function_elimination = 0;
   gfc_option.warn_implicit_interface = 0;
@@ -423,9 +422,6 @@ 
   if (!gfc_option.flag_automatic)
     gfc_option.flag_max_stack_var_size = 0;
   
-  if (pedantic)
-    gfc_option.warn_ampersand = 1;
-
   /* Optimization implies front end optimization, unless the user
      specified it directly.  */
 
@@ -447,7 +443,6 @@ 
 set_Wall (int setting)
 {
   gfc_option.warn_aliasing = setting;
-  gfc_option.warn_ampersand = setting;
   gfc_option.warn_line_truncation = setting;
   gfc_option.warn_surprising = setting;
   gfc_option.warn_underflow = setting;
@@ -642,10 +637,6 @@ 
       gfc_option.warn_aliasing = value;
       break;
 
-    case OPT_Wampersand:
-      gfc_option.warn_ampersand = value;
-      break;
-
     case OPT_Warray_temporaries:
       gfc_option.warn_array_temp = value;
       break;
@@ -1003,7 +994,7 @@ 
       gfc_option.max_continue_fixed = 19;
       gfc_option.max_continue_free = 39;
       gfc_option.max_identifier_length = 31;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1012,7 +1003,7 @@ 
 	| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008_OBS;
       gfc_option.warn_std = GFC_STD_F95_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1021,7 +1012,7 @@ 
 	| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008 | GFC_STD_F2008_OBS;
       gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1031,7 +1022,7 @@ 
 	| GFC_STD_F2008_TS;
       gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;