Various values of -fdiagnostics-format= request machine-readable output on stderr, using JSON, but in various places we use fnotice to write free-form text to stderr, such as "compilation terminated", leading to corrupt JSON.
Fix by having fnotice skip the output for such cases. Backported from r14-9554-g0bf99b1b7eda2f (using a variable rather than a vfunc of class diagnostic_output_format, since the latter was added in gcc 14) gcc/ChangeLog: PR middle-end/114348 * diagnostic.cc (output_format): New variable. (fnotice): Bail out if the user requested one of the machine-readable diagnostic output formats on stderr. (diagnostic_output_format_init): Set output_format. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/diagnostic.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 0f093081161..a3d84cf0bfa 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -2175,6 +2175,9 @@ internal_error_no_backtrace (const char *gmsgid, ...) gcc_unreachable (); } + +static enum diagnostics_output_format output_format; + /* Special case error functions. Most are implemented in terms of the above, or should be. */ @@ -2183,6 +2186,25 @@ internal_error_no_backtrace (const char *gmsgid, ...) void fnotice (FILE *file, const char *cmsgid, ...) { + /* If the user requested one of the machine-readable diagnostic output + formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then + emitting free-form text on stderr will lead to corrupt output. + Skip the message for such cases. */ + if (file == stderr && global_dc) + switch (output_format) + { + default: + gcc_unreachable (); + case DIAGNOSTICS_OUTPUT_FORMAT_TEXT: + case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE: + case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE: + break; + case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR: + case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR: + /* stderr is meant to machine-readable; skip. */ + return; + } + va_list ap; va_start (ap, cmsgid); @@ -2290,6 +2312,8 @@ diagnostic_output_format_init (diagnostic_context *context, const char *base_file_name, enum diagnostics_output_format format) { + output_format = format; + switch (format) { default: -- 2.26.3