diff mbox

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

Message ID 5477ACB3.2000409@net-b.de
State New
Headers show

Commit Message

Tobias Burnus Nov. 27, 2014, 10:58 p.m. UTC
Manuel López-Ibáñez wrote:
> Oh, I didn't notice that the _now versions override the buffered 
> messages. Where do you see that?

I think I messed up a bit - they do not seem to get cleared. I was 
reading gfc_error_now_1, which has:

   error_buffer.flag = 1;
   error_buffer.index = 0;
   cur_error_buffer = &error_buffer;

and I misread the "error_buffer.index = 0" as resetting the output. 
However, this "index = 0" is completely unused as one has unbuffered 
output and it only applies to the next error.

Actually, I wonder whether that can lead to printing an error message 
multiple times. Assume a buffered message, that's printed with 
gfc_error_check(), which sets flags = 0, but the buffer->message still 
contains the message. gfc_error_now_1 sets the flag to 1; it doesn't 
touch the buffer itself as it directly outputs the message. If one now 
calls gfc_error_check(), it outputs the previous buffer again. I wonder 
whether that's sometimes happens. I do recall seeing the same message 
multiple times without understanding why.

Thus, I withdraw the comment. And regarding error push/pop: I also 
missed that point.

>> 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.

Hmm, theoretically, it would be possible. However, my feeling is that 
there is no such case. What would be needed is something which is 
ambiguous, the compiler assumes first the wrong kind of statement, 
fails, and retries is with a different kind of statement.

That's simple. However, either one has already aborted (gfc_error or 
NO_MATCH) *before* reaching a gfc_warning – or the code is valid and, 
hence, the buffered warning is printed.

Hence, sorry, I cannot deliver for gfc_warning.

For error, I'd could create one.


>> 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?

Maybe it has been fixed by your latest patch, which added %L, but using
     printf '\tend' > test.f90; gfortran -Wtabs test.f90
used to ICE for me. However, it no longer ICEs. Thus, the following 
patch could be committed:

at %C");


I also confirm that the "!$OMP" warning now works correctly.


However, the change

-         gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus);
+         gfc_warning_now ("Line truncated at %L", &gfc_current_locus);

still triggers an ICE with "gfortran -Wall test.f90" and with "test.f" 
(two locations in scanner.c; see attached test cases and attache patch). 
The backtrace for test.f90 is:

Aborted
0xb6c38f crash_signal
         ../../gcc/toplev.c:359
0x1244620 linemap_position_for_loc_and_offset(line_maps*, unsigned int, 
unsigned int)
         ../../libcpp/line-map.c:648
0x63247a gfc_format_decoder
         ../../gcc/fortran/error.c:991
0x1231e8c pp_format(pretty_printer*, text_info*)
         ../../gcc/pretty-print.c:616
0x122f6ec diagnostic_report_diagnostic(diagnostic_context*, 
diagnostic_info*)
         ../../gcc/diagnostic.c:820
0x63380b gfc_warning_now(char const*, ...)
         ../../gcc/fortran/error.c:1133
0x69aca9 gfc_next_char_literal(gfc_instring)
         ../../gcc/fortran/scanner.c:1059


Besides those, there is additionally:
   gfc_warning_now_1 ("%s:%d: Illegal preprocessor directive",
which I haven't tested.

Tobias

Comments

Manuel López-Ibáñez Nov. 28, 2014, 1:46 a.m. UTC | #1
On 27 November 2014 at 23:58, Tobias Burnus <burnus@net-b.de> wrote:
> Manuel López-Ibáñez wrote:
>> 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.
>
>
> Hmm, theoretically, it would be possible. However, my feeling is that there
> is no such case. What would be needed is something which is ambiguous, the
> compiler assumes first the wrong kind of statement, fails, and retries is
> with a different kind of statement.
>
> That's simple. However, either one has already aborted (gfc_error or
> NO_MATCH) *before* reaching a gfc_warning - or the code is valid and, hence,
> the buffered warning is printed.

Then, I don't understand the point of gfc_warning.

If gfc_warning is never reached, then we could have used gfc_warning_now.
If the warning is printed, then gfc_warning was reached, thus we could
have used gfc_warning_now.

The only difference is that gfc_warning_now will print the warning as
soon as gfc_warning is reached, but since there is at most one
buffered warning and there can not be a previous error, then this
should not make a difference. What am I missing here?

>> 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?
>
> However, the change
>
> -         gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus);
> +         gfc_warning_now ("Line truncated at %L", &gfc_current_locus);
>
> still triggers an ICE with "gfortran -Wall test.f90" and with "test.f" (two
> locations in scanner.c; see attached test cases and attache patch). The
> backtrace for test.f90 is:

The problem seems to be that linemap_position_for_loc_and_offset
cannot handle an offset larger than the column_hint. Fortran hardcodes
that to 120. There are two bugs there: (1) we should not crash, at
worst we should use offset=0 and (2) we should update the column_hint
to the largest column seen. I'm testing a patch that seems to fix the
problem.

Cheers,

Manuel.
Tobias Burnus Nov. 28, 2014, 7:17 a.m. UTC | #2
Manuel López-Ibáñez wrote:
> On 27 November 2014 at 23:58, Tobias Burnus <burnus@net-b.de> wrote:
>> Hmm, theoretically, it would be possible. However, my feeling is that there
>> is no such case. What would be needed is something which is ambiguous, the
>> compiler assumes first the wrong kind of statement, fails, and retries is
>> with a different kind of statement.
>>
>> That's simple. However, either one has already aborted (gfc_error or
>> NO_MATCH) *before* reaching a gfc_warning - or the code is valid and, hence,
>> the buffered warning is printed.
> Then, I don't understand the point of gfc_warning.

I think the idea is that a warning could be printed in the wrong code 
path (assumption of which kind of statement or expression one has) – and 
then one re-tries a different code path, see that it fits and drops the 
buffered message.

Grepping through the 132 gfc_warning, I have the impression that this 
cannot happen, i.e. that the message is always shown. However, in order 
to be sure, I had to check all code paths and had to think about ways 
they become unreachable – with the chance that I miss something.

> If gfc_warning is never reached, then we could have used gfc_warning_now.
> If the warning is printed, then gfc_warning was reached, thus we could
> have used gfc_warning_now.

I concur; the question is only whether my impression is correct. You 
could try to map gfc_warning to gfc_warning_now_1 and see whether 
something in the testsuite breaks.

> The only difference is that gfc_warning_now will print the warning as
> soon as gfc_warning is reached, but since there is at most one
> buffered warning and there can not be a previous error, then this
> should not make a difference. What am I missing here?

(a) That, conceptionally, warning buffering makes sense, if you 
buffering errors for rewinding - even if it only occurs for error and 
not for warnings. (b) That I might have missed some code path. (c) That 
one might add such a code path in future.

Except for (b), I do not see a reason not to map gfc_warning to 
gfc_warning_now. If one later needs buffering, one can still take 
gfc_error as model for implementing it as it surely needs buffering.

FX, Steve et al.: Comments or additional facts?

>>> 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?
>> However, the change
>>
>> -         gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus);
>> +         gfc_warning_now ("Line truncated at %L", &gfc_current_locus);
>>
>> still triggers an ICE with "gfortran -Wall test.f90" and with "test.f" (two
>> locations in scanner.c; see attached test cases and attache patch). The
>> backtrace for test.f90 is:
> The problem seems to be that linemap_position_for_loc_and_offset
> cannot handle an offset larger than the column_hint. Fortran hardcodes
> that to 120. There are two bugs there: (1) we should not crash, at
> worst we should use offset=0 and (2) we should update the column_hint
> to the largest column seen. I'm testing a patch that seems to fix the
> problem.

Fortran (old code) chops off items from the beginning of the line if the 
column number is high (and also trimps the output line to the right). 
Thus, instead of
   print 'aa.................'
     ....................(1)
is just show
    aaaaaaa'
        (1)
I don't know how C/C++ handles this. If one doesn't chop off, the output 
can become extremely long – especially with "topformflat 0". And then 
the "^" is also not helpful as one has to count the numbe of lines ...

Tobias
diff mbox

Patch

diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 884fe70..5b42777 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -777,6 +777,6 @@  skip_free_comments (void)
 			  else
-			    gfc_warning_now_1 ("!$OMP at %C starts a commented "
-					       "line as it neither is followed "
-					       "by a space nor is a "
-					       "continuation line");
+			    gfc_warning_now ("!$OMP at %C starts a commented "
+					     "line as it neither is followed "
+					     "by a space nor is a "
+					     "continuation line");
 			}
@@ -1058,3 +1058,3 @@  restart:
 	  gfc_current_locus.nextc =  gfc_current_locus.lb->line + maxlen;
-	  gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus);
+	  gfc_warning_now ("Line truncated at %L", &gfc_current_locus);
 	  gfc_current_locus.nextc = current_nextc;
@@ -1196,3 +1196,3 @@  restart:
 	  gfc_current_locus.lb->truncated = 0;
-	  gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus);
+	  gfc_warning_now ("Line truncated at %L", &gfc_current_locus);
 	}
@@ -1390,3 +1390,3 @@  gfc_gobble_whitespace (void)
 	      linenum = cur_linenum;
-	      gfc_warning_now_1 ("Nonconforming tab character at %C");
+	      gfc_warning_now (OPT_Wtabs, "Nonconforming tab character at %C");
 	    }