Using the option `-fdiagnostics-format=json` with gfortran yields unexpected and erroneous output. Consider the trivial MWE tmp.f90 ```fortran program main implicit none print*, "Hello World!" end program main ``` One would expect when compiled the json output to be empty, but gfortran -fdiagnostics-format=json tmp.f90 results to (formatted to be human readable) ```json [ { "kind": "error", "column-origin": 1, "children": [ { "kind": "error", "escape-source": false, "locations": [ { "caret": { "byte-column": 13, "display-column": 13, "line": 2, "file": "tmp.f90", "column": 13 } } ], "message": "Function ‘implicit’ requires an argument list at (1)" }, { "kind": "error", "escape-source": false, "locations": [ { "caret": { "byte-column": 13, "display-column": 13, "line": 2, "file": "tmp.f90", "column": 13 } } ], "message": "Syntax error in IMPLICIT statement at (1)" }, { "kind": "error", "escape-source": false, "locations": [ { "caret": { "byte-column": 10, "display-column": 10, "line": 3, "file": "tmp.f90", "column": 10 } } ], "message": "Function ‘print’ requires an argument list at (1)" }, { "kind": "error", "escape-source": false, "locations": [ { "caret": { "byte-column": 4, "display-column": 4, "line": 4, "file": "tmp.f90", "column": 4 } } ], "message": "Function ‘end’ requires an argument list at (1)" } ], "escape-source": false, "locations": [ { "caret": { "byte-column": 8, "display-column": 8, "line": 1, "file": "tmp.f90", "column": 8 } } ], "message": "Function ‘program’ requires an argument list at (1)" } ] ```
Thanks for filing this. Reproducable with trunk. On trunk I also see similar behavior with the new SARIF output format via options: -fdiagnostics-format=sarif-stderr -fdiagnostics-format=sarif-file and with: -fdiagnostics-format=json-file With json output, the json::object for the error is being stashed for later output here: (gdb) bt #0 json_end_diagnostic (context=0x3f4a370, diagnostic=0x3f46100, orig_diag_kind=DK_UNSPECIFIED) at ../../src/gcc/diagnostic-format-json.cc:159 #1 0x0000000002e78ecf in diagnostic_report_diagnostic (context=0x3f31b00 <global_diagnostic_context>, diagnostic=0x7fffffffd170) at ../../src/gcc/diagnostic.cc:1548 #2 0x0000000000adaca8 in gfc_report_diagnostic (diagnostic=0x7fffffffd170) at ../../src/gcc/fortran/error.cc:883 #3 0x0000000000adc61d in gfc_error_opt(int, const char *, typedef __va_list_tag __va_list_tag *) (opt=0, gmsgid=0x2f7b0d0 "Function %qs requires an argument list at %C", ap=0x7fffffffd258) at ../../src/gcc/fortran/error.cc:1453 #4 0x0000000000adc7ce in gfc_error (gmsgid=0x2f7b0d0 "Function %qs requires an argument list at %C") at ../../src/gcc/fortran/error.cc:1482 #5 0x0000000000b83162 in gfc_match_rvalue (result=0x7fffffffd4b0) at ../../src/gcc/fortran/primary.cc:3711 #6 0x0000000000b319f3 in match_primary (result=0x7fffffffd4b0) at ../../src/gcc/fortran/matchexp.cc:157 #7 0x0000000000b31b0e in match_level_1 (result=0x7fffffffd508) at ../../src/gcc/fortran/matchexp.cc:211 #8 0x0000000000b31bd8 in match_mult_operand (result=0x7fffffffd568) at ../../src/gcc/fortran/matchexp.cc:267 #9 0x0000000000b31df1 in match_add_operand (result=0x7fffffffd5b0) at ../../src/gcc/fortran/matchexp.cc:356 #10 0x0000000000b320bf in match_level_2 (result=0x7fffffffd608) at ../../src/gcc/fortran/matchexp.cc:480 #11 0x0000000000b32257 in match_level_3 (result=0x7fffffffd678) at ../../src/gcc/fortran/matchexp.cc:551 #12 0x0000000000b32361 in match_level_4 (result=0x7fffffffd6c8) at ../../src/gcc/fortran/matchexp.cc:599 #13 0x0000000000b32616 in match_and_operand (result=0x7fffffffd718) at ../../src/gcc/fortran/matchexp.cc:693 #14 0x0000000000b3269e in match_or_operand (result=0x7fffffffd768) at ../../src/gcc/fortran/matchexp.cc:722 #15 0x0000000000b327a8 in match_equiv_operand (result=0x7fffffffd7b8) at ../../src/gcc/fortran/matchexp.cc:765 #16 0x0000000000b328b2 in match_level_5 (result=0x7fffffffd810) at ../../src/gcc/fortran/matchexp.cc:811 #17 0x0000000000b32a01 in gfc_match_expr (result=0x7fffffffd9b0) at ../../src/gcc/fortran/matchexp.cc:870 #18 0x0000000000b24e0e in gfc_match (target=0x2f66b7a " %e") at ../../src/gcc/fortran/match.cc:1125 #19 0x0000000000b2e443 in gfc_match_ptr_fcn_assign () at ../../src/gcc/fortran/match.cc:6039 #20 0x0000000000b693e9 in match_word (str=0x0, subr=0xb2e2c3 <gfc_match_ptr_fcn_assign()>, old_locus=0x7fffffffdba0) at ../../src/gcc/fortran/parse.cc:67 #21 0x0000000000b6a0d8 in decode_statement () at ../../src/gcc/fortran/parse.cc:375 #22 0x0000000000b72035 in next_free () at ../../src/gcc/fortran/parse.cc:1397 #23 0x0000000000b72664 in next_statement () at ../../src/gcc/fortran/parse.cc:1629 #24 0x0000000000b7af20 in gfc_parse_file () at ../../src/gcc/fortran/parse.cc:6738 #25 0x0000000000be3143 in gfc_be_parse_file () at ../../src/gcc/fortran/f95-lang.cc:229 #26 0x0000000001523847 in compile_file () at ../../src/gcc/toplev.cc:452 #27 0x0000000001527367 in do_compile (no_backend=false) at ../../src/gcc/toplev.cc:2144 #28 0x00000000015277f9 in toplev::main (this=0x7fffffffde3a, argc=15, argv=0x7fffffffdf48) at ../../src/gcc/toplev.cc:2296 #29 0x0000000002e4ab76 in main (argc=15, argv=0x7fffffffdf48) at ../../src/gcc/main.cc:39
With the default diagnostic output format, for this error it looks like gfc_error_opt uses a "buffered_p" global; the message is written to a pp_error_buffer, rather than the diagnostic context's regular pretty printer. The buffering is enabled here: (gdb) bt #0 gfc_buffer_error (flag=true) at ../../src/gcc/fortran/error.cc:120 #1 0x0000000000b725f7 in next_statement () at ../../src/gcc/fortran/parse.cc:1611 #2 0x0000000000b7af20 in gfc_parse_file () at ../../src/gcc/fortran/parse.cc:6738 #3 0x0000000000be3143 in gfc_be_parse_file () at ../../src/gcc/fortran/f95-lang.cc:229 #4 0x0000000001523847 in compile_file () at ../../src/gcc/toplev.cc:452 #5 0x0000000001527367 in do_compile (no_backend=false) at ../../src/gcc/toplev.cc:2144 #6 0x00000000015277f9 in toplev::main (this=0x7fffffffde6a, argc=14, argv=0x7fffffffdf78) at ../../src/gcc/toplev.cc:2296 #7 0x0000000002e4ab76 in main (argc=14, argv=0x7fffffffdf78) at ../../src/gcc/main.cc:39 #1 0x0000000000b725f7 in next_statement () at ../../src/gcc/fortran/parse.cc:1611 1611 gfc_buffer_error (true); (gdb) list 1606 gfc_current_ns->old_equiv = gfc_current_ns->equiv; 1607 gfc_current_ns->old_data = gfc_current_ns->data; 1608 for (;;) 1609 { 1610 gfc_statement_label = NULL; 1611 gfc_buffer_error (true); <<<<<< BUFFERING ENABLED HERE 1612 1613 if (gfc_at_eol ()) 1614 gfc_advance_line (); 1615 1616 gfc_skip_comments (); 1617 1618 if (gfc_at_end ()) 1619 { 1620 st = ST_NONE; 1621 break; 1622 } 1623 1624 if (gfc_define_undef_line ()) 1625 continue; 1626 1627 old_locus = gfc_current_locus; 1628 1629 st = (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free (); 1630 1631 if (st != ST_NONE) 1632 break; 1633 } 1634 1635 gfc_buffer_error (false); <<<<<< BUFFERING DISABLED HERE The output handling for json/sarif doesn't know about this fortran-specific buffered_p thing, hence these buffered errors get erroneously added to the JSON/SARIF output.