diagnostics: fix <title> of experimental-html output [PR116792]

Add a new vfunc diagnostic_output_format::set_main_input_filename
so that we can separate setting the <title> of HTML output and
the diagnostic_artifact_role::analysis_target of SARIF output from
creation of the sinks.  Calling it is done by the various creators
of the sinks.

gcc/ChangeLog:
	PR other/116792
	* diagnostic-format-html.cc (html_builder::m_title_element): New
	field.
	(html_builder::html_builder): Initialize it.  Don't add
	placeholder text.
	(html_builder::set_main_input_filename): New.
	(html_output_format::set_main_input_filename): New.
	(test_html_diagnostic_context::test_html_diagnostic_context): Call
	set_main_input_filename on the new sink.
	(seldtest::test_simple_log): Update expected <title> text.
	* diagnostic-format-json.cc (diagnostic_output_format_init_json):
	Return a reference to the new sink.
	(diagnostic_output_format_init_json_stderr): Likewise.
	(diagnostic_output_format_init_json_file): Likewise.
	* diagnostic-format-sarif.cc (sarif_builder::sarif_builder): Drop
	"main_input_filename_" param, and move adding an artifact for it
	with diagnostic_artifact_role::analysis_target to...
	(sarif_builder::set_main_input_filename): ...this new function.
	(sarif_output_format::set_main_input_filename): New.
	(sarif_output_format::sarif_output_format): Drop
	"main_input_filename_" param.
	(sarif_stream_output_format::sarif_stream_output_format):
	Likewise.
	(sarif_file_output_format::sarif_file_output_format): Likewise.
	(diagnostic_output_format_init_sarif): Return a reference to *FMT.
	(diagnostic_output_format_init_sarif_stderr): Return a refererence
	to the new sink.  Drop "main_input_filename_" param.
	(diagnostic_output_format_init_sarif_file): Likewise.
	(diagnostic_output_format_init_sarif_stream): Likewise.
	(make_sarif_sink): Drop "main_input_filename_" param.
	(selftest::test_sarif_diagnostic_context::test_sarif_diagnostic_context):
	Likewise.  Call set_main_input_filename on the new format.
	(selftest::test_sarif_diagnostic_context::buffered_output_format::buffered_output_format):
	Drop "main_input_filename_" param.
	(selftest::test_make_location_object): Likewise.
	* diagnostic-format-sarif.h
	(diagnostic_output_format_init_sarif_stderr): Return a refererence
	to the new sink.  Drop "main_input_filename_" param.
	(diagnostic_output_format_init_sarif_file): Likewise.
	(diagnostic_output_format_init_sarif_stream): Likewise.
	(make_sarif_sink): Drop "main_input_filename_" param.
	* diagnostic-format.h
	(diagnostic_output_format::set_main_input_filename): New vfunc.
	(diagnostic_output_format_init_json_stderr): Return a refererence
	to the new sink.
	(diagnostic_output_format_init_json_file): Likewise.
	* diagnostic.cc (diagnostic_output_format_init): Likewise.  Call
	set_main_input_filename on the new sink.
	* libgdiagnostics.cc (sarif_sink::sarif_sink): Update for above
	changes.
	* opts-diagnostic.cc (sarif_scheme_handler::make_sink): Likewise.
	(handle_OPT_fdiagnostics_add_output_): Likewise.
	(handle_OPT_fdiagnostics_set_output_): Likewise.

gcc/testsuite/ChangeLog:
	PR other/116792
	* gcc.dg/html-output/missing-semicolon.py: Update expected <title>
	text.  Drop out-of-date comment.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm
2025-06-09 09:40:06 -04:00
parent af3de9e209
commit 82de4cada8
9 changed files with 118 additions and 101 deletions

View File

@@ -104,6 +104,9 @@ public:
const line_maps *line_maps,
const html_generation_options &html_gen_opts);
void
set_main_input_filename (const char *name);
void on_report_diagnostic (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
diagnostic_html_format_buffer *buffer);
@@ -151,6 +154,7 @@ private:
std::unique_ptr<xml::document> m_document;
xml::element *m_head_element;
xml::element *m_title_element;
xml::element *m_diagnostics_element;
std::unique_ptr<xml::element> m_cur_diagnostic_element;
int m_next_diag_id; // for handing out unique IDs
@@ -348,6 +352,7 @@ html_builder::html_builder (diagnostic_context &context,
m_line_maps (line_maps),
m_html_gen_opts (html_gen_opts),
m_head_element (nullptr),
m_title_element (nullptr),
m_diagnostics_element (nullptr),
m_next_diag_id (0)
{
@@ -367,7 +372,7 @@ html_builder::html_builder (diagnostic_context &context,
m_head_element = xp.get_insertion_point ();
{
xml::auto_print_element title (xp, "title", true);
xp.add_text ("Title goes here");
m_title_element = xp.get_insertion_point ();
}
if (m_html_gen_opts.m_css)
xp.add_raw (HTML_STYLE);
@@ -392,6 +397,17 @@ html_builder::html_builder (diagnostic_context &context,
}
}
void
html_builder::set_main_input_filename (const char *name)
{
gcc_assert (m_title_element);
if (name)
{
m_title_element->m_children.clear ();
m_title_element->add_text (name);
}
}
/* Implementation of "on_report_diagnostic" for HTML output. */
void
@@ -765,6 +781,12 @@ public:
diagnostic_output_format::dump (out, indent);
}
void
set_main_input_filename (const char *name) final override
{
m_builder.set_main_input_filename (name);
}
std::unique_ptr<diagnostic_per_format_buffer>
make_per_format_buffer () final override
{
@@ -940,6 +962,7 @@ public:
line_table,
html_gen_opts);
sink->update_printer ();
sink->set_main_input_filename ("(main input filename)");
m_format = sink.get (); // borrowed
set_output_format (std::move (sink));
@@ -998,7 +1021,7 @@ test_simple_log ()
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
" <head>\n"
" <title>Title goes here</title>\n"
" <title>(main input filename)</title>\n"
" </head>\n"
" <body>\n"
" <div class=\"gcc-diagnostic-list\">\n"

View File

@@ -505,40 +505,47 @@ private:
};
/* Populate CONTEXT in preparation for JSON output (either to stderr, or
to a file). */
to a file) using FMT. Return a reference to *FMT. */
static void
static diagnostic_output_format &
diagnostic_output_format_init_json (diagnostic_context &context,
std::unique_ptr<json_output_format> fmt)
{
gcc_assert (fmt);
diagnostic_output_format &out = *fmt;
/* Don't colorize the text. */
pp_show_color (fmt->get_printer ()) = false;
context.set_show_highlight_colors (false);
context.set_output_format (std::move (fmt));
return out;
}
/* Populate CONTEXT in preparation for JSON output to stderr. */
/* Populate CONTEXT in preparation for JSON output to stderr.
Return a reference to the context's new sink. */
void
diagnostic_output_format &
diagnostic_output_format_init_json_stderr (diagnostic_context &context,
bool formatted)
{
diagnostic_output_format_init_json
return diagnostic_output_format_init_json
(context,
std::make_unique<json_stderr_output_format> (context,
formatted));
}
/* Populate CONTEXT in preparation for JSON output to a file named
BASE_FILE_NAME.gcc.json. */
BASE_FILE_NAME.gcc.json.
Return a reference to the context's new sink. */
void
diagnostic_output_format &
diagnostic_output_format_init_json_file (diagnostic_context &context,
bool formatted,
const char *base_file_name)
{
diagnostic_output_format_init_json
return diagnostic_output_format_init_json
(context,
std::make_unique<json_file_output_format> (context,
formatted,

View File

@@ -751,7 +751,6 @@ public:
sarif_builder (diagnostic_context &context,
pretty_printer &printer,
const line_maps *line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts);
~sarif_builder ();
@@ -767,6 +766,9 @@ public:
return m_logical_loc_mgr;
}
void
set_main_input_filename (const char *name);
void on_report_diagnostic (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
diagnostic_sarif_format_buffer *buffer);
@@ -1643,7 +1645,6 @@ sarif_thread_flow::add_location ()
sarif_builder::sarif_builder (diagnostic_context &context,
pretty_printer &printer,
const line_maps *line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts)
: m_context (context),
@@ -1672,17 +1673,6 @@ sarif_builder::sarif_builder (diagnostic_context &context,
if (auto client_data_hooks = context.get_client_data_hooks ())
m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
/* Mark MAIN_INPUT_FILENAME_ as the artifact that the tool was
instructed to scan.
Only quote the contents if it gets referenced by physical locations,
since otherwise the "no diagnostics" case would quote the main input
file, and doing so noticeably bloated the output seen in analyzer
integration testing (build directory went from 20G -> 21G). */
if (main_input_filename_)
get_or_create_artifact (main_input_filename_,
diagnostic_artifact_role::analysis_target,
false);
}
sarif_builder::~sarif_builder ()
@@ -1820,6 +1810,20 @@ sarif_builder::make_stack_from_backtrace ()
return stack;
}
void
sarif_builder::set_main_input_filename (const char *name)
{
/* Mark NAME as the artifact that the tool was instructed to scan.
Only quote the contents if it gets referenced by physical locations,
since otherwise the "no diagnostics" case would quote the main input
file, and doing so noticeably bloated the output seen in analyzer
integration testing (build directory went from 20G -> 21G). */
if (name)
get_or_create_artifact (name,
diagnostic_artifact_role::analysis_target,
false);
}
/* Implementation of "on_report_diagnostic" for SARIF output. */
void
@@ -3657,6 +3661,12 @@ public:
diagnostic_output_format::dump (out, indent);
}
void
set_main_input_filename (const char *name) final override
{
m_builder.set_main_input_filename (name);
}
std::unique_ptr<diagnostic_per_format_buffer>
make_per_format_buffer () final override
{
@@ -3722,11 +3732,10 @@ public:
protected:
sarif_output_format (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts)
: diagnostic_output_format (context),
m_builder (context, *get_printer (), line_maps, main_input_filename_,
m_builder (context, *get_printer (), line_maps,
std::move (serialization_format), sarif_gen_opts),
m_buffer (nullptr)
{}
@@ -3740,11 +3749,10 @@ class sarif_stream_output_format : public sarif_output_format
public:
sarif_stream_output_format (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts,
FILE *stream)
: sarif_output_format (context, line_maps, main_input_filename_,
: sarif_output_format (context, line_maps,
std::move (serialization_format), sarif_gen_opts),
m_stream (stream)
{
@@ -3766,11 +3774,10 @@ class sarif_file_output_format : public sarif_output_format
public:
sarif_file_output_format (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts,
diagnostic_output_file output_file)
: sarif_output_format (context, line_maps, main_input_filename_,
: sarif_output_format (context, line_maps,
std::move (serialization_format), sarif_gen_opts),
m_output_file (std::move (output_file))
{
@@ -3914,34 +3921,39 @@ sarif_builder::sarif_token_printer::print_tokens (pretty_printer *pp,
}
/* Populate CONTEXT in preparation for SARIF output (either to stderr, or
to a file). */
to a file).
Return a reference to *FMT. */
static void
static diagnostic_output_format &
diagnostic_output_format_init_sarif (diagnostic_context &context,
std::unique_ptr<sarif_output_format> fmt)
{
gcc_assert (fmt);
diagnostic_output_format &out = *fmt;
fmt->update_printer ();
context.set_output_format (std::move (fmt));
return out;
}
/* Populate CONTEXT in preparation for SARIF output to stderr. */
/* Populate CONTEXT in preparation for SARIF output to stderr.
Return a reference to the new sink. */
void
diagnostic_output_format &
diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
bool formatted)
{
gcc_assert (line_maps);
const sarif_generation_options sarif_gen_opts;
auto serialization
= std::make_unique<sarif_serialization_format_json> (formatted);
diagnostic_output_format_init_sarif
return diagnostic_output_format_init_sarif
(context,
std::make_unique<sarif_stream_output_format> (context,
line_maps,
main_input_filename_,
std::move (serialization),
sarif_gen_opts,
stderr));
@@ -4018,12 +4030,12 @@ diagnostic_output_format_open_sarif_file (diagnostic_context &context,
}
/* Populate CONTEXT in preparation for SARIF output to a file named
BASE_FILE_NAME.sarif. */
BASE_FILE_NAME.sarif.
Return a reference to the new sink. */
void
diagnostic_output_format &
diagnostic_output_format_init_sarif_file (diagnostic_context &context,
line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
const char *base_file_name)
{
@@ -4038,22 +4050,21 @@ diagnostic_output_format_init_sarif_file (diagnostic_context &context,
= std::make_unique<sarif_serialization_format_json> (formatted);
const sarif_generation_options sarif_gen_opts;
diagnostic_output_format_init_sarif
return diagnostic_output_format_init_sarif
(context,
std::make_unique<sarif_file_output_format> (context,
line_maps,
main_input_filename_,
std::move (serialization),
sarif_gen_opts,
std::move (output_file)));
}
/* Populate CONTEXT in preparation for SARIF output to STREAM. */
/* Populate CONTEXT in preparation for SARIF output to STREAM.
Return a reference to the new sink. */
void
diagnostic_output_format &
diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
FILE *stream)
{
@@ -4061,11 +4072,10 @@ diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
const sarif_generation_options sarif_gen_opts;
auto serialization
= std::make_unique<sarif_serialization_format_json> (formatted);
diagnostic_output_format_init_sarif
return diagnostic_output_format_init_sarif
(context,
std::make_unique<sarif_stream_output_format> (context,
line_maps,
main_input_filename_,
std::move (serialization),
sarif_gen_opts,
stream));
@@ -4074,7 +4084,6 @@ diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
std::unique_ptr<diagnostic_output_format>
make_sarif_sink (diagnostic_context &context,
const line_maps &line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization,
const sarif_generation_options &sarif_gen_opts,
diagnostic_output_file output_file)
@@ -4082,7 +4091,6 @@ make_sarif_sink (diagnostic_context &context,
auto sink
= std::make_unique<sarif_file_output_format> (context,
&line_maps,
main_input_filename_,
std::move (serialization),
sarif_gen_opts,
std::move (output_file));
@@ -4183,11 +4191,11 @@ public:
{
auto format = std::make_unique<buffered_output_format> (*this,
line_table,
main_input_filename,
true,
sarif_gen_opts);
m_format = format.get (); // borrowed
diagnostic_output_format_init_sarif (*this, std::move (format));
m_format->set_main_input_filename (main_input_filename);
}
std::unique_ptr<sarif_log> flush_to_object ()
@@ -4204,10 +4212,9 @@ private:
public:
buffered_output_format (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
const sarif_generation_options &sarif_gen_opts)
: sarif_output_format (context, line_maps, main_input_filename_,
: sarif_output_format (context, line_maps,
std::make_unique<sarif_serialization_format_json>
(formatted),
sarif_gen_opts)
@@ -4243,7 +4250,7 @@ test_make_location_object (const sarif_generation_options &sarif_gen_opts,
test_diagnostic_context dc;
pretty_printer pp;
sarif_builder builder
(dc, pp, line_table, "MAIN_INPUT_FILENAME",
(dc, pp, line_table,
std::make_unique<sarif_serialization_format_json> (true),
sarif_gen_opts);

View File

@@ -41,21 +41,18 @@ diagnostic_output_format_open_sarif_file (diagnostic_context &context,
const char *base_file_name,
enum sarif_serialization_kind serialization_kind);
extern void
extern diagnostic_output_format &
diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
bool formatted);
extern void
extern diagnostic_output_format &
diagnostic_output_format_init_sarif_file (diagnostic_context &context,
line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
const char *base_file_name);
extern void
extern diagnostic_output_format &
diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
const line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
FILE *stream);
@@ -109,7 +106,6 @@ struct sarif_generation_options
extern std::unique_ptr<diagnostic_output_format>
make_sarif_sink (diagnostic_context &context,
const line_maps &line_maps,
const char *main_input_filename_,
std::unique_ptr<sarif_serialization_format> serialization_format,
const sarif_generation_options &sarif_gen_opts,
diagnostic_output_file output_file);

View File

@@ -36,6 +36,10 @@ public:
virtual void dump (FILE *out, int indent) const;
/* Vfunc for notifying this format what the primary input file is,
e.g. for titles of HTML, for SARIF's artifact metadata. */
virtual void set_main_input_filename (const char *) {}
/* Vfunc for making an appropriate diagnostic_per_format_buffer
subclass for this format. */
virtual std::unique_ptr<diagnostic_per_format_buffer>
@@ -95,10 +99,11 @@ diagnostic_output_format_init (diagnostic_context &,
const char *base_file_name,
enum diagnostics_output_format,
bool json_formatting);
extern void
extern diagnostic_output_format &
diagnostic_output_format_init_json_stderr (diagnostic_context &context,
bool formatted);
extern void
extern diagnostic_output_format &
diagnostic_output_format_init_json_file (diagnostic_context &context,
bool formatted,
const char *base_file_name);

View File

@@ -1865,6 +1865,7 @@ diagnostic_output_format_init (diagnostic_context &context,
enum diagnostics_output_format format,
bool json_formatting)
{
diagnostic_output_format *new_sink = nullptr;
switch (format)
{
default:
@@ -1874,31 +1875,31 @@ diagnostic_output_format_init (diagnostic_context &context,
break;
case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
diagnostic_output_format_init_json_stderr (context,
json_formatting);
new_sink = &diagnostic_output_format_init_json_stderr (context,
json_formatting);
break;
case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
diagnostic_output_format_init_json_file (context,
json_formatting,
base_file_name);
new_sink = &diagnostic_output_format_init_json_file (context,
json_formatting,
base_file_name);
break;
case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
diagnostic_output_format_init_sarif_stderr (context,
line_table,
main_input_filename_,
json_formatting);
new_sink = &diagnostic_output_format_init_sarif_stderr (context,
line_table,
json_formatting);
break;
case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
diagnostic_output_format_init_sarif_file (context,
line_table,
main_input_filename_,
json_formatting,
base_file_name);
new_sink = &diagnostic_output_format_init_sarif_file (context,
line_table,
json_formatting,
base_file_name);
break;
}
if (new_sink)
new_sink->set_main_input_filename (main_input_filename_);
}
/* Initialize this context's m_diagrams based on CHARSET.

View File

@@ -1191,10 +1191,10 @@ sarif_sink::sarif_sink (diagnostic_manager &mgr,
auto serialization = std::make_unique<sarif_serialization_format_json> (true);
auto inner_sink = make_sarif_sink (mgr.get_dc (),
*mgr.get_line_table (),
main_input_file->get_name (),
std::move (serialization),
sarif_gen_opts,
std::move (output_file));
inner_sink->set_main_input_filename (main_input_file->get_name ());
mgr.get_dc ().add_sink (std::move (inner_sink));
}

View File

@@ -531,7 +531,6 @@ sarif_scheme_handler::make_sink (const context &ctxt,
auto sink = make_sarif_sink (ctxt.m_dc,
*line_table,
ctxt.m_opts.x_main_input_filename,
std::move (serialization_obj),
sarif_gen_opts,
std::move (output_file));
@@ -633,6 +632,7 @@ handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts,
if (!sink)
return;
sink->set_main_input_filename (opts.x_main_input_filename);
dc.add_sink (std::move (sink));
}
@@ -657,6 +657,7 @@ handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts,
if (!sink)
return;
sink->set_main_input_filename (opts.x_main_input_filename);
dc.set_output_format (std::move (sink));
}

View File

@@ -26,7 +26,7 @@ def test_basics(html_tree):
assert head is not None
title = head.find('xhtml:title', ns)
assert title.text == 'Title goes here'
assert title.text.endswith('gcc/testsuite/gcc.dg/html-output/missing-semicolon.c')
body = root.find('xhtml:body', ns)
assert body is not None
@@ -56,26 +56,3 @@ def test_basics(html_tree):
assert pre is not None
assert pre.attrib['class'] == 'gcc-generated-patch'
assert pre.text.startswith('--- ')
# For reference, here's the generated HTML:
"""
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Title goes here</title>
</head>
<body>
<div class="gcc-diagnostic-list">
<div class="gcc-diagnostic">
<span class="gcc-message">expected &apos;<span class="gcc-quoted-text">;</span>&apos; before &apos;<span class="gcc-quoted-text">}</span>&apos; token</span>
<pre class="gcc-generated-patch">
[...snip...]
</pre>
</div>
</div>
</body>
</html>
"""