[gcc r15-4081] diagnostics: bulletproof opening of SARIF output [PR116978]

2024-10-04 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:385a232229a5b4ee3f4d2a2472bcda28cd8d17b2

commit r15-4081-g385a232229a5b4ee3f4d2a2472bcda28cd8d17b2
Author: David Malcolm 
Date:   Fri Oct 4 18:31:17 2024 -0400

diagnostics: bulletproof opening of SARIF output [PR116978]

Introduce a new RAII class diagnostic_output_file to track ownership
of the FILE * for SARIF output.

In particular, the .sarif file is now opened immediately, rather
than at the end of the compile, and so will fail earlier if the
file can't be opened.

Doing so fixes a couple of ICEs in -fdiagnostics-format=sarif-file when
invoking, say, cc1 directly, rather than from the driver.

gcc/ChangeLog:
PR other/116978
* diagnostic-format-sarif.cc (sarif_builder::sarif_builder):
Gracefully handle "main_input_filename_" being NULL.
(sarif_output_format::sarif_output_format): Replace param
"base_file_name" with "output_file" and assert that the file
was opened successfully and has a non-NULL filename.
(sarif_output_format::~sarif_file_output_format): Move
responsibility for building the filename and opening the file from
here to the creator of the instance.
(sarif_output_format::m_base_file_name): Replace with...
(sarif_output_format::m_output_file): ...this.
(diagnostic_output_format_init_sarif_file): Make "line_maps" param
non-const.  Gracefully handle "base_file_name" being NULL.
Construct the filename and open the file here, rather than in
~sarif_file_output_format, and handle failures immediately here,
rather than at the end of the compile.
* diagnostic-format-sarif.h: Include "diagnostic-output-file.h".
(diagnostic_output_format_init_sarif_file): Make "line_maps" param
non-const.
* diagnostic-output-file.h: New file.
* diagnostic.cc (diagnostic_context::emit_diagnostic): New.
(diagnostic_context::emit_diagnostic_va): New.
* diagnostic.h (diagnostic_context::emit_diagnostic): New decl.
(diagnostic_context::emit_diagnostic_va): New decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 57 +++-
 gcc/diagnostic-format-sarif.h  |  3 +-
 gcc/diagnostic-output-file.h   | 75 ++
 gcc/diagnostic.cc  | 41 +++
 gcc/diagnostic.h   | 13 
 5 files changed, 165 insertions(+), 24 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index aeba9f9ceef3..f053dec19205 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1510,9 +1510,10 @@ sarif_builder::sarif_builder (diagnostic_context 
&context,
  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).  */
-  get_or_create_artifact (main_input_filename_,
- diagnostic_artifact_role::analysis_target,
- false);
+  if (main_input_filename_)
+get_or_create_artifact (main_input_filename_,
+   diagnostic_artifact_role::analysis_target,
+   false);
 }
 
 sarif_builder::~sarif_builder ()
@@ -3239,29 +3240,17 @@ public:
const char *main_input_filename_,
bool formatted,
enum sarif_version version,
-   const char *base_file_name)
+   diagnostic_output_file output_file)
   : sarif_output_format (context, line_maps, main_input_filename_,
 formatted, version),
-m_base_file_name (xstrdup (base_file_name))
+m_output_file (std::move (output_file))
   {
+gcc_assert (m_output_file.get_open_file ());
+gcc_assert (m_output_file.get_filename ());
   }
   ~sarif_file_output_format ()
   {
-char *filename = concat (m_base_file_name, ".sarif", nullptr);
-free (m_base_file_name);
-m_base_file_name = nullptr;
-FILE *outf = fopen (filename, "w");
-if (!outf)
-  {
-   const char *errstr = xstrerror (errno);
-   fnotice (stderr, "error: unable to open '%s' for writing: %s\n",
-filename, errstr);
-   free (filename);
-   return;
-  }
-m_builder.flush_to_file (outf);
-fclose (outf);
-free (filename);
+m_builder.flush_to_file (m_output_file.get_open_file ());
   }
   bool machine_readable_stderr_p () const final override
   {
@@ -3269,7 +3258,7 @@ public:
   }
 
 private:
-  char *m_base_file_name;
+  diagnostic_output_file m_output_file;
 };
 
 /* Print the start of an embedded link to PP, as per 3.11.6.  */
@@ -3435,13 +3

[gcc r15-3978] diagnostics: return text buffer from test_show_locus [PR116613]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:9c14f9a9c19957d9a45a7df97701bad475c80eea

commit r15-3978-g9c14f9a9c19957d9a45a7df97701bad475c80eea
Author: David Malcolm 
Date:   Mon Sep 30 11:48:30 2024 -0400

diagnostics: return text buffer from test_show_locus [PR116613]

As work towards supporting multiple diagnostic outputs (where each
output has its own pretty_printer), avoid referencing dc.m_printer
throughout the selftests of diagnostic-show-locus.cc.  Instead
have test_diagnostic_context::test_show_locus return the result
buffer, hiding the specifics of which printer is in use in such
test cases.

No functional change intended.

gcc/ChangeLog:
PR other/116613
* diagnostic-show-locus.cc
(selftest::test_diagnostic_show_locus_unknown_location): Move call
to dc.test_show_locus into ASSERT_STREQ, and compare against its
result, rather than explicitly using dc.m_printer.
(selftest::test_one_liner_simple_caret): Likewise.
(selftest::test_one_liner_no_column): Likewise.
(selftest::test_one_liner_caret_and_range): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges): Likewise.
(selftest::test_one_liner_fixit_insert_before): Likewise.
(selftest::test_one_liner_fixit_insert_after): Likewise.
(selftest::test_one_liner_fixit_remove): Likewise.
(selftest::test_one_liner_fixit_replace): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations):
Likewise.
(selftest::test_one_liner_many_fixits_1): Likewise.
(selftest::test_one_liner_many_fixits_2): Likewise.
(selftest::test_one_liner_labels): Likewise.
(selftest::test_one_liner_simple_caret_utf8): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges_utf8):
Likewise.
(selftest::test_one_liner_fixit_insert_before_utf8): Likewise.
(selftest::test_one_liner_fixit_insert_after_utf8): Likewise.
(selftest::test_one_liner_fixit_remove_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations_utf8):
Likewise.
(selftest::test_one_liner_many_fixits_1_utf8): Likewise.
(selftest::test_one_liner_many_fixits_2_utf8): Likewise.
(selftest::test_one_liner_labels_utf8): Likewise.
(selftest::test_one_liner_colorized_utf8): Likewise.
(selftest::test_add_location_if_nearby): Likewise.
(selftest::test_diagnostic_show_locus_fixit_lines): Likewise.
(selftest::test_overlapped_fixit_printing): Likewise.
(selftest::test_overlapped_fixit_printing_utf8): Likewise.
(selftest::test_overlapped_fixit_printing_utf8): Likewise.
(selftest::test_overlapped_fixit_printing_2): Likewise.
(selftest::test_fixit_insert_containing_newline): Likewise.
(selftest::test_fixit_insert_containing_newline_2): Likewise.
(selftest::test_fixit_replace_containing_newline): Likewise.
(selftest::test_fixit_deletion_affecting_newline): Likewise.
(selftest::test_tab_expansion): Likewise.
(selftest::test_escaping_bytes_1): Likewise.
(selftest::test_escaping_bytes_2): Likewise.
(selftest::test_line_numbers_multiline_range): Likewise.
* selftest-diagnostic.cc
(selftest::test_diagnostic_context::test_show_locus): Return the
formatted text of m_printer.
* selftest-diagnostic.h
(selftest::test_diagnostic_context::test_show_locus): Convert
return type from void to const char *.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-show-locus.cc | 248 +++
 gcc/selftest-diagnostic.cc   |   6 +-
 gcc/selftest-diagnostic.h|   2 +-
 3 files changed, 88 insertions(+), 168 deletions(-)

diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index b575dc51a78c..415de42cbc7b 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -3742,8 +3742,7 @@ test_diagnostic_show_locus_unknown_location ()
 {
   test_diagnostic_context dc;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
-  dc.test_show_locus (richloc);
-  ASSERT_STREQ ("", pp_formatted_text (dc.m_printer));
+  ASSERT_STREQ ("", dc.test_show_locus (richloc));
 }
 
 /* Ve

[gcc r15-3973] diagnostics: add "dump" to pretty_printer and output_buffer

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:4c7a58ac2617e24069c9ad3d469a7f87dc96091d

commit r15-3973-g4c7a58ac2617e24069c9ad3d469a7f87dc96091d
Author: David Malcolm 
Date:   Mon Sep 30 11:48:28 2024 -0400

diagnostics: add "dump" to pretty_printer and output_buffer

No functional change intended.

gcc/ChangeLog:
* pretty-print.cc (output_buffer::dump): New.
(pretty_printer::dump): New.
* pretty-print.h (output_buffer::dump): New decls.
(pretty_printer::dump): New decls.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/pretty-print.cc | 23 +++
 gcc/pretty-print.h  |  6 ++
 2 files changed, 29 insertions(+)

diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 68c145e2d532..6a1d1ec484ba 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -790,6 +790,21 @@ output_buffer::pop_formatted_chunks ()
   obstack_free (&m_chunk_obstack, old_top);
 }
 
+/* Dump state of this output_buffer to OUT, for debugging.  */
+
+void
+output_buffer::dump (FILE *out) const
+{
+  int depth = 0;
+  for (pp_formatted_chunks *iter = m_cur_formatted_chunks;
+   iter;
+   iter = iter->m_prev, depth++)
+{
+  fprintf (out, "pp_formatted_chunks: depth %i\n", depth);
+  iter->dump (out);
+}
+}
+
 #ifndef PTRDIFF_MAX
 #define PTRDIFF_MAX INTTYPE_MAXIMUM (ptrdiff_t)
 #endif
@@ -3013,6 +3028,14 @@ pretty_printer::end_url ()
 pp_string (this, get_end_url_string (this));
 }
 
+/* Dump state of this pretty_printer to OUT, for debugging.  */
+
+void
+pretty_printer::dump (FILE *out) const
+{
+  m_buffer->dump (out);
+}
+
 /* class pp_markup::context.  */
 
 void
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index b5ded5cdd5e0..ec64a167327b 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -93,6 +93,9 @@ public:
   pp_formatted_chunks *push_formatted_chunks ();
   void pop_formatted_chunks ();
 
+  void dump (FILE *out) const;
+  void DEBUG_FUNCTION dump () const { dump (stderr); }
+
   /* Obstack where the text is built up.  */
   struct obstack m_formatted_obstack;
 
@@ -313,6 +316,9 @@ public:
   void set_real_maximum_length ();
   int remaining_character_count_for_line ();
 
+  void dump (FILE *out) const;
+  void DEBUG_FUNCTION dump () const { dump (stderr); }
+
 private:
   /* Where we print external representation of ENTITY.  */
   output_buffer *m_buffer;


[gcc r15-3977] diagnostics: require callers of diagnostic_show_locus to be explicit about the printer [PR116613]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:e7a8fbe2fed83b5ce6e2bdb6fd66d9bf47f74db7

commit r15-3977-ge7a8fbe2fed83b5ce6e2bdb6fd66d9bf47f74db7
Author: David Malcolm 
Date:   Mon Sep 30 11:48:30 2024 -0400

diagnostics: require callers of diagnostic_show_locus to be explicit about 
the printer [PR116613]

As work towards supporting multiple diagnostic outputs (where each
output has its own pretty_printer), update diagnostic_show_locus
so that the pretty_printer must always be explicitly passed in.

No functional change intended.

gcc/c-family/ChangeLog:
PR other/116613
* c-format.cc (selftest::test_type_mismatch_range_labels):
Explicitly pass in dc.m_printer to diagnostic_show_locus.

gcc/ChangeLog:
PR other/116613
* diagnostic-show-locus.cc (diagnostic_context::maybe_show_locus):
Convert param "pp" from * to &.  Drop logic for using the
context's m_printer when the param is null.
* diagnostic.h (diagnostic_context::maybe_show_locus): Convert
param "pp" from * to &.
(diagnostic_show_locus): Drop default "nullptr" value for pp
param.  Assert that it and context are nonnull.  Pass pp by
reference to maybe_show_locus.

gcc/testsuite/ChangeLog:
PR other/116613
* gcc.dg/plugin/expensive_selftests_plugin.c (test_richloc):
Explicitly pass in dc.m_printer to diagnostic_show_locus.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/c-family/c-format.cc | 2 +-
 gcc/diagnostic-show-locus.cc | 8 ++--
 gcc/diagnostic.h | 8 +---
 gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c | 2 +-
 4 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index 614b43266a31..f4a65a5019c3 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -5578,7 +5578,7 @@ test_type_mismatch_range_labels ()
   richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, ¶m_label);
 
   test_diagnostic_context dc;
-  diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+  diagnostic_show_locus (&dc, &richloc, DK_ERROR, dc.m_printer);
   if (c_dialect_cxx ())
 /* "char*", without a space.  */
 ASSERT_STREQ ("   printf (\"msg: %i\\n\", msg);\n"
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index a1d66cf493d6..b575dc51a78c 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -3265,7 +3265,7 @@ add_location_if_nearby (const diagnostic_context &dc,
 void
 diagnostic_context::maybe_show_locus (const rich_location &richloc,
  diagnostic_t diagnostic_kind,
- pretty_printer *pp,
+ pretty_printer &pp,
  diagnostic_source_effect_info *effects)
 {
   const location_t loc = richloc.get_loc ();
@@ -3287,12 +3287,8 @@ diagnostic_context::maybe_show_locus (const 
rich_location &richloc,
 
   m_last_location = loc;
 
-  if (!pp)
-pp = m_printer;
-  gcc_assert (pp);
-
   diagnostic_source_print_policy source_policy (*this);
-  source_policy.print (*pp, richloc, diagnostic_kind, effects);
+  source_policy.print (pp, richloc, diagnostic_kind, effects);
 }
 
 diagnostic_source_print_policy::
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index bc0e67cb4ef2..23a9a1b117b9 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -528,7 +528,7 @@ public:
 
   void maybe_show_locus (const rich_location &richloc,
 diagnostic_t diagnostic_kind,
-pretty_printer *pp,
+pretty_printer &pp,
 diagnostic_source_effect_info *effect_info);
 
   void emit_diagram (const diagnostic_diagram &diagram);
@@ -981,11 +981,13 @@ inline void
 diagnostic_show_locus (diagnostic_context *context,
   rich_location *richloc,
   diagnostic_t diagnostic_kind,
-  pretty_printer *pp = nullptr,
+  pretty_printer *pp,
   diagnostic_source_effect_info *effect_info = nullptr)
 {
+  gcc_assert (context);
   gcc_assert (richloc);
-  context->maybe_show_locus (*richloc, diagnostic_kind, pp, effect_info);
+  gcc_assert (pp);
+  context->maybe_show_locus (*richloc, diagnostic_kind, *pp, effect_info);
 }
 
 /* Because we read source files a second time after the frontend did it the
diff --git a/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c 
b/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
index 3c534005a419..554dad6fa35a 100644
--- a/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
@@ -48,7 +48,7 @@ test_richloc (rich_location *richloc)

[gcc r15-3976] diagnostics: isolate diagnostic_context with interface classes [PR116613]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:be02253af810348be689cfa6f235af96c8cc5802

commit r15-3976-gbe02253af810348be689cfa6f235af96c8cc5802
Author: David Malcolm 
Date:   Mon Sep 30 11:48:29 2024 -0400

diagnostics: isolate diagnostic_context with interface classes [PR116613]

As work towards supporting multiple diagnostic outputs (where each
output has its own pretty_printer), avoid passing around
diagnostic_context to the various printing routines, so that we
can be more explicit about which pretty_printer is in use.

Introduce a set of "policy" classes that capture the parts of
diagnostic_context that are needed, and use these rather than
diagnostic_context *.  Pass around pretty_printer & rather than
taking value from context.  Split out the pretty_printer-using code
from class layout into a new class layout_printer, separating the
responsibilities of determining layout when quoting source versus
actually printing the source.

No functional change intended.

gcc/analyzer/ChangeLog:
PR other/116613
* program-point.cc (function_point::print_source_line): Replace
call to diagnostic_show_locus with a call to
diagnostic_source_print_policy::print.

gcc/ChangeLog:
PR other/116613
* diagnostic-format-json.cc (json_from_expanded_location): Replace
call to diagnostic_context::converted_column with call to
diagnostic_column_policy::converted_column.
* diagnostic-format-sarif.cc
(sarif_builder::make_location_object): Replace call to
diagnostic_show_locus with call to
diagnostic_source_print_policy::print.
* diagnostic-format-text.cc (get_location_text): Replace call to
diagnostic_context::get_location_text with call to
diagnostic_column_policy::get_location_text.
(diagnostic_text_output_format::report_current_module): Replace call
to diagnostic_context::converted_column with call to
diagnostic_column_policy::converted_column.
* diagnostic-format-text.h
(diagnostic_text_output_format::diagnostic_output_format):
Initialize m_column_policy.
(diagnostic_text_output_format::get_column_policy): New.
(diagnostic_text_output_format::m_column_policy): New.
* diagnostic-path.cc (class path_print_policy): New.
(event_range::maybe_add_event): Replace diagnostic_context param
with path_print_policy.
(event_range::print): Convert "pp" from * to &.  Convert first
param of start_span callback from diagnostic_context to
diagnostic_location_print_policy.
(path_summary::path_summary): Convert first param from
diagnostic_text_output_format to path_print_policy.  Add
colorize param.  Update for changes to
event_range::maybe_add_event.
(thread_event_printer::print_swimlane_for_event_range): Assert
that pp is non-null.  Update for change to event_range::print.
(diagnostic_text_output_format::print_path): Pass
path_print_policy to path_summary's ctor.
(selftest::test_empty_path): Likewise.
(selftest::test_intraprocedural_path): Likewise.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(selftest::assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.
* diagnostic-show-locus.cc (colorizer::set_range): Update for
change to m_pp.
(colorizer::m_pp): Convert from * to &.
(class layout): Add friend class layout_printer and move various
decls to it.
(layout::m_pp): Drop field.
(layout::m_policy): Rename to...
(layout::m_char_policy): ...this.
(layout::m_colorizer): Move field to class layout_printer.
(layout::m_diagnostic_path_p): Drop field.
(class layout_printer): New class, by refactoring class layout.
(colorizer::colorizer): Convert "pp" param from * to &.
(colorizer::set_named_color): Update for above change.
(colorizer::begin_state): Likewise.
(colorizer::finish_state): Likewise.
(make_policy): Rename to...
(make_char_policy): ...this, and update param from
diagnostic_context to diagnostic_source_print_policy.
(layout::layout): Update param from diagnostic_context to
diagnostic_source_print_p

[gcc r15-3975] diagnostics: avoid using diagnostic_context's m_printer [PR116613]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:cce52867d1892c08386f780107288473ec0033b7

commit r15-3975-gcce52867d1892c08386f780107288473ec0033b7
Author: David Malcolm 
Date:   Mon Sep 30 11:48:29 2024 -0400

diagnostics: avoid using diagnostic_context's m_printer [PR116613]

As work towards supporting multiple diagnostic outputs (where each
output has its own pretty_printer), avoid using diagnostic_context's
m_printer field.  Instead, use the output format's printer.  Currently
this *is* the dc's printer, but eventually it might not be.

No functional change intended.

gcc/ChangeLog:
PR other/116613
* diagnostic-format-json.cc (diagnostic_output_format_init_json):
Pass in the format.  Use the format's printer when disabling
colorization.  Move the call to set_output_format into here.
(diagnostic_output_format_init_json_stderr): Update for above
change.
(diagnostic_output_format_init_json_file): Likewise.
* diagnostic-format-sarif.cc
(diagnostic_output_format_init_sarif): Use the format's printer
when disabling colorization.
* diagnostic-path.cc (selftest::test_empty_path): Use the
text_output's printer.
(selftest::test_intraprocedural_path): Likewise.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(selftest::assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.

gcc/testsuite/ChangeLog:
PR other/116613
* gcc.dg/plugin/diagnostic_group_plugin.c
(test_output_format::on_begin_group): Use get_printer () rather
than accessing m_context.m_printer.
(test_output_format::on_end_group): Likewise.
* gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
(xhtml_builder::m_printer): New field.
(xhtml_builder::xhtml_builder): Add "pp" param and use it to
initialize m_printer.
(xhtml_builder::on_report_diagnostic): Drop "context" param.
(xhtml_builder::make_element_for_diagnostic): Likewise.  Use
this->m_printer rather than the context's m_printer.  Pass
m_printer to call to diagnostic_show_locus.
(xhtml_builder::emit_diagram): Drop "context" param.
(xhtml_output_format::on_report_diagnostic): Drop context param
from call to m_builder.
(xhtml_output_format::on_diagram): Likewise.
(xhtml_output_format::xhtml_output_format): Pass result of
get_printer as printer for builder.
(diagnostic_output_format_init_xhtml): Use the fmt's printer
rather than the context's.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc  | 23 ++-
 gcc/diagnostic-format-sarif.cc |  2 +-
 gcc/diagnostic-path.cc | 38 -
 .../gcc.dg/plugin/diagnostic_group_plugin.c| 12 +++---
 .../gcc.dg/plugin/diagnostic_plugin_xhtml_format.c | 47 +++---
 5 files changed, 64 insertions(+), 58 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 448b6cb54eee..cf900a9ecba2 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -393,14 +393,17 @@ private:
to a file).  */
 
 static void
-diagnostic_output_format_init_json (diagnostic_context &context)
+diagnostic_output_format_init_json (diagnostic_context &context,
+   std::unique_ptr fmt)
 {
   /* Suppress normal textual path output.  */
   context.set_path_format (DPF_NONE);
 
   /* Don't colorize the text.  */
-  pp_show_color (context.m_printer) = false;
+  pp_show_color (fmt->get_printer ()) = false;
   context.set_show_highlight_colors (false);
+
+  context.set_output_format (fmt.release ());
 }
 
 /* Populate CONTEXT in preparation for JSON output to stderr.  */
@@ -409,9 +412,10 @@ void
 diagnostic_output_format_init_json_stderr (diagnostic_context &context,
   bool formatted)
 {
-  diagnostic_output_format_init_json (context);
-  context.set_output_format (new json_stderr_output_format (context,
-   formatted));
+  diagnostic_output_format_init_json
+(context,
+ ::make_unique (context,
+  formatted));
 }
 
 /* Populate CONTEXT in preparation for JSON output to a file named
@@ -422,10 +426,11 @@ diagnostic_output

[gcc r15-3974] diagnostics: use "%e" to avoid intermediate strings [PR116613]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3d3d20ccd8365970f34002bfe0a632f2868bc95b

commit r15-3974-g3d3d20ccd8365970f34002bfe0a632f2868bc95b
Author: David Malcolm 
Date:   Mon Sep 30 11:48:29 2024 -0400

diagnostics: use "%e" to avoid intermediate strings [PR116613]

Various diagnostics build an intermediate string, potentially with
colorization, and then use this in a diagnostic message.

This won't work if we have multiple diagnostic sinks, where some might
be colorized and some not.

This patch reworks such places using "%e" and pp_element subclasses, so
that any colorization happens within report_diagnostic's call to
pp_format.

gcc/analyzer/ChangeLog:
PR other/116613
* kf-analyzer.cc: Include "pretty-print-markup.h".
(kf_analyzer_dump_escaped::impl_call_pre): Defer colorization
choices by eliminating the construction of a intermediate string,
replacing it with a new pp_element subclass via "%e".

gcc/ChangeLog:
PR other/116613
* attribs.cc: Include "pretty-print-markup.h".
(decls_mismatched_attributes): Defer colorization choices by
replacing printing to a pretty_printer * param with appending
to a vec of strings.
(maybe_diag_alias_attributes): As above, replacing pretty_printer
with usage of pp_markup::comma_separated_quoted_strings and "%e"
in two places.
* attribs.h (decls_mismatched_attributes): Update decl.
* gimple-ssa-warn-access.cc: Include "pretty-print-markup.h".
(pass_waccess::maybe_warn_memmodel): Defer colorization choices by
replacing printing to a pretty_printer * param with use of
pp_markup::comma_separated_quoted_strings and "%e".
(pass_waccess::maybe_warn_memmodel): Likewise, replacing printing
to a temporary buffer.
* pretty-print-markup.h
(class pp_markup::comma_separated_quoted_strings): New.
* pretty-print.cc
(pp_markup::comma_separated_quoted_strings::add_to_phase_2): New.
(selftest::test_pp_printf_within_pp_element): New.
(selftest::test_comma_separated_quoted_strings): New.
(selftest::pretty_print_cc_tests): Call the new tests.

gcc/cp/ChangeLog:
PR other/116613
* pt.cc: Include "pretty-print-markup.h".
(warn_spec_missing_attributes): Defer colorization choices by
replacing printing to a pretty_printer * param with appending
to a vec of strings.  Replace pretty_printer with usage of
pp_markup::comma_separated_quoted_strings and "%e".

gcc/testsuite/ChangeLog:
PR other/116613
* c-c++-common/analyzer/escaping-1.c: Update expected results to
remove type information from C++ results.  Previously we were
using %qD with default_tree_printer, which used
lang_hooks.decl_printable_name, whereas now we're using %qD with
a clone of the cxx_pretty_printer.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/kf-analyzer.cc  | 42 +++
 gcc/attribs.cc   | 33 +
 gcc/attribs.h|  2 +-
 gcc/cp/pt.cc | 18 +++--
 gcc/gimple-ssa-warn-access.cc| 21 +++---
 gcc/pretty-print-markup.h| 17 +
 gcc/pretty-print.cc  | 92 
 gcc/testsuite/c-c++-common/analyzer/escaping-1.c |  9 +--
 8 files changed, 179 insertions(+), 55 deletions(-)

diff --git a/gcc/analyzer/kf-analyzer.cc b/gcc/analyzer/kf-analyzer.cc
index 26c2e41da6ff..da49baa5bff1 100644
--- a/gcc/analyzer/kf-analyzer.cc
+++ b/gcc/analyzer/kf-analyzer.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/pending-diagnostic.h"
 #include "analyzer/call-details.h"
 #include "make-unique.h"
+#include "pretty-print-markup.h"
 
 #if ENABLE_ANALYZER
 
@@ -176,23 +177,40 @@ public:
probably most user-friendly.  */
 escaped_decls.qsort (cmp_decls_ptr_ptr);
 
-pretty_printer pp;
-pp_format_decoder (&pp) = default_tree_printer;
-pp_show_color (&pp) = pp_show_color (global_dc->m_printer);
-bool first = true;
-for (auto iter : escaped_decls)
+class escaped_list_element : public pp_element
+{
+public:
+  escaped_list_element (auto_vec &escaped_decls)
+  : m_escaped_decls (escaped_decls)
   {
-   if (first)
- first = false;
-   else
- pp_string (&pp, ", ");
-   pp_printf (&pp, "%qD", iter);
   }
+
+  void add_to_phase_2 (pp_markup::context &ctxt) final override
+  {
+   /* We can't call pp_printf directly on ctxt.m_pp from within
+  formatting.  As a workaround, 

[gcc r15-3972] diagnostics: fix typo in XHTML output [PR116792]

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3286b6724ec1d005436dffa5228516db88e754b9

commit r15-3972-g3286b6724ec1d005436dffa5228516db88e754b9
Author: David Malcolm 
Date:   Mon Sep 30 11:48:28 2024 -0400

diagnostics: fix typo in XHTML output [PR116792]

gcc/testsuite/ChangeLog:
PR other/116792
* gcc.dg/plugin/diagnostic_plugin_xhtml_format.c: Fix stray
reference to JSON.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c 
b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
index 192288aff1bc..0f13e8d6d01a 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
@@ -751,7 +751,7 @@ diagnostic_output_format_init_xhtml_file 
(diagnostic_context &context,
 namespace selftest {
 
 /* A subclass of xhtml_output_format for writing selftests.
-   The JSON output is cached internally, rather than written
+   The XML output is cached internally, rather than written
out to a file.  */
 
 class test_xhtml_diagnostic_context : public test_diagnostic_context


[gcc r15-3971] diagnostics: fix memory leak in SARIF selftests

2024-09-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:ab6c7a329d4958aa1f2975196358f7f56a463b3b

commit r15-3971-gab6c7a329d4958aa1f2975196358f7f56a463b3b
Author: David Malcolm 
Date:   Mon Sep 30 11:48:28 2024 -0400

diagnostics: fix memory leak in SARIF selftests

"make selftest-valgrind" was complaining about leaks of artifact objects
in SARIF's selftest::test_make_location_object:

-fself-test: 7638695 pass(es) in 89.999249 seconds
==3306525==
==3306525== HEAP SUMMARY:
==3306525== in use at exit: 1,215,639 bytes in 2,808 blocks
==3306525==   total heap usage: 2,860,898 allocs, 2,858,090 frees, 
1,336,446,579 bytes allocated
==3306525==
==3306525== 11,728 (1,536 direct, 10,192 indirect) bytes in 16 blocks are 
definitely lost in loss record 353 of 375
==3306525==at 0x514FE7D: operator new(unsigned long) 
(vg_replace_malloc.c:342)
==3306525==by 0x36E5FD2: sarif_builder::get_or_create_artifact(char 
const*, diagnostic_artifact_role, bool) (diagnostic-format-sarif.cc:2884)
==3306525==by 0x36E3D57: 
sarif_builder::maybe_make_physical_location_object(unsigned int, 
diagnostic_artifact_role, int, content_renderer const*) 
(diagnostic-format-sarif.cc:2097)
==3306525==by 0x36E34CE: 
sarif_builder::make_location_object(sarif_location_manager&, rich_location 
const&, logical_location const*, diagnostic_artifact_role) 
(diagnostic-format-sarif.cc:1922)
==3306525==by 0x36E72C6: 
selftest::test_make_location_object(selftest::line_table_case const&) 
(diagnostic-format-sarif.cc:3500)
==3306525==by 0x375609B: selftest::for_each_line_table_case(void 
(*)(selftest::line_table_case const&)) (input.cc:3898)
==3306525==by 0x36E9668: selftest::diagnostic_format_sarif_cc_tests() 
(diagnostic-format-sarif.cc:3910)
==3306525==by 0x3592A11: selftest::run_tests() 
(selftest-run-tests.cc:100)
==3306525==by 0x17DBEF3: toplev::run_self_tests() (toplev.cc:2268)
==3306525==by 0x17DC2BF: toplev::main(int, char**) (toplev.cc:2376)
==3306525==by 0x36A1919: main (main.cc:39)
==3306525==
==3306525== 12,400 (1,536 direct, 10,864 indirect) bytes in 16 blocks are 
definitely lost in loss record 355 of 375
==3306525==at 0x514FE7D: operator new(unsigned long) 
(vg_replace_malloc.c:342)
==3306525==by 0x36E5FD2: sarif_builder::get_or_create_artifact(char 
const*, diagnostic_artifact_role, bool) (diagnostic-format-sarif.cc:2884)
==3306525==by 0x36E2323: 
sarif_builder::sarif_builder(diagnostic_context&, line_maps const*, char 
const*, bool) (diagnostic-format-sarif.cc:1500)
==3306525==by 0x36E70AA: 
selftest::test_make_location_object(selftest::line_table_case const&) 
(diagnostic-format-sarif.cc:3469)
==3306525==by 0x375609B: selftest::for_each_line_table_case(void 
(*)(selftest::line_table_case const&)) (input.cc:3898)
==3306525==by 0x36E9668: selftest::diagnostic_format_sarif_cc_tests() 
(diagnostic-format-sarif.cc:3910)
==3306525==by 0x3592A11: selftest::run_tests() 
(selftest-run-tests.cc:100)
==3306525==by 0x17DBEF3: toplev::run_self_tests() (toplev.cc:2268)
==3306525==by 0x17DC2BF: toplev::main(int, char**) (toplev.cc:2376)
==3306525==by 0x36A1919: main (main.cc:39)
==3306525==
==3306525== LEAK SUMMARY:
==3306525==definitely lost: 3,072 bytes in 32 blocks
==3306525==indirectly lost: 21,056 bytes in 368 blocks
==3306525==  possibly lost: 0 bytes in 0 blocks
==3306525==still reachable: 1,191,511 bytes in 2,408 blocks
==3306525== suppressed: 0 bytes in 0 blocks
==3306525== Reachable blocks (those to which a pointer was found) are not 
shown.
==3306525== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==3306525==
==3306525== For lists of detected and suppressed errors, rerun with: -s
==3306525== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Fixed thusly.

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_builder::~sarif_builder): New,
deleting any remaining artifact objects.
(sarif_builder::make_run_object): Empty the artifact map.
* ordered-hash-map.h (ordered_hash_map::empty): New.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 14 ++
 gcc/ordered-hash-map.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 6cd18cef6c89..7b11dfd89a31 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -649,6 +649,7 @@ public:
 const line_maps *line_maps,
 const char *main_input_filename_,
 bool formatted);
+  ~sarif_builder ();
 
   void on_report_diagnostic (const diagnostic_info &diagnostic,
 diagnostic_t orig_diag_kind);
@@ -1500,6 +1501,18 @@ sarif_builder::

[gcc r15-3749] diagnostics: convert text hooks to use diagnostic_text_output_format [PR116613]

2024-09-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:7da682c896f949259eaf820be17b5781df2cbead

commit r15-3749-g7da682c896f949259eaf820be17b5781df2cbead
Author: David Malcolm 
Date:   Fri Sep 20 18:51:55 2024 -0400

diagnostics: convert text hooks to use diagnostic_text_output_format 
[PR116613]

The diagnostic_starter and diagnostic_finalizer callbacks and most of
their support subroutines are only used by the "text" output format.

Emphasize this and reduce the binding with diagnostic_context
by renaming the callbacks to add "_text" in their names, and converting
the first param from diagnostic_context * to
diagnostic_text_output_output &.  Update the various subroutines used
by diagnostic starter/finalizer callbacks to also take a
diagnostic_text_output_output & rather than a diagnostic_context *.
Move m_includes and m_last_seen from the context to the text output.

Use the text_output's get_printer () rather than the context's
m_printer, which should ease the transition to multiple output sinks.

No functional change intended.

gcc/c-family/ChangeLog:
PR other/116613
* c-opts.cc: Include "diagnostic-format-text.h".
(c_diagnostic_finalizer): Rename to...
(c_diagnostic_text_finalizer): ...this.  Convert first param
from diagnostic_context * to diagnostic_text_output_format & and
update accordingly.
(c_common_diagnostics_set_defaults): Update for renamings.

gcc/ChangeLog:
PR other/116613
* coretypes.h (class diagnostic_text_output_format): Add forward
decl.
* diagnostic-format-json.cc
(json_output_format::after_diagnostic): New.
* diagnostic-format-sarif.cc
(sarif_output_format::after_diagnostic): New.
* diagnostic-format-text.cc: Use pragmas to ignore -Wformat-diag.
(diagnostic_text_output_format::~diagnostic_text_output_format):
Use get_printer.  Clean up m_includes_seen here, rather than
in ~diagnostic_context.
(diagnostic_text_output_format::on_report_diagnostic):  Use
get_printer.  Update for callback renamings and pass *this
to them, rather than &m_context.
(diagnostic_text_output_format::after_diagnostic): New.
(diagnostic_text_output_format::includes_seen_p): Move here
from diagnostic_context/diagnostic.cc.
(diagnostic_text_output_format::get_location_text): New.
(maybe_line_and_column): Move here from diagnostic.cc and make
non-static.
(diagnostic_text_output_format::report_current_module): Move
here from diagnostic_context/diagnostic.cc.
(default_diagnostic_text_starter): Move here from diagnostic.cc,
renaming from default_diagnostic_starter.
(default_diagnostic_text_finalizer): Likewise, renaming from
default_diagnostic_finalizer.
* diagnostic-format-text.h
(diagnostic_text_output_format::diagnostic_text_output_format):
Initialize m_last_module and m_includes_seen.
(diagnostic_text_output_format::after_diagnostic): New decl.
(diagnostic_text_output_format::build_prefix): New decl.
(diagnostic_text_output_format::report_current_module): New decl.
(diagnostic_text_output_format::append_note): New decl.
(diagnostic_text_output_format::file_name_as_prefix): New decl.
(diagnostic_text_output_format::print_path): New decl.
(diagnostic_text_output_format::show_column_p): New decl.
(diagnostic_text_output_format::get_location_text): New decl.
(diagnostic_text_output_format::includes_seen_p): New decl.
(diagnostic_text_output_format::show_any_path): New decl.
(diagnostic_text_output_format::m_last_module): New field.
(diagnostic_text_output_format::m_includes_seen): New field.
* diagnostic-format.h
(diagnostic_output_format::after_diagnostic): New vfunc.
(diagnostic_output_format::get_context): New.
(diagnostic_output_format::get_diagram_theme): New.
* diagnostic-macro-unwinding.cc: Include
"diagnostic-format-text.h".
(maybe_unwind_expanded_macro_loc): Convert first param from
diagnostic_context * to diagnostic_text_output_format & and update
accordingly.
(virt_loc_aware_diagnostic_finalizer): Likewise.
* diagnostic-macro-unwinding.h
(virt_loc_aware_diagnostic_finalizer): Likewise.
(maybe_unwind_expanded_macro_loc): Likewise.
* diagnostic-path.cc: Include "diagnostic-format-text.h".
(path_label::path_label): Drop "ctxt" param and add "colorize"
and "allow_emojis" params.  Update initializations.
 

[gcc r15-3751] analyzer: simplify dumps using tree_dump_pretty_printer [PR116613]

2024-09-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:39f7703fffee0c1a8aa999b29ae52b2a31903715

commit r15-3751-g39f7703fffee0c1a8aa999b29ae52b2a31903715
Author: David Malcolm 
Date:   Fri Sep 20 18:51:55 2024 -0400

analyzer: simplify dumps using tree_dump_pretty_printer [PR116613]

There are numerous "dump" member functions in the analyzer with
copied-and-pasted logic.  Simplify them by moving the shared code
to a new class tree_dump_pretty_printer.

As well as reducing code duplication, this eliminates numerous
uses of pp_show_color (global_dc->m_printer), which should
ultimately help with supporting multiple diagnostic sinks.

No functional change intended.

gcc/analyzer/ChangeLog:
PR other/116613
* access-diagram.cc (access_range::dump): Simplify using
tree_dump_pretty_printer.
* call-details.cc (call_details::dump): Likewise.
* call-summary.cc (call_summary::dump): Likewise.
(call_summary_replay::dump): Likewise.
* checker-event.cc (checker_event::debug): Likewise.
* constraint-manager.cc (range::dump): Likewise.
(bounded_range::dump): Likewise.
(bounded_ranges::dump): Likewise.
(constraint_manager::dump): Likewise.
* engine.cc (exploded_node::dump): Likewise.
(exploded_path::dump): Likewise.
* program-point.cc (program_point::dump): Likewise.
* program-state.cc (extrinsic_state::dump_to_file): Likewise.
(sm_state_map::dump): Likewise.
(program_state::dump_to_file): Likewise.
* ranges.cc (symbolic_byte_offset::dump): Likewise.
(symbolic_byte_range::dump): Likewise.
* record-layout.cc (record_layout::dump): Likewise.
* region-model-reachability.cc (reachable_regions::dump):
Likewise.
* region-model.cc (region_to_value_map::dump): Likewise.
(region_model::dump): Likewise.
(model_merger::dump): Likewise.
* region.cc (region_offset::dump): Likewise.
(region::dump): Likewise.
* sm-malloc.cc (deallocator_set::dump): Likewise.
* store.cc (uncertainty_t::dump): Likewise.
(binding_key::dump): Likewise.
(bit_range::dump): Likewise.
(byte_range::dump): Likewise.
(binding_map::dump): Likewise.
(binding_cluster::dump): Likewise.
(store::dump): Likewise.
* supergraph.cc (superedge::dump): Likewise.
* svalue.cc (svalue::dump): Likewise.

gcc/ChangeLog:
PR other/116613
* text-art/dump.h (dump_to_file): Simplify using
tree_dump_pretty_printer.
* tree-diagnostic.h (class tree_dump_pretty_printer): New.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/access-diagram.cc|  6 +
 gcc/analyzer/call-details.cc  |  6 +
 gcc/analyzer/call-summary.cc  | 12 ++
 gcc/analyzer/checker-event.cc |  6 +
 gcc/analyzer/constraint-manager.cc| 24 ---
 gcc/analyzer/engine.cc| 12 ++
 gcc/analyzer/program-point.cc |  5 +---
 gcc/analyzer/program-state.cc | 19 +++-
 gcc/analyzer/ranges.cc| 12 ++
 gcc/analyzer/record-layout.cc |  5 +---
 gcc/analyzer/region-model-reachability.cc |  6 +
 gcc/analyzer/region-model.cc  | 18 +++
 gcc/analyzer/region.cc| 12 ++
 gcc/analyzer/sm-malloc.cc |  5 +---
 gcc/analyzer/store.cc | 38 ++-
 gcc/analyzer/supergraph.cc|  6 +
 gcc/analyzer/svalue.cc|  6 +
 gcc/text-art/dump.h   |  8 +--
 gcc/tree-diagnostic.h | 20 
 19 files changed, 55 insertions(+), 171 deletions(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index ddeb45a94b24..4822ae392845 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -544,13 +544,9 @@ access_range::dump_to_pp (pretty_printer *pp, bool simple) 
const
 DEBUG_FUNCTION void
 access_range::dump (bool simple) const
 {
-  pretty_printer pp;
-  pp_format_decoder (&pp) = default_tree_printer;
-  pp_show_color (&pp) = pp_show_color (global_dc->m_printer);
-  pp.set_output_stream (stderr);
+  tree_dump_pretty_printer pp (stderr);
   dump_to_pp (&pp, simple);
   pp_newline (&pp);
-  pp_flush (&pp);
 }
 
 void
diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc
index e543eda347a5..a9c613bc1822 100644
--- a/gcc/analyzer/call-details.cc
+++ b/gcc/analyzer/call-details.cc
@@ -363,12 +363,8 @@ call_details::dump_to_pp (pretty_printer *pp, bool simple) 
const
 DEBUG_FUNCTION void
 

[gcc r15-3752] diagnostics: add HTML output format as a plugin [PR116792]

2024-09-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:48261bd26df624f0b906600fb0ef6864c7a7f895

commit r15-3752-g48261bd26df624f0b906600fb0ef6864c7a7f895
Author: David Malcolm 
Date:   Fri Sep 20 18:51:56 2024 -0400

diagnostics: add HTML output format as a plugin [PR116792]

This patch adds an experimental diagnostics output format that
writes HTML.  It isn't ready yet for end-users, but seems worth
keeping in the tree as I refactor the diagnostics subsystem, to
ensure that this code still builds, and to verify that it's possible to
implement new diagnostic output formats via GCC plugins. Hence
this patch merely adds it to the testsuite as an example of a GCC
plugin, rather than exposing it as a feature for end-users.

gcc/testsuite/ChangeLog:
PR other/116792
* gcc.dg/plugin/diagnostic-test-xhtml-1.c: New test.
* gcc.dg/plugin/diagnostic_plugin_xhtml_format.c: New test plugin.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above.

Signed-off-by: David Malcolm 

Diff:
---
 .../gcc.dg/plugin/diagnostic-test-xhtml-1.c|  19 +
 .../gcc.dg/plugin/diagnostic_plugin_xhtml_format.c | 866 +
 gcc/testsuite/gcc.dg/plugin/plugin.exp |   2 +
 3 files changed, 887 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-xhtml-1.c 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-xhtml-1.c
new file mode 100644
index ..da069ff4789d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-xhtml-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+int missing_semicolon (void)
+{
+  return 42
+}
+
+/* Verify some properties of the generated HTML.  */
+
+/* { dg-begin-multiline-output "" }
+
+http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+http://www.w3.org/1999/xhtml";>
+  
+   { dg-end-multiline-output "" } */
+
+/* { dg-excess-errors "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c 
b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
new file mode 100644
index ..192288aff1bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_xhtml_format.c
@@ -0,0 +1,866 @@
+/* Verify that we can write a non-trivial diagnostic output format
+   as a plugin (XHTML).
+   Copyright (C) 2018-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+
+#include "config.h"
+#define INCLUDE_LIST
+#define INCLUDE_MAP
+#define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic.h"
+#include "diagnostic-metadata.h"
+#include "diagnostic-path.h"
+#include "cpplib.h"
+#include "logical-location.h"
+#include "diagnostic-client-data-hooks.h"
+#include "diagnostic-diagram.h"
+#include "text-art/canvas.h"
+#include "diagnostic-format.h"
+#include "ordered-hash-map.h"
+#include "sbitmap.h"
+#include "make-unique.h"
+#include "selftest.h"
+#include "selftest-diagnostic.h"
+#include "selftest-diagnostic-show-locus.h"
+#include "text-range-label.h"
+#include "pretty-print-format-impl.h"
+#include "pretty-print-urlifier.h"
+#include "intl.h"
+#include "gcc-plugin.h"
+#include "plugin-version.h"
+
+namespace xml {
+
+/* Disable warnings about quoting issues in the pp_xxx calls below
+   that (intentionally) don't follow GCC diagnostic conventions.  */
+#if __GNUC__ >= 10
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
+static void write_escaped_text (const char *text);
+
+struct node
+{
+  virtual ~node () {}
+  virtual void write_as_xml (pretty_printer *pp,
+int depth, bool indent) const = 0;
+  void dump (FILE *out) const;
+  void DEBUG_FUNCTION dump () const { dump (stderr); }
+};
+
+struct text : public node
+{
+  text (label_text str)
+  : m_str (std::move (str))
+  {}
+
+  void write_as_xml (pretty_printer *pp,
+int depth, bool indent) const final override;
+
+  label_text m_str;
+};
+
+struct node_with_children : public node
+{
+  void add_child (std::unique_ptr node);
+  void add_text (label_text str);
+
+  std::vector> m_children;
+};
+
+struct document : public node_with_children
+{
+  void write_as_xml (pretty_printer *pp,
+int depth, bool indent) const final override;
+};
+
+struct element : public node_with_children
+{
+  elemen

[gcc r15-3748] analyzer: remove redundant 'pp' [PR116613]

2024-09-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:37604edf37b3799e0203ede4dfa60d547322fdfc

commit r15-3748-g37604edf37b3799e0203ede4dfa60d547322fdfc
Author: David Malcolm 
Date:   Fri Sep 20 18:51:55 2024 -0400

analyzer: remove redundant 'pp' [PR116613]

diagnostic_manager::emit_saved_diagnostic makes a useless clone
of global_dc->m_printer; remove it.

No functional change intended.

gcc/analyzer/ChangeLog:
PR other/116613
* diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic):
Remove remove redundant 'pp'.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/diagnostic-manager.cc | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/gcc/analyzer/diagnostic-manager.cc 
b/gcc/analyzer/diagnostic-manager.cc
index 4a5a95136156..2363ae5df19c 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -1561,8 +1561,6 @@ diagnostic_manager::emit_saved_diagnostic (const 
exploded_graph &eg,
sd.get_index (), sd.m_d->get_kind (), sd.m_snode->m_index);
   log ("num dupes: %i", sd.get_num_dupes ());
 
-  pretty_printer *pp = global_dc->m_printer->clone ();
-
   const exploded_path *epath = sd.get_best_epath ();
   gcc_assert (epath);
 
@@ -1645,7 +1643,6 @@ diagnostic_manager::emit_saved_diagnostic (const 
exploded_graph &eg,
  free (filename);
}
 }
-  delete pp;
 }
 
 /* Emit a "path" of events to EMISSION_PATH describing the exploded path


[gcc r15-3750] diagnostics: isolate SARIF output's pretty_printer [PR116613]

2024-09-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:725231e16768bd9f16169b3b7e4cb5a98b251d1c

commit r15-3750-g725231e16768bd9f16169b3b7e4cb5a98b251d1c
Author: David Malcolm 
Date:   Fri Sep 20 18:51:55 2024 -0400

diagnostics: isolate SARIF output's pretty_printer [PR116613]

Add an m_printer to sarif_builder and use throughout, rather than
using the context's printer.  For now this is the same printer, but
eventually this should help with transitioning to multiple output sinks.

No functional change intended.

gcc/ChangeLog:
PR other/116613
* diagnostic-format-sarif.cc (sarif_builder::m_printer): New
field.
(sarif_invocation::add_notification_for_ice): Drop context param.
(sarif_invocation::prepare_to_flush): Convert param from context
to builder.
(sarif_result::on_nested_diagnostic): Drop context param.  Use
builder's printer.
(sarif_result::on_diagram): Drop context param.
(sarif_ice_notification::sarif_ice_notification): Drop context
param.  Use builder's printer.
(sarif_builder::sarif_builder): Initialize m_printer.
(sarif_builder::on_report_diagnostic): Drop context param.  Use
builder's printer.
(sarif_builder::emit_diagram): Drop context param.
(sarif_builder::flush_to_object): Use this rather than context
for call to prepare_to_flush.
(sarif_builder::make_result_object): Drop context param.  Use
builder's printer.
(sarif_builder::make_reporting_descriptor_object_for_warning):
Drop context param.
(sarif_builder::make_message_object_for_diagram): Likewise.
Use builder's printer.
(sarif_output_format::on_report_diagnostic): Drop context param
from call to sarif_builder::on_report_diagnostic.
(sarif_output_format::on_diagram): Drop context param from call to
sarif_builder::emit_diagram.
* diagnostic.h (diagnostic_conetxt::get_client_data_hooks): Make 
const.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 116 ++---
 gcc/diagnostic.h   |   2 +-
 2 files changed, 51 insertions(+), 67 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index eda67a6f6583..6cd18cef6c89 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -166,10 +166,9 @@ public:
   sarif_invocation (sarif_builder &builder,
const char * const *original_argv);
 
-  void add_notification_for_ice (diagnostic_context &context,
-const diagnostic_info &diagnostic,
+  void add_notification_for_ice (const diagnostic_info &diagnostic,
 sarif_builder &builder);
-  void prepare_to_flush (diagnostic_context &context);
+  void prepare_to_flush (sarif_builder &builder);
 
 private:
   std::unique_ptr m_notifications_arr;
@@ -395,12 +394,10 @@ public:
   unsigned get_index_within_parent () const { return m_idx_within_parent; }
 
   void
-  on_nested_diagnostic (diagnostic_context &context,
-   const diagnostic_info &diagnostic,
+  on_nested_diagnostic (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
sarif_builder &builder);
-  void on_diagram (diagnostic_context &context,
-  const diagnostic_diagram &diagram,
+  void on_diagram (const diagnostic_diagram &diagram,
   sarif_builder &builder);
 
   void
@@ -583,8 +580,7 @@ class sarif_replacement : public sarif_object {};
 class sarif_ice_notification : public sarif_location_manager
 {
 public:
-  sarif_ice_notification (diagnostic_context &context,
- const diagnostic_info &diagnostic,
+  sarif_ice_notification (const diagnostic_info &diagnostic,
  sarif_builder &builder);
 
   void
@@ -654,11 +650,9 @@ public:
 const char *main_input_filename_,
 bool formatted);
 
-  void on_report_diagnostic (diagnostic_context &context,
-const diagnostic_info &diagnostic,
+  void on_report_diagnostic (const diagnostic_info &diagnostic,
 diagnostic_t orig_diag_kind);
-  void emit_diagram (diagnostic_context &context,
-const diagnostic_diagram &diagram);
+  void emit_diagram (const diagnostic_diagram &diagram);
   void end_group ();
 
   std::unique_ptr take_current_result ()
@@ -685,8 +679,7 @@ public:
   std::unique_ptr
   make_message_object (const char *msg) const;
   std::unique_ptr
-  make_message_object_for_diagram (diagnostic_context &context,
-  const diagnostic_diagram &diagram);
+  make_message_object_for_diagram (const diagnostic_diagram &dia

[gcc r15-3556] diagnostics: introduce struct diagnostic_option_id

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:89991f31c5ded21179b12a9f4063c2b8fabc2e3b

commit r15-3556-g89991f31c5ded21179b12a9f4063c2b8fabc2e3b
Author: David Malcolm 
Date:   Mon Sep 9 19:38:13 2024 -0400

diagnostics: introduce struct diagnostic_option_id

Use a new struct diagnostic_option_id rather than just "int" when
referring to command-line options controlling warnings in the
diagnostic subsystem.

No functional change intended, but better documents the meaning of
the code.

gcc/c-family/ChangeLog:
* c-common.cc (c_option_controlling_cpp_diagnostic): Return
diagnostic_option_id rather than int.
(c_cpp_diagnostic): Update for renaming of
diagnostic_override_option_index to diagnostic_set_option_id.

gcc/c/ChangeLog:
* c-errors.cc (pedwarn_c23): Use "diagnostic_option_id option_id"
rather than "int opt".  Update for renaming of diagnostic_info
field.
(pedwarn_c11): Likewise.
(pedwarn_c99): Likewise.
(pedwarn_c90): Likewise.
* c-tree.h (pedwarn_c90): Likewise for decl.
(pedwarn_c99): Likewise.
(pedwarn_c11): Likewise.
(pedwarn_c23): Likewise.

gcc/cp/ChangeLog:
* constexpr.cc (constexpr_error): Update for renaming of
diagnostic_info field.
* cp-tree.h (pedwarn_cxx98): Use "diagnostic_option_id" rather
than "int".
* error.cc (cp_adjust_diagnostic_info): Update for renaming of
diagnostic_info field.
(pedwarn_cxx98): Use "diagnostic_option_id option_id" rather than
"int opt".  Update for renaming of diagnostic_info field.
(diagnostic_set_info): Likewise.

gcc/d/ChangeLog:
* d-diagnostic.cc (d_diagnostic_report_diagnostic): Update for
renaming of diagnostic_info field.

gcc/ChangeLog:
* diagnostic-core.h (struct diagnostic_option_id): New.
(warning): Use it rather than "int" for param.
(warning_n): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(pedwarn): Likewise.
(permerror_opt): Likewise.
(emit_diagnostic): Likewise.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
* diagnostic-format-json.cc
(json_output_format::on_report_diagnostic): Update for renaming of
diagnostic_info field.
* diagnostic-format-sarif.cc (sarif_builder::make_result_object):
Likewise.
(make_reporting_descriptor_object_for_warning): Likewise.
* diagnostic-format-text.cc (print_option_information): Likewise.
* diagnostic-global-context.cc (emit_diagnostic): Use
"diagnostic_option_id option_id" rather than "int opt".
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror_opt): Likewise.
* diagnostic.cc (diagnostic_set_info_translated): Update for
renaming of diagnostic_info field.
(diagnostic_option_classifier::classify_diagnostic): Use
"diagnostic_option_id option_id" rather than "int opt".
(update_effective_level_from_pragmas): Update for renaming of
diagnostic_info field.
(diagnostic_context::diagnostic_enabled): Likewise.
(diagnostic_context::warning_enabled_at): Use
"diagnostic_option_id option_id" rather than "int opt".
(diagnostic_context::diagnostic_impl): Likewise.
(diagnostic_context::diagnostic_n_impl): Likewise.
* diagnostic.h (diagnostic_info::diagnostic_info): Update for...
(diagnostic_info::option_index): Rename...
(diagnostic_info::option_id): ...to this.
(class diagnostic_option_manager): Use
"diagnostic_option_id option_id" rather than "int opt" for vfuncs.
(diagnostic_option_classifier): Likewise for member funcs.
(diagnostic_classification_change_t::option): Add comment.
(diagnostic_context::warning_enabled_at): Use
"diagnostic_option_id option_id" rather than "int option_index".
(diagnostic_context::option_unspecified_p): Likewise.
(diagnostic_context::classify_diagnostic): Likewise.
(diagnostic_context::option_enabled_p): Likewise.
(diagnostic_context::make_option_name): Likewise.
(diagnostic_context::make_option_url): Likewise.
(diagnostic_context::diagnostic_impl): Likewise.
(diagnostic_context::diagnostic_n_impl): Likewise.
(diagnostic

[gcc r15-3554] diagnostics: rename dc.printer to m_printer [PR116613]

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:19363bf5564ffbe992265a1e69a0d99a0d29f016

commit r15-3554-g19363bf5564ffbe992265a1e69a0d99a0d29f016
Author: David Malcolm 
Date:   Mon Sep 9 19:38:12 2024 -0400

diagnostics: rename dc.printer to m_printer [PR116613]

Rename diagnostic_context's "printer" field to "m_printer",
for consistency with other fields, and to highlight places
where we currently use this, to help assess feasibility
of supporting multiple output sinks (PR other/116613).

No functional change intended.

gcc/ChangeLog:
PR other/116613
* attribs.cc (decls_mismatched_attributes): Rename
diagnostic_context's "printer" field to "m_printer".
(attr_access::array_as_string): Likewise.
* diagnostic-format-json.cc
(json_output_format::on_report_diagnostic): Likewise.
(diagnostic_output_format_init_json): Likewise.
* diagnostic-format-sarif.cc
(sarif_result::on_nested_diagnostic): Likewise.
(sarif_ice_notification): Likewise.
(sarif_builder::on_report_diagnostic): Likewise.
(sarif_builder::make_result_object): Likewise.
(sarif_builder::make_location_object): Likewise.
(sarif_builder::make_message_object_for_diagram): Likewise.
(diagnostic_output_format_init_sarif): Likewise.
* diagnostic-format-text.cc
(diagnostic_text_output_format::~diagnostic_text_output_format):
Likewise.
(diagnostic_text_output_format::on_report_diagnostic): Likewise.
(diagnostic_text_output_format::on_diagram): Likewise.
(diagnostic_text_output_format::print_any_cwe): Likewise.
(diagnostic_text_output_format::print_any_rules): Likewise.
(diagnostic_text_output_format::print_option_information):
Likewise.
* diagnostic-format.h (diagnostic_output_format::get_printer):
New.
* diagnostic-global-context.cc (verbatim): Rename
diagnostic_context's "printer" field to "m_printer".
* diagnostic-path.cc (path_label::get_text): Likewise.
(print_path_summary_as_text): Likewise.
(diagnostic_context::print_path): Likewise.
(selftest::test_empty_path): Likewise.
(selftest::test_intraprocedural_path): Likewise.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.
* diagnostic-show-locus.cc (layout::layout): Likewise.
(selftest::test_layout_x_offset_display_utf8): Likewise.
(selftest::test_layout_x_offset_display_tab): Likewise.
(selftest::test_diagnostic_show_locus_unknown_location): Likewise.
(selftest::test_one_liner_simple_caret): Likewise.
(selftest::test_one_liner_no_column): Likewise.
(selftest::test_one_liner_caret_and_range): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges): Likewise.
(selftest::test_one_liner_fixit_insert_before): Likewise.
(selftest::test_one_liner_fixit_insert_after): Likewise.
(selftest::test_one_liner_fixit_remove): Likewise.
(selftest::test_one_liner_fixit_replace): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations):
Likewise.
(selftest::test_one_liner_many_fixits_1): Likewise.
(selftest::test_one_liner_many_fixits_2): Likewise.
(selftest::test_one_liner_labels): Likewise.
(selftest::test_one_liner_simple_caret_utf8): Likewise.
(selftest::test_one_liner_caret_and_range_utf8): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges_utf8):
Likewise.
(selftest::test_one_liner_fixit_insert_before_utf8): Likewise.
(selftest::test_one_liner_fixit_insert_after_utf8): Likewise.
(selftest::test_one_liner_fixit_remove_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations_

[gcc r15-3555] diagnostics: replace option_hooks with a diagnostic_option_manager class

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a97448e92eb76a69b4183183d14a791f9b76cc8d

commit r15-3555-ga97448e92eb76a69b4183183d14a791f9b76cc8d
Author: David Malcolm 
Date:   Mon Sep 9 19:38:12 2024 -0400

diagnostics: replace option_hooks with a diagnostic_option_manager class

Introduce a diagnostic_option_manager class to help isolate the
diagnostics subsystem from GCC's option handling.

No functional change intended.

gcc/ChangeLog:
* diagnostic.cc (diagnostic_context::initialize): Replace
m_options_callbacks with m_option_mgr.
(diagnostic_context::set_option_hooks): Replace with...
(diagnostic_context::set_option_manager): ...this.
* diagnostic.h (diagnostic_option_enabled_cb): Delete.
(diagnostic_make_option_name_cb): Delete.
(diagnostic_make_option_url_cb): Delete.
(class diagnostic_option_manager): New.
(diagnostic_manager::option_enabled_p): Convert from using
m_option_callbacks to m_option_mgr.
(diagnostic_manager::make_option_name): Likewise.
(diagnostic_manager::make_option_url): Likewise.
(diagnostic_manager::set_option_hooks): Replace with...
(diagnostic_manager::set_option_manager): ...this.
(diagnostic_manager::get_lang_mask): Update for field changes.
(diagnostic_manager::m_option_callbacks): Replace with...
(diagnostic_manager::m_option_mgr): ...this and...
(diagnostic_manager::m_lang_mask): ...this.
* lto-wrapper.cc (class lto_diagnostic_option_manager): New.
(main): Port from option hooks to diagnostic_option_manager.
* opts-common.cc: Include "opts-diagnostic.h".
(compiler_diagnostic_option_manager::option_enabled_p): New.
* opts-diagnostic.h (option_name): Drop decl.
(get_option_url): Drop decl.
(class gcc_diagnostic_option_manager): New.
(class compiler_diagnostic_option_manager): New.
* opts.cc (option_name): Convert to...
(compiler_diagnostic_option_manager::make_option_name): ...this.
(get_option_url): Convert to...
(gcc_diagnostic_option_manager::make_option_url): ...this.
* toplev.cc (general_init): Port from option hooks to
diagnostic_option_manager.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic.cc | 23 -
 gcc/diagnostic.h  | 94 ++-
 gcc/lto-wrapper.cc| 24 ++---
 gcc/opts-common.cc|  7 
 gcc/opts-diagnostic.h | 44 
 gcc/opts.cc   | 18 +-
 gcc/toplev.cc | 10 +++---
 7 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 32eab7d5407a..0e0ab7aeb838 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -226,10 +226,7 @@ diagnostic_context::initialize (int n_opts)
   m_text_callbacks.m_begin_diagnostic = default_diagnostic_starter;
   m_text_callbacks.m_start_span = default_diagnostic_start_span_fn;
   m_text_callbacks.m_end_diagnostic = default_diagnostic_finalizer;
-  m_option_callbacks.m_option_enabled_cb = nullptr;
-  m_option_callbacks.m_option_state = nullptr;
-  m_option_callbacks.m_make_option_name_cb = nullptr;
-  m_option_callbacks.m_make_option_url_cb = nullptr;
+  m_option_mgr = nullptr;
   m_urlifier = nullptr;
   m_last_location = UNKNOWN_LOCATION;
   m_last_module = nullptr;
@@ -446,18 +443,12 @@ diagnostic_context::set_original_argv (unique_argv 
original_argv)
 }
 
 void
-diagnostic_context::
-set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb,
- void *option_state,
- diagnostic_make_option_name_cb make_option_name_cb,
- diagnostic_make_option_url_cb make_option_url_cb,
- unsigned lang_mask)
-{
-  m_option_callbacks.m_option_enabled_cb = option_enabled_cb;
-  m_option_callbacks.m_option_state = option_state;
-  m_option_callbacks.m_make_option_name_cb = make_option_name_cb;
-  m_option_callbacks.m_make_option_url_cb = make_option_url_cb;
-  m_option_callbacks.m_lang_mask = lang_mask;
+diagnostic_context::set_option_manager (diagnostic_option_manager *mgr,
+   unsigned lang_mask)
+{
+  delete m_option_mgr;
+  m_option_mgr = mgr;
+  m_lang_mask = lang_mask;
 }
 
 void
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 4d6147b87458..7244f425936c 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -181,14 +181,34 @@ typedef void (*diagnostic_finalizer_fn) 
(diagnostic_context *,
 const diagnostic_info *,
 diagnostic_t);
 
-typedef int (*diagnostic_option_enabled_cb) (int, unsigned, void *);
-typedef char *(*diagnostic_make_option_name_cb) (const diagnostic_context *,
- 

[gcc r15-3553] SARIF output: fix schema URL [§3.13.3, PR116603]

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:38dc2c64710aa0e6a03c0c1201477e3e75b1a0b0

commit r15-3553-g38dc2c64710aa0e6a03c0c1201477e3e75b1a0b0
Author: David Malcolm 
Date:   Mon Sep 9 19:38:11 2024 -0400

SARIF output: fix schema URL [§3.13.3, PR116603]

We were using
  
https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json
as the URL for the SARIF 2.1 schema, but this is now a 404.

Update it to the URL listed in the spec (§3.13.3 "$schema property"),
which is:
  
https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json
and update the copy in
  gcc/testsuite/lib/sarif-schema-2.1.0.json
used by the "verify-sarif-file" DejaGnu directive to the version found at
that latter URL; the sha256 sum changes
from: 2b19d2358baef0251d7d24e208d05ffabf1b2a3ab5e1b3a816066fc57fd4a7e8
  to: c3b4bb2d6093897483348925aaa73af03b3e3f4bd4ca38cef26dcb4212a2682e

Doing so added a validation error on
  c-c++-common/diagnostic-format-sarif-file-pr111700.c
for which we emit this textual output:
  this-file-does-not-exist.c: warning: #warning message [-Wcpp]
with no line number, and these invalid SARIF regions within the
physical location of the warning:
  "region": {"startColumn": 2,
 "endColumn": 9},
  "contextRegion": {}

This is due to this directive:
  # 0 "this-file-does-not-exist.c"
with line number 0.

The patch fixes this by not creating regions that have startLine <= 0.

gcc/ChangeLog:
PR other/116603
* diagnostic-format-sarif.cc (SARIF_SCHEMA): Update URL.
(sarif_builder::maybe_make_region_object): Don't create regions
with startLine <= 0.
(sarif_builder::maybe_make_region_object_for_context): Likewise.

gcc/testsuite/ChangeLog:
PR other/116603
* gcc.dg/plugin/diagnostic-test-metadata-sarif.py (test_basics):
Update expected schema URL.
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py:
Likewise.
* gcc.dg/sarif-output/test-include-chain-1.py: Likewise.
* gcc.dg/sarif-output/test-include-chain-2.py: Likewise.
* gcc.dg/sarif-output/test-missing-semicolon.py: Likewise.
* gcc.dg/sarif-output/test-no-diagnostics.py: Likewise.
* gcc.dg/sarif-output/test-werror.py: Likewise.
* lib/sarif-schema-2.1.0.json: Update with copy downloaded from

https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 25 ++--
 .../plugin/diagnostic-test-metadata-sarif.py   |  2 +-
 .../diagnostic-test-paths-multithreaded-sarif.py   |  2 +-
 .../gcc.dg/sarif-output/test-include-chain-1.py|  2 +-
 .../gcc.dg/sarif-output/test-include-chain-2.py|  2 +-
 .../gcc.dg/sarif-output/test-missing-semicolon.py  |  2 +-
 .../gcc.dg/sarif-output/test-no-diagnostics.py |  2 +-
 gcc/testsuite/gcc.dg/sarif-output/test-werror.py   |  2 +-
 gcc/testsuite/lib/sarif-schema-2.1.0.json  | 73 ++
 9 files changed, 72 insertions(+), 40 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 9d9e7ae60734..e95f18f31bda 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -2221,7 +2221,10 @@ sarif_builder::get_sarif_column (expanded_location 
exploc) const
or return nullptr.
 
If COLUMN_OVERRIDE is non-zero, then use it as the column number
-   if LOC has no column information.  */
+   if LOC has no column information.
+
+   We only support text properties of regions ("text regions"),
+   not binary properties ("binary regions"); see 3.30.1.  */
 
 std::unique_ptr
 sarif_builder::maybe_make_region_object (location_t loc,
@@ -2244,11 +2247,16 @@ sarif_builder::maybe_make_region_object (location_t loc,
   if (exploc_finish.file !=exploc_caret.file)
 return nullptr;
 
+  /* We can have line == 0 in the presence of "#" lines.
+ SARIF requires lines > 0, so if we hit this case we don't have a
+ way of validly representing the region as SARIF; bail out.  */
+  if (exploc_start.line <= 0)
+return nullptr;
+
   auto region_obj = ::make_unique ();
 
   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
-  if (exploc_start.line > 0)
-region_obj->set_integer ("startLine", exploc_start.line);
+  region_obj->set_integer ("startLine", exploc_start.line);
 
   /* "startColumn" property (SARIF v2.1.0 section 3.30.6).
 
@@ -2316,11 +2324,16 @@ maybe_make_region_object_for_context (location_t loc,
   if (exploc_finish.file !=exploc_caret.file)
 return nullptr;
 
+  /* We can have line == 0 in the presence of "#" lines.
+ SARIF requires lines > 0, so if we hit this case we don't have a
+ wa

[gcc r15-3551] analyzer: fix "unused variable 'summary_cast_reg'" warning

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:6e35b0e8572a71d0e6f407cc356592a0b97fc298

commit r15-3551-g6e35b0e8572a71d0e6f407cc356592a0b97fc298
Author: David Malcolm 
Date:   Mon Sep 9 15:30:42 2024 -0400

analyzer: fix "unused variable 'summary_cast_reg'" warning

I missed this in r15-1108-g70f26314b62e2d.

gcc/analyzer/ChangeLog:
* call-summary.cc
(call_summary_replay::convert_region_from_summary_1): Drop unused
local "summary_cast_reg"

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/call-summary.cc | 2 --
 1 file changed, 2 deletions(-)

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index ec36fdfd9f1a..663a89567a79 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -724,8 +724,6 @@ call_summary_replay::convert_region_from_summary_1 (const 
region *summary_reg)
   break;
 case RK_CAST:
   {
-   const cast_region *summary_cast_reg
- = as_a  (summary_reg);
const region *summary_parent_reg = summary_reg->get_parent_region ();
const region *caller_parent_reg
  = convert_region_from_summary (summary_parent_reg);


[gcc r15-3431] pretty-print: split up pretty_printer::format into subroutines

2024-09-03 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:07e74798b93c256bea3a91895d3517223a58da61

commit r15-3431-g07e74798b93c256bea3a91895d3517223a58da61
Author: David Malcolm 
Date:   Tue Sep 3 15:11:06 2024 -0400

pretty-print: split up pretty_printer::format into subroutines

The body of pretty_printer::format is almost 500 lines long,
mostly comprising two distinct phases.

This patch splits it up so that there are explicit subroutines
for the two different phases, reducing the scope of various
locals, and making it easier to e.g. put a breakpoint on phase 2.

No functional change intended.

gcc/ChangeLog:
* pretty-print-markup.h (pp_markup::context::context): Drop
params "buf" and "chunk_idx", initializing m_buf from pp.
(pp_markup::context::m_chunk_idx): Drop field.
* pretty-print.cc (pretty_printer::format): Convert param
from a text_info * to a text_info &.  Split out phase 1
and phase 2 into subroutines...
(format_phase_1): New, from pretty_printer::format.
(format_phase_2): Likewise.
* pretty-print.h (pretty_printer::format): Convert param
from a text_info * to a text_info &.
(pp_format): Update for above change.  Assert that text_info is
non-null.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/pretty-print-markup.h |   6 +-
 gcc/pretty-print.cc   | 232 +-
 gcc/pretty-print.h|   5 +-
 3 files changed, 131 insertions(+), 112 deletions(-)

diff --git a/gcc/pretty-print-markup.h b/gcc/pretty-print-markup.h
index ce2c5e9dbbe9..de9e4bda6ade 100644
--- a/gcc/pretty-print-markup.h
+++ b/gcc/pretty-print-markup.h
@@ -30,13 +30,10 @@ class context
 {
 public:
   context (pretty_printer &pp,
-  output_buffer &buf,
-  unsigned chunk_idx,
   bool "ed,
   pp_token_list *formatted_token_list)
   : m_pp (pp),
-m_buf (buf),
-m_chunk_idx (chunk_idx),
+m_buf (*pp_buffer (&pp)),
 m_quoted (quoted),
 m_formatted_token_list (formatted_token_list)
   {
@@ -52,7 +49,6 @@ public:
 
   pretty_printer &m_pp;
   output_buffer &m_buf;
-  unsigned m_chunk_idx;
   bool &m_quoted;
   pp_token_list *m_formatted_token_list;
 };
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 115f376c4512..998e06e155f7 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -1589,35 +1589,79 @@ push_back_any_text (pp_token_list *tok_list,
Phase 3 is in pp_output_formatted_text, which pops the pp_formatted_chunks
instance.  */
 
+static void
+format_phase_1 (const text_info &text,
+   obstack &chunk_obstack,
+   pp_token_list **args,
+   pp_token_list ***formatters);
+
+static void
+format_phase_2 (pretty_printer *pp,
+   text_info &text,
+   obstack &chunk_obstack,
+   pp_token_list ***formatters);
+
 void
-pretty_printer::format (text_info *text)
+pretty_printer::format (text_info &text)
 {
-  output_buffer * const buffer = m_buffer;
+  pp_formatted_chunks *new_chunk_array = m_buffer->push_formatted_chunks ();
+  pp_token_list **args = new_chunk_array->m_args;
 
-  unsigned int chunk = 0, argno;
   pp_token_list **formatters[PP_NL_ARGMAX];
-
-  pp_formatted_chunks *new_chunk_array = buffer->push_formatted_chunks ();
-  pp_token_list **args = new_chunk_array->m_args;
+  memset (formatters, 0, sizeof formatters);
 
   /* Formatting phase 1: split up TEXT->format_spec into chunks in
  pp_buffer (PP)->args[].  Even-numbered chunks are to be output
  verbatim, odd-numbered chunks are format specifiers.
  %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
  this point.  */
+  format_phase_1 (text, m_buffer->m_chunk_obstack, args, formatters);
 
-  memset (formatters, 0, sizeof formatters);
+  /* Note that you can debug the state of the chunk arrays here using
+   (gdb) call m_buffer->cur_chunk_array->dump()
+ which, given e.g. "foo: %s bar: %s" might print:
+   0: [TEXT("foo: ")]
+   1: [TEXT("s")]
+   2: [TEXT(" bar: ")]
+   3: [TEXT("s")]
+  */
+
+  /* Set output to the argument obstack, and switch line-wrapping and
+ prefixing off.  */
+  m_buffer->m_obstack = &m_buffer->m_chunk_obstack;
+  const int old_line_length = m_buffer->m_line_length;
+  const pp_wrapping_mode_t old_wrapping_mode = pp_set_verbatim_wrapping (this);
+
+  format_phase_2 (this, text, m_buffer->m_chunk_obstack, formatters);
+
+  /* If the client supplied a postprocessing object, call its "handle"
+ hook here.  */
+  if (m_format_postprocessor)
+m_format_postprocessor->handle (this);
+
+  /* Revert to normal obstack and wrapping mode.  */
+  m_buffer->m_obstack = &m_buffer->m_formatted_obstack;
+  m_buffer->m_line_length = old_line_length;
+  pp_wrapping_mode (this) = old_wrapping_mode;
+  clear_state ();
+}
 
+static void
+format_phase_1 (cons

[gcc r15-3429] pretty-print: naming cleanups

2024-09-03 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:34f01475611b422668a70744c79273c7019625f2

commit r15-3429-g34f01475611b422668a70744c79273c7019625f2
Author: David Malcolm 
Date:   Tue Sep 3 15:10:56 2024 -0400

pretty-print: naming cleanups

This patch is a followup to r15-3311-ge31b6176996567 making some
cleanups to pretty-printing to reflect those changes:
- renaming "chunk_info" to "pp_formatted_chunks"
- renaming "cur_chunk_array" to "m_cur_fomatted_chunks"
- rewording/clarifying comments
and taking the opportunity to add a "m_" prefix to all fields of
output_buffer.

No functional change intended.

gcc/analyzer/ChangeLog:
* analyzer-logging.cc (logger::logger): Prefix all output_buffer
fields with "m_".

gcc/c-family/ChangeLog:
* c-ada-spec.cc (dump_ada_node): Prefix all output_buffer fields
with "m_".
* c-pretty-print.cc (pp_c_integer_constant): Likewise.
(pp_c_integer_constant): Likewise.
(pp_c_floating_constant): Likewise.
(pp_c_fixed_constant): Likewise.

gcc/c/ChangeLog:
* c-objc-common.cc (print_type): Prefix all output_buffer fields
with "m_".

gcc/cp/ChangeLog:
* error.cc (type_to_string): Prefix all output_buffer fields with
"m_".
(append_formatted_chunk): Likewise.  Rename "chunk_info" to
"pp_formatted_chunks" and field cur_chunk_array with
m_cur_formatted_chunks.

gcc/fortran/ChangeLog:
* error.cc (gfc_move_error_buffer_from_to): Prefix all
output_buffer fields with "m_".
(gfc_diagnostics_init): Likewise.

gcc/ChangeLog:
* diagnostic.cc (diagnostic_set_caret_max_width): Prefix all
output_buffer fields with "m_".
* dumpfile.cc (emit_any_pending_textual_chunks): Likewise.
(emit_any_pending_textual_chunks): Likewise.
* gimple-pretty-print.cc (gimple_dump_bb_buff): Likewise.
* json.cc (value::dump): Likewise.
* pretty-print-format-impl.h (class chunk_info): Rename to...
(class pp_formatted_chunks): ...this.  Add friend
class output_buffer.  Update comment near end of decl to show
the pp_formatted_chunks instance on the chunk_obstack.
(pp_formatted_chunks::pop_from_output_buffer): Delete decl.
(pp_formatted_chunks::on_begin_quote): Delete decl that should
have been removed in r15-3311-ge31b6176996567.
(pp_formatted_chunks::on_end_quote): Likewise.
(pp_formatted_chunks::m_prev): Update for renaming.
* pretty-print.cc (output_buffer::output_buffer): Prefix all
fields with "m_".  Rename "cur_chunk_array" to
"m_cur_formatted_chunks".
(output_buffer::~output_buffer): Prefix all fields with "m_".
(output_buffer::push_formatted_chunks): New.
(output_buffer::pop_formatted_chunks): New.
(pp_write_text_to_stream): Prefix all output_buffer fields with
"m_".
(pp_write_text_as_dot_label_to_stream): Likewise.
(pp_write_text_as_html_like_dot_to_stream): Likewise.
(chunk_info::append_formatted_chunk): Rename to...
(pp_formatted_chunks::append_formatted_chunk): ...this.
(chunk_info::pop_from_output_buffer): Delete.
(pretty_printer::format): Update leading comment to mention
pushing pp_formatted_chunks, and to reflect changes in
r15-3311-ge31b6176996567.  Prefix all output_buffer fields with
"m_".
(pp_output_formatted_text): Update leading comment to mention
popping a pp_formatted_chunks, and to reflect the changes in
r15-3311-ge31b6176996567.  Prefix all output_buffer fields with
"m_" and rename "cur_chunk_array" to "m_cur_formatted_chunks".
Replace call to chunk_info::pop_from_output_buffer with a call to
output_buffer::pop_formatted_chunks.
(pp_flush): Prefix all output_buffer fields with "m_".
(pp_really_flush): Likewise.
(pp_clear_output_area): Likewise.
(pp_append_text): Likewise.
(pretty_printer::remaining_character_count_for_line): Likewise.
(pp_newline): Likewise.
(pp_character): Likewise.
(pp_markup::context::push_back_any_text): Likewise.
* pretty-print.h (class chunk_info): Rename to...
(class pp_formatted_chunks): ...this.
(class output_buffer): Delete unimplemented rule-of-5 members.
(output_buffer::push_formatted_chunks): New decl.
(output_buffer::pop_formatted_chunks): New decl.
(output_buffer::formatted_obstack): Rename to...
(output_buffer::m_formatted_obstack): ...this.
(output_buffe

[gcc r15-3430] pretty-print: add selftest of pp_format's stack

2024-09-03 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d0891f3aa75d31744de728905f2f454e9d07ce54

commit r15-3430-gd0891f3aa75d31744de728905f2f454e9d07ce54
Author: David Malcolm 
Date:   Tue Sep 3 15:11:01 2024 -0400

pretty-print: add selftest of pp_format's stack

gcc/ChangeLog:
* pretty-print-format-impl.h (pp_formatted_chunks::get_prev): New
accessor.
* pretty-print.cc (selftest::push_pp_format): New.
(ASSERT_TEXT_TOKEN): New macro.
(selftest::test_pp_format_stack): New test.
(selftest::pretty_print_cc_tests): New.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/pretty-print-format-impl.h |  3 ++
 gcc/pretty-print.cc| 78 ++
 2 files changed, 81 insertions(+)

diff --git a/gcc/pretty-print-format-impl.h b/gcc/pretty-print-format-impl.h
index c70f61ce1bab..ec4425c9dafb 100644
--- a/gcc/pretty-print-format-impl.h
+++ b/gcc/pretty-print-format-impl.h
@@ -376,6 +376,9 @@ public:
   void dump (FILE *out) const;
   void DEBUG_FUNCTION dump () const { dump (stderr); }
 
+  // For use in selftests
+  pp_formatted_chunks *get_prev () const { return m_prev; }
+
 private:
   /* Pointer to previous level on the stack.  */
   pp_formatted_chunks *m_prev;
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 50aea69edd62..115f376c4512 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -3547,6 +3547,83 @@ test_custom_tokens_2 ()
"print_tokens was called");
 }
 
+/* Helper subroutine for test_pp_format_stack.
+   Call pp_format (phases 1 and 2), without calling phase 3.  */
+
+static void
+push_pp_format (pretty_printer *pp, const char *msg, ...)
+{
+  va_list ap;
+
+  va_start (ap, msg);
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+  text_info ti (msg, &ap, 0, nullptr, &rich_loc);
+  pp_format (pp, &ti);
+  va_end (ap);
+}
+
+#define ASSERT_TEXT_TOKEN(TOKEN, EXPECTED_TEXT)\
+  SELFTEST_BEGIN_STMT  \
+ASSERT_NE ((TOKEN), nullptr);  \
+ASSERT_EQ ((TOKEN)->m_kind, pp_token::kind::text); \
+ASSERT_STREQ   \
+  (as_a  (TOKEN)->m_value.get (),   \
+   (EXPECTED_TEXT));   \
+  SELFTEST_END_STMT
+
+
+/* Verify that the stack of pp_formatted_chunks works as expected.  */
+
+static void
+test_pp_format_stack ()
+{
+  auto_fix_quotes fix_quotes;
+
+  pretty_printer pp;
+  push_pp_format (&pp, "unexpected foo: %i bar: %qs", 42, "test");
+  push_pp_format (&pp, "In function: %qs", "test_fn");
+
+  /* Expect the top of the stack to have:
+ (gdb) call top->dump()
+ 0: [TEXT("In function: ")]
+ 1: [BEGIN_QUOTE, TEXT("test_fn"), END_QUOTE].  */
+
+  pp_formatted_chunks *top = pp_buffer (&pp)->m_cur_formatted_chunks;
+  ASSERT_NE (top, nullptr);
+  ASSERT_TEXT_TOKEN (top->get_token_lists ()[0]->m_first, "In function: ");
+  ASSERT_EQ (top->get_token_lists ()[1]->m_first->m_kind,
+pp_token::kind::begin_quote);
+  ASSERT_EQ (top->get_token_lists ()[2], nullptr);
+
+  /* Expect an entry in the stack below it with:
+ 0: [TEXT("unexpected foo: ")]
+ 1: [TEXT("42")]
+ 2: [TEXT(" bar: ")]
+ 3: [BEGIN_QUOTE, TEXT("test"), END_QUOTE].  */
+  pp_formatted_chunks *prev = top->get_prev ();
+  ASSERT_NE (prev, nullptr);
+  ASSERT_TEXT_TOKEN (prev->get_token_lists ()[0]->m_first, "unexpected foo: ");
+  ASSERT_TEXT_TOKEN (prev->get_token_lists ()[1]->m_first, "42");
+  ASSERT_TEXT_TOKEN (prev->get_token_lists ()[2]->m_first, " bar: ");
+  ASSERT_EQ (prev->get_token_lists ()[3]->m_first->m_kind,
+pp_token::kind::begin_quote);
+  ASSERT_EQ (prev->get_token_lists ()[4], nullptr);
+
+  ASSERT_EQ (prev->get_prev (), nullptr);
+
+  /* Pop the top of the stack.  */
+  pp_output_formatted_text (&pp);
+  ASSERT_EQ (pp_buffer (&pp)->m_cur_formatted_chunks, prev);
+  pp_newline (&pp);
+
+  /* Pop the remaining entry from the stack.  */
+  pp_output_formatted_text (&pp);
+  ASSERT_EQ (pp_buffer (&pp)->m_cur_formatted_chunks, nullptr);
+
+  ASSERT_STREQ (pp_formatted_text (&pp),
+   "In function: `test_fn'\nunexpected foo: 42 bar: `test'");
+}
+
 /* A subclass of pretty_printer for use by test_prefixes_and_wrapping.  */
 
 class test_pretty_printer : public pretty_printer
@@ -3976,6 +4053,7 @@ pretty_print_cc_tests ()
   test_merge_consecutive_text_tokens ();
   test_custom_tokens_1 ();
   test_custom_tokens_2 ();
+  test_pp_format_stack ();
   test_prefixes_and_wrapping ();
   test_urls ();
   test_urls_from_braces ();


[gcc r15-3311] pretty-print: reimplement pp_format with a new struct pp_token

2024-08-29 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:e31b61769965674c7005277f2d9a5db2f6c30f3a

commit r15-3311-ge31b61769965674c7005277f2d9a5db2f6c30f3a
Author: David Malcolm 
Date:   Thu Aug 29 18:48:27 2024 -0400

pretty-print: reimplement pp_format with a new struct pp_token

The following patch rewrites the internals of pp_format.

A pretty_printer's output_buffer maintains a stack of chunk_info
instances, each one responsible for handling a call to pp_format, where
having a stack allows us to support re-entrant calls to pp_format on the
same pretty_printer.

Previously a chunk_info merely stored buffers of accumulated text
per unformatted run and per formatted argument.

This led to various special-casing for handling:

- urlifiers, needing class quoting_info to handle awkard cases where
  the run of quoted text could be split between stages 1 and 2
  of formatting

- dumpfiles, where the optinfo machinery could lead to objects being
  stashed during formatting for later replay to JSON optimization
  records

- in the C++ frontend, the format codes %H and %I can't be processed
  until we've seen both, leading to awkward code to manipulate the
  text buffers

Further, supporting URLs in messages in SARIF output (PR other/116419)
would add additional manipulations of text buffers, since our internal
pp_begin_url API gives the URL at the beginning of the wrapped text,
whereas SARIF's format for embedded URLs has the URL *after* the wrapped
text.  Also when handling "%@" we wouldn't necessarily know the URL of
an event ID until later, requiring further nasty special-case
manipulation of text buffers.

This patch rewrites pretty-print formatting by introducing a new
intermediate representation during formatting: pp_token and
pp_token_list.  Rather than simply accumulating a buffer of "char" in
the chunk_obstack during formatting, we now also accumulate a
pp_token_list, a doubly-linked list of pp_token, which can be:
- text buffers
- begin/end colorization
- begin/end quote
- begin/end URL
- "custom data" tokens

Working at the level of tokens rather than just text buffers allows the
various awkward special cases above to be replaced with uniform logic.
For example, all "urlification" is now done in phase 3 of formatting,
in one place, by looking for [..., BEGIN_QUOTE, TEXT, END_QUOTE, ...]
and injecting BEGIN_URL and END_URL wrapper tokens when the urlifier
has a URL for TEXT.  Doing so greatly simplifies the urlifier code,
allowing the removal of class quoting_info.

The tokens and token lists are allocated on the chunk_obstack, and so
there's no additional heap activity required, with the memory reclaimed
when the chunk_obstack is freed after phase 3 of formatting.

New kinds of pp_token can be added as needed to support output formats.
For example, the followup patch adds a token for "%@" for events IDs, to
better support SARIF output.

No functional change intended.

gcc/c/ChangeLog:
* c-objc-common.cc (c_tree_printer): Convert final param from
const char ** to pp_token_list &.

gcc/cp/ChangeLog:
* error.cc: Include "make-unique.h".
(deferred_printed_type::m_buffer_ptr): Replace with...
(deferred_printed_type::m_printed_text): ...this and...
(deferred_printed_type::m_token_list): ...this.
(deferred_printed_type::deferred_printed_type): Update ctors for
above changes.
(deferred_printed_type::set_text_for_token_list): New.
(append_formatted_chunk): Pass chunk_obstack to
append_formatted_chunk.
(add_quotes): Delete.
(cxx_format_postprocessor::handle): Reimplement to call
deferred_printed_type::set_text_for_token_list, rather than store
buffer pointers.
(defer_phase_2_of_type_diff): Replace param "buffer_ptr"
with "formatted_token_list".  Reimplement by storing
a pointer to formatted_token_list so that the postprocessor can
put its text there.
(cp_printer): Convert param "buffer_ptr" to
"formatted_token_list".  Update calls to
defer_phase_2_of_type_diff accordingly.

gcc/ChangeLog:
* diagnostic.cc (diagnostic_context::report_diagnostic): Don't
pass m_urlifier to pp_format, as urlification now happens in
phase 3.
* dump-context.h (class dump_pretty_printer): Update leading
comment.
(dump_pretty_printer::emit_items): Drop decl.
(dump_pretty_printer::set_optinfo): New.
(class dump_pretty_printer::stashed_item): Delete class.
(class dump_pretty_printer::custom_token_printer): New class.
(dump_pret

[gcc r15-3312] SARIF output: implement embedded URLs in messages (§3.11.6; PR other/116419)

2024-08-29 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:aff7f677120ec394adcedd0dd5cc3afa3b5be102

commit r15-3312-gaff7f677120ec394adcedd0dd5cc3afa3b5be102
Author: David Malcolm 
Date:   Thu Aug 29 18:48:32 2024 -0400

SARIF output: implement embedded URLs in messages (§3.11.6; PR other/116419)

GCC diagnostic messages can contain URLs, such as to our documentation
when we suggest an option name to correct a misspelling.

SARIF message strings can contain embedded URLs in the plain text
messages (see SARIF v2.1.0 §3.11.6), but previously we were
simply dropping any URLs from the diagnostic messages.

This patch adds support for encoding URLs into messages in our SARIF
output, using the pp_token machinery added in the previous patch.

As well as supporting URLs, the patch also adjusts how we report
event IDs in SARIF message, so that rather than e.g.
  "text": "second 'free' here; first 'free' was at (1)"
we now report:
  "text": "second 'free' here; first 'free' was at 
[(1)](sarif:/runs/0/results/0/codeFlows/0/threadFlows/0/locations/0)"

i.e. the text "(1)" now has a embedded link referring within the sarif
log to the threadFlowLocation object for the other event, via JSON
pointer (see §3.10.3 "URIs that use the sarif scheme").  Doing so
requires the arious objects to know their index within their containing
array, requiring some reworking of how they are constructed.

gcc/ChangeLog:
PR other/116419
* diagnostic-event-id.h (diagnostic_event_id_t::zero_based): New.
* diagnostic-format-sarif.cc: Include "pretty-print-format-impl.h"
and "pretty-print-urlifier.h".
(sarif_result::sarif_result): Add param "idx_within_parent".
(sarif_result::get_index_within_parent): New accessor.
(sarif_result::m_idx_within_parent): New field.
(sarif_code_flow::sarif_code_flow): New ctor.
(sarif_code_flow::get_parent): New accessor.
(sarif_code_flow::get_index_within_parent): New accessor.
(sarif_code_flow::m_parent): New field.
(sarif_code_flow::m_thread_id_map): New field.
(sarif_code_flow::m_thread_flows_arr): New field.
(sarif_code_flow::m_all_tfl_objs): New field.
(sarif_thread_flow::sarif_thread_flow): Add "parent" and
"idx_within_parent" params.
(sarif_thread_flow::get_parent): New accessor.
(sarif_thread_flow::get_index_within_parent): New accessor.
(sarif_thread_flow::m_parent): New field.
(sarif_thread_flow::m_idx_within_parent): New field.
(sarif_thread_flow_location::sarif_thread_flow_location): New
ctor.
(sarif_thread_flow_location::get_parent): New accessor.
(sarif_thread_flow_location::get_index_within_parent): New
accessor.
(sarif_thread_flow_location::m_parent): New field.
(sarif_thread_flow_location::m_idx_within_parent): New field.
(sarif_builder::get_code_flow_for_event_ids): New accessor.
(class sarif_builder::sarif_token_printer): New.
(sarif_builder::m_token_printer): New member.
(sarif_builder::m_next_result_idx): New field.
(sarif_builder::m_current_code_flow): New field.
(sarif_code_flow::get_or_append_thread_flow): New.
(sarif_code_flow::get_thread_flow): New.
(sarif_code_flow::add_location): New.
(sarif_code_flow::get_thread_flow_loc_obj): New.
(sarif_thread_flow::add_location): Create the new
sarif_thread_flow_location internally, rather than passing
it in as a parm so that we can keep track of its index in
the array.  Return a reference to it.
(sarif_builder::sarif_builder): Initialize m_token_printer,
m_next_result_idx, and m_current_code_flow.
(sarif_builder::on_report_diagnostic): Pass index to
make_result_object.
(sarif_builder::make_result_object): Add "idx_within_parent" param
and pass to sarif_result ctor.  Pass code flow index to call to
make_code_flow_object.
(make_sarif_url_for_event): New.
(sarif_builder::make_code_flow_object): Add "idx_within_parent"
param and pass it to sarif_code_flow ctor.  Reimplement walking
of events so that we first create threadFlow objects for each
thread, then populate them with threadFlowLocation objects, so
that the IDs work.  Set m_current_code_flow whilst creating the
latter, so that we can create correct URIs for "%@".
(sarif_builder::make_thread_flow_location_object): Replace with...
(sarif_builder::populate_thread_flow_location_object): ...this.
(sarif_output_format::get_builder): New accessor.
(sarif_be

[gcc r15-3310] pretty-print: move class chunk_info into its own header

2024-08-29 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:68a0ca66972a0607b3e90ae51521da9b12ad63ca

commit r15-3310-g68a0ca66972a0607b3e90ae51521da9b12ad63ca
Author: David Malcolm 
Date:   Thu Aug 29 18:48:20 2024 -0400

pretty-print: move class chunk_info into its own header

No functional change intended.

gcc/cp/ChangeLog:
* error.cc: Include "pretty-print-format-impl.h".

gcc/ChangeLog:
* dumpfile.cc: Include "pretty-print-format-impl.h".
* pretty-print-format-impl.h: New file, based on material from
pretty-print.h.
* pretty-print.cc: Include "pretty-print-format-impl.h".
* pretty-print.h (chunk_info): Replace full declaration with
a forward decl, moving full decl to pretty-print-format-impl.h.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/cp/error.cc|  1 +
 gcc/dumpfile.cc|  1 +
 gcc/pretty-print-format-impl.h | 70 ++
 gcc/pretty-print.cc|  1 +
 gcc/pretty-print.h | 45 +--
 5 files changed, 74 insertions(+), 44 deletions(-)

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 879e5a115cfe..3cc0dd1cdfa9 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-type-mismatch.h"
 #include "cp-name-hint.h"
 #include "attribs.h"
+#include "pretty-print-format-impl.h"
 
 #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
 #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 2971c69bb0a1..eb245059210a 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h" /* for get_identifier.  */
 #include "spellcheck.h"
 #include "make-unique.h"
+#include "pretty-print-format-impl.h"
 
 /* If non-NULL, return one past-the-end of the matching SUBPART of
the WHOLE string.  */
diff --git a/gcc/pretty-print-format-impl.h b/gcc/pretty-print-format-impl.h
new file mode 100644
index ..e05ad388963d
--- /dev/null
+++ b/gcc/pretty-print-format-impl.h
@@ -0,0 +1,70 @@
+/* Implementation detail of pp_format.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
+   Contributed by Gabriel Dos Reis 
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_PRETTY_PRINT_FORMAT_IMPL_H
+#define GCC_PRETTY_PRINT_FORMAT_IMPL_H
+
+#include "pretty-print.h"
+
+/* The chunk_info data structure forms a stack of the results from the
+   first phase of formatting (pp_format) which have not yet been
+   output (pp_output_formatted_text).  A stack is necessary because
+   the diagnostic starter may decide to generate its own output by way
+   of the formatter.  */
+class chunk_info
+{
+  friend class pretty_printer;
+  friend class pp_markup::context;
+
+public:
+  const char * const *get_args () const { return m_args; }
+  quoting_info *get_quoting_info () const { return m_quotes; }
+
+  void append_formatted_chunk (const char *content);
+
+  void pop_from_output_buffer (output_buffer &buf);
+
+private:
+  void on_begin_quote (const output_buffer &buf,
+  unsigned chunk_idx,
+  const urlifier *urlifier);
+
+  void on_end_quote (pretty_printer *pp,
+output_buffer &buf,
+unsigned chunk_idx,
+const urlifier *urlifier);
+
+  /* Pointer to previous chunk on the stack.  */
+  chunk_info *m_prev;
+
+  /* Array of chunks to output.  Each chunk is a NUL-terminated string.
+ In the first phase of formatting, even-numbered chunks are
+ to be output verbatim, odd-numbered chunks are format specifiers.
+ The second phase replaces all odd-numbered chunks with formatted
+ text, and the third phase simply emits all the chunks in sequence
+ with appropriate line-wrapping.  */
+  const char *m_args[PP_NL_ARGMAX * 2];
+
+  /* If non-null, information on quoted text runs within the chunks
+ for use by a urlifier.  */
+  quoting_info *m_quotes;
+};
+
+#endif /* GCC_PRETTY_PRINT_FORMAT_IMPL_H */
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 1d91da828212..810c629ef116 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -24,6 +24,7 @@ along with GCC; see the file

[gcc r15-3309] Use std::unique_ptr for optinfo_item

2024-08-29 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:464a3d2fe53362281eba123c3099346f625edd58

commit r15-3309-g464a3d2fe53362281eba123c3099346f625edd58
Author: David Malcolm 
Date:   Thu Aug 29 18:48:16 2024 -0400

Use std::unique_ptr for optinfo_item

As preliminary work towards an overhaul of how optinfo_items
interact with dump_pretty_printer, replace uses of optinfo_item * with
std::unique_ptr to make ownership clearer.

No functional change intended.

gcc/ChangeLog:
* config/aarch64/aarch64.cc: Define INCLUDE_MEMORY.
* config/arm/arm.cc: Likewise.
* config/i386/i386.cc: Likewise.
* config/loongarch/loongarch.cc: Likewise.
* config/riscv/riscv-vector-costs.cc: Likewise.
* config/riscv/riscv.cc: Likewise.
* config/rs6000/rs6000.cc: Likewise.
* dump-context.h (dump_context::emit_item): Convert "item" param
from * to const &.
(dump_pretty_printer::stash_item): Convert "item" param from
optinfo_ * to std::unique_ptr.
(dump_pretty_printer::emit_item): Likewise.
* dumpfile.cc: Include "make-unique.h".
(make_item_for_dump_gimple_stmt): Replace uses of optinfo_item *
with std::unique_ptr.
(dump_context::dump_gimple_stmt): Likewise.
(make_item_for_dump_gimple_expr): Likewise.
(dump_context::dump_gimple_expr): Likewise.
(make_item_for_dump_generic_expr): Likewise.
(dump_context::dump_generic_expr): Likewise.
(make_item_for_dump_symtab_node): Likewise.
(dump_pretty_printer::emit_items): Likewise.
(dump_pretty_printer::emit_any_pending_textual_chunks): Likewise.
(dump_pretty_printer::emit_item): Likewise.
(dump_pretty_printer::stash_item): Likewise.
(dump_pretty_printer::decode_format): Likewise.
(dump_context::dump_printf_va): Fix overlong line.
(make_item_for_dump_dec): Replace uses of optinfo_item * with
std::unique_ptr.
(dump_context::dump_dec): Likewise.
(dump_context::dump_symtab_node): Likewise.
(dump_context::begin_scope): Likewise.
(dump_context::emit_item): Likewise.
* gimple-loop-interchange.cc: Define INCLUDE_MEMORY.
* gimple-loop-jam.cc: Likewise.
* gimple-loop-versioning.cc: Likewise.
* graphite-dependences.cc: Likewise.
* graphite-isl-ast-to-gimple.cc: Likewise.
* graphite-optimize-isl.cc: Likewise.
* graphite-poly.cc: Likewise.
* graphite-scop-detection.cc: Likewise.
* graphite-sese-to-poly.cc: Likewise.
* graphite.cc: Likewise.
* opt-problem.cc: Likewise.
* optinfo.cc (optinfo::add_item): Convert "item" param from
optinfo_ * to std::unique_ptr.
(optinfo::emit_for_opt_problem): Update for change to
dump_context::emit_item.
* optinfo.h: Add #error to fail immediately if INCLUDE_MEMORY
wasn't defined, rather than fail to find std::unique_ptr.
(optinfo::add_item): Convert "item" param from optinfo_ * to
std::unique_ptr.
* sese.cc: Define INCLUDE_MEMORY.
* targhooks.cc: Likewise.
* tree-data-ref.cc: Likewise.
* tree-if-conv.cc: Likewise.
* tree-loop-distribution.cc: Likewise.
* tree-parloops.cc: Likewise.
* tree-predcom.cc: Likewise.
* tree-ssa-live.cc: Likewise.
* tree-ssa-loop-ivcanon.cc: Likewise.
* tree-ssa-loop-ivopts.cc: Likewise.
* tree-ssa-loop-prefetch.cc: Likewise.
* tree-ssa-loop-unswitch.cc: Likewise.
* tree-ssa-phiopt.cc: Likewise.
* tree-ssa-threadbackward.cc: Likewise.
* tree-ssa-threadupdate.cc: Likewise.
* tree-vect-data-refs.cc: Likewise.
* tree-vect-generic.cc: Likewise.
* tree-vect-loop-manip.cc: Likewise.
* tree-vect-loop.cc: Likewise.
* tree-vect-patterns.cc: Likewise.
* tree-vect-slp-patterns.cc: Likewise.
* tree-vect-slp.cc: Likewise.
* tree-vect-stmts.cc: Likewise.
* tree-vectorizer.cc: Likewise.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/dump_plugin.c: Define INCLUDE_MEMORY.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/config/aarch64/aarch64.cc |   1 +
 gcc/config/arm/arm.cc |   1 +
 gcc/config/i386/i386.cc   |   1 +
 gcc/config/loongarch/loongarch.cc |   1 +
 gcc/config/riscv/riscv-vector-costs.cc|   1 +
 gcc/config/riscv/riscv.cc |   1 +
 gcc/config/rs6000/rs6000.cc   |   1 +
 gcc/dump-context.h|   7 +-
 gcc/dumpfile.cc 

[gcc r15-3198] testsuite: generalize support for Python tests for SARIF output

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:aa3b950291119a2b107e3a82bb4ad35a2baa2105

commit r15-3198-gaa3b950291119a2b107e3a82bb4ad35a2baa2105
Author: David Malcolm 
Date:   Mon Aug 26 12:24:21 2024 -0400

testsuite: generalize support for Python tests for SARIF output

In r15-2354-g4d1f71d49e396c I added the ability to use Python to write
tests of SARIF output via a new "run-sarif-pytest" based
on "run-gcov-pytest", with a sarif.py support script in
testsuite/gcc.dg/sarif-output.

This followup patch:
(a) removes the limitation of such tests needing to be in
testsuite/gcc.dg/sarif-output by moving sarif.py to testsuite/lib
and adding logic to add that directory to PYTHONPATH when invoking
pytest.

(b) uses this to replace fragile regexp-based tests in
gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.c with
Python logic that verifies the structure within the generated JSON,
and to add test coverage for SARIF output relating to GCC plugins.

gcc/ChangeLog:
* diagnostic-format-sarif.cc: Add comments noting that we don't
yet capture any diagnostic_metadata::rules associated with a
diagnostic.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic-test-metadata-sarif.c: New test,
based on diagnostic-test-metadata.c.
* gcc.dg/plugin/diagnostic-test-metadata-sarif.py: New script.
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.c:
Replace scan-sarif-file directives with run-sarif-pytest, to
run...
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py:
...this new test.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
diagnostic-test-metadata-sarif.c.
* gcc.dg/sarif-output/sarif.py: Move to...
* lib/sarif.py: ...here.
* lib/scansarif.exp (run-sarif-pytest): Prepend "lib" to
PYTHONPATH before running python scripts.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc |   6 +-
 .../gcc.dg/plugin/diagnostic-test-metadata-sarif.c |  17 
 .../plugin/diagnostic-test-metadata-sarif.py   |  55 +++
 .../diagnostic-test-paths-multithreaded-sarif.c|  17 +---
 .../diagnostic-test-paths-multithreaded-sarif.py   | 109 +
 gcc/testsuite/gcc.dg/plugin/plugin.exp |   4 +-
 .../{gcc.dg/sarif-output => lib}/sarif.py  |   0
 gcc/testsuite/lib/scansarif.exp|  16 +++
 8 files changed, 208 insertions(+), 16 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 963a185f6ced..1d99c904ff0c 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -580,7 +580,9 @@ public:
  (SARIF v2.1.0 section 3.27.13).
- doesn't capture -Werror cleanly
- doesn't capture inlining information (can SARIF handle this?)
-   - doesn't capture macro expansion information (can SARIF handle this?).  */
+   - doesn't capture macro expansion information (can SARIF handle this?).
+   - doesn't capture any diagnostic_metadata::rules associated with
+ a diagnostic.  */
 
 class sarif_builder
 {
@@ -1522,6 +1524,8 @@ sarif_builder::make_result_object (diagnostic_context 
&context,
}
 
   diagnostic.metadata->maybe_add_sarif_properties (*result_obj);
+
+  /* We don't yet support diagnostic_metadata::rule.  */
 }
 
   /* "level" property (SARIF v2.1.0 section 3.27.10).  */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.c 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.c
new file mode 100644
index ..246a8429090d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-format=sarif-file" } */
+
+extern char *gets (char *s);
+
+void test_cwe (void)
+{
+  char buf[1024];
+  gets (buf);
+}
+
+/* Verify that some JSON was written to a file with the expected name.  */
+/* { dg-final { verify-sarif-file } } */
+
+/* Use a Python script to verify various properties about the generated
+   .sarif file:
+   { dg-final { run-sarif-pytest diagnostic-test-metadata-sarif.c 
"diagnostic-test-metadata-sarif.py" } } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.py 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.py
new file mode 100644
index ..959e6f2e9942
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-sarif.py
@@ -0,0 +1,55 @@
+# We expect a warning with this textual form:
+#
+# . PATH/diagnostic-test-metadata-sarif.c: In function 'test_cwe':
+# . PATH/diagnostic-test-metadata-sarif.c:8:3: warning: never use 'gets' 
[CWE-242] [STR34-C]
+
+from sarif import *
+
+import pytest
+
+@pytest.fixture(scope='function', autouse=True)
+def sarif():
+retu

[gcc r15-3201] diagnostics: move output formats from diagnostic.{c, h} to their own files

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:92c5265d22afaac146b2a7ecbc3dac9fc3382877

commit r15-3201-g92c5265d22afaac146b2a7ecbc3dac9fc3382877
Author: David Malcolm 
Date:   Mon Aug 26 12:24:22 2024 -0400

diagnostics: move output formats from diagnostic.{c,h} to their own files

In particular, move the classic text output code to a
diagnostic-text.cc (analogous to -json.cc and -sarif.cc).

No functional change intended.

gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add diagnostic-format-text.o.
* diagnostic-format-json.cc: Include "diagnostic-format.h".
* diagnostic-format-sarif.cc: Likewise.
* diagnostic-format-text.cc: New file, using material from
diagnostics.cc.
* diagnostic-global-context.cc: Include
"diagnostic-format.h".
* diagnostic-format-text.h: New file, using material from
diagnostics.h.
* diagnostic-format.h: New file, using material from
diagnostics.h.
* diagnostic.cc: Include "diagnostic-format.h" and
"diagnostic-format-text.h".
(diagnostic_text_output_format::~diagnostic_text_output_format):
Move to diagnostic-format-text.cc.
(diagnostic_text_output_format::on_report_diagnostic): Likewise.
(diagnostic_text_output_format::on_diagram): Likewise.
(diagnostic_text_output_format::print_any_cwe): Likewise.
(diagnostic_text_output_format::print_any_rules): Likewise.
(diagnostic_text_output_format::print_option_information):
Likewise.
* diagnostic.h (class diagnostic_output_format): Move to
diagnostic-format.h.
(class diagnostic_text_output_format): Move to
diagnostic-format-text.h.
(diagnostic_output_format_init): Move to
diagnostic-format.h.
(diagnostic_output_format_init_json_stderr): Likewise.
(diagnostic_output_format_init_json_file): Likewise.
(diagnostic_output_format_init_sarif_stderr): Likewise.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* gcc.cc: Include "diagnostic-format.h".
* opts.cc: Include "diagnostic-format.h".

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic_group_plugin.c: Include
"diagnostic-format-text.h".

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in|   1 +
 gcc/diagnostic-format-json.cc  |   1 +
 gcc/diagnostic-format-sarif.cc |   1 +
 gcc/diagnostic-format-text.cc  | 209 +
 gcc/diagnostic-format-text.h   |  56 ++
 gcc/diagnostic-format.h|  83 
 gcc/diagnostic-global-context.cc   |   1 +
 gcc/diagnostic.cc  | 176 +
 gcc/diagnostic.h   |  85 +
 gcc/gcc.cc |   1 +
 gcc/opts.cc|   1 +
 .../gcc.dg/plugin/diagnostic_group_plugin.c|   1 +
 12 files changed, 359 insertions(+), 257 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 8fba8f7db6a2..68fda1a75918 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1821,6 +1821,7 @@ OBJS = \
 OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
diagnostic-format-json.o \
diagnostic-format-sarif.o \
+   diagnostic-format-text.o \
diagnostic-global-context.o \
diagnostic-macro-unwinding.o \
diagnostic-path.o \
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index f2e9d0d79e51..c94f5f73bb5a 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest-diagnostic.h"
 #include "diagnostic-metadata.h"
 #include "diagnostic-path.h"
+#include "diagnostic-format.h"
 #include "json.h"
 #include "selftest.h"
 #include "logical-location.h"
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 554bf3cb2d5c..59d9cd721839 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "diagnostic-metadata.h"
 #include "diagnostic-path.h"
+#include "diagnostic-format.h"
 #include "json.h"
 #include "cpplib.h"
 #include "logical-location.h"
diff --git a/gcc/diagnostic-format-text.cc b/gcc/diagnostic-format-text.cc
new file mode 100644
index ..b984803ff380
--- /dev/null
+++ b/gcc/diagnostic-format-text.cc
@@ -0,0 +1,209 @@
+/* Classic text-based output of diagnostics.
+   Copyright (C) 1999-202

[gcc r15-3200] diagnostics: consolidate on_{begin, end}_diagnostic into on_report_diagnostic

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:ac707d30ce449f30c6018829d443956fdd653f4c

commit r15-3200-gac707d30ce449f30c6018829d443956fdd653f4c
Author: David Malcolm 
Date:   Mon Aug 26 12:24:22 2024 -0400

diagnostics: consolidate on_{begin,end}_diagnostic into on_report_diagnostic

Previously diagnostic_context::report_diagnostic had, after the call to
pp_format (phases 1 and 2 of formatting the message):

  m_output_format->on_begin_diagnostic (*diagnostic);
  pp_output_formatted_text (this->printer, m_urlifier);
  if (m_show_cwe)
print_any_cwe (*diagnostic);
  if (m_show_rules)
print_any_rules (*diagnostic);
  if (m_show_option_requested)
  print_option_information (*diagnostic, orig_diag_kind);
  m_output_format->on_end_diagnostic (*diagnostic, orig_diag_kind);

This patch replaces all of the above with a single call to

  m_output_format->on_report_diagnostic (*diagnostic, orig_diag_kind);

moving responsibility for phase 3 of formatting and printing the result
from diagnostic_context to the output format.

This simplifies diagnostic_context::report_diagnostic and allows us to
move the code that prints CWEs, rules, and option information in textual
form from diagnostic_context to diagnostic_text_output_format, where it
belongs.

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc
(json_output_format::on_begin_diagnostic): Delete.
(json_output_format::on_end_diagnostic): Rename to...
(json_output_format::on_report_diagnostic): ...this and add call
to pp_output_formatted_text.
(diagnostic_output_format_init_json): Drop unnecessary calls
to disable textual printing of CWEs, rules, and options.
* diagnostic-format-sarif.cc (sarif_builder::end_diagnostic):
Rename to...
(sarif_builder::on_report_diagnostic): ...this and add call to
pp_output_formatted_text.
(sarif_output_format::on_begin_diagnostic): Delete.
(sarif_output_format::on_end_diagnostic): Rename to...
(sarif_output_format::on_report_diagnostic): ...this and update
call to m_builder accordingly.
(diagnostic_output_format_init_sarif): Drop unnecessary calls
to disable textual printing of CWEs, rules, and options.
* diagnostic.cc (diagnostic_context::print_any_cwe): Convert to...
(diagnostic_text_output_format::print_any_cwe): ...this.
(diagnostic_context::print_any_rules): Convert to...
(diagnostic_text_output_format::print_any_rules): ...this.
(diagnostic_context::print_option_information): Convert to...
(diagnostic_text_output_format::print_option_information):
...this.
(diagnostic_context::report_diagnostic): Replace calls to the
output format's on_begin_diagnostic, to pp_output_formatted_text,
printing CWE, rules, option info, and the call to the format's
on_end_diagnostic with a call to the format's
on_report_diagnostic.
(diagnostic_text_output_format::on_begin_diagnostic): Delete.
(diagnostic_text_output_format::on_end_diagnostic): Delete.
(diagnostic_text_output_format::on_report_diagnostic): New vfunc,
which effectively does the on_begin_diagnostic, the call to
pp_output_formatted_text, the calls for printing CWE, rules,
option info, and the call to the diagnostic_finalizer.
* diagnostic.h (diagnostic_output_format::on_begin_diagnostic):
Delete.
(diagnostic_output_format::on_end_diagnostic): Delete.
(diagnostic_output_format::on_report_diagnostic): New.
(diagnostic_text_output_format::on_begin_diagnostic): Delete.
(diagnostic_text_output_format::on_end_diagnostic): Delete.
(diagnostic_text_output_format::on_report_diagnostic): New.
(class diagnostic_context): Add friend class
diagnostic_text_output_format.
(diagnostic_context::get_urlifier): New accessor.
(diagnostic_context::print_any_cwe): Move decl...
(diagnostic_text_output_format::print_any_cwe): ...to here.
(diagnostic_context::print_any_rules): Move decl...
(diagnostic_text_output_format::print_any_rules): ...to here.
(diagnostic_context::print_option_information): Move decl...
(diagnostic_text_output_format::print_option_information): ...to
here.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc  |  24 ++--
 gcc/diagnostic-format-sarif.cc |  34 ++
 gcc/diagnostic.cc  | 261 +
 gcc/diagnostic.h   |  28 +++--
 4 files changed, 171 insertions(+), 176

[gcc r15-3199] testsuite: add event IDs to multithreaded event plugin test

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:6a1c359e28442cb86ed40e0d432814b5807e7640

commit r15-3199-g6a1c359e28442cb86ed40e0d432814b5807e7640
Author: David Malcolm 
Date:   Mon Aug 26 12:24:22 2024 -0400

testsuite: add event IDs to multithreaded event plugin test

Add test coverage of "%@" in event messages in a multithreaded
execution path.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c:
Update expected output.
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py:
Likewise.
* 
gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c:
Likewise.
* gcc.dg/plugin/diagnostic_plugin_test_paths.c
(test_diagnostic_path::add_event_2): Return the id of the added
event.
(test_diagnostic_path::add_event_2_with_event_id): New.
(example_4): Add event IDs to the deadlock messages indicating
where the locks where acquired.

Signed-off-by: David Malcolm 

Diff:
---
 ...nostic-test-paths-multithreaded-inline-events.c |  4 +-
 .../diagnostic-test-paths-multithreaded-sarif.py   |  4 +-
 ...stic-test-paths-multithreaded-separate-events.c |  4 +-
 .../gcc.dg/plugin/diagnostic_plugin_test_paths.c   | 46 +++---
 4 files changed, 38 insertions(+), 20 deletions(-)

diff --git 
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c
 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c
index 333ef7359440..b306bcc1a0f3 100644
--- 
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c
+++ 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-inline-events.c
@@ -58,7 +58,7 @@ Thread: 'Thread 1'
|   NN |   acquire_lock_b ();
|  |   ^
|  |   |
-   |  |   (5) deadlocked due to waiting for lock b in thread 1...
+   |  |   (5) deadlocked due to waiting for lock b in thread 1 
(acquired by thread 2 at (4))...
|
 
 Thread: 'Thread 2'
@@ -67,6 +67,6 @@ Thread: 'Thread 2'
|   NN |   acquire_lock_a ();
|  |   ^
|  |   |
-   |  |   (6) ...whilst waiting for lock a in thread 2
+   |  |   (6) ...whilst waiting for lock a in thread 2 (acquired 
by thread 1 at (2))
|
  { dg-end-multiline-output "" } */
diff --git 
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py
index cff78aa8ac8e..cb00faf1532a 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py
@@ -95,7 +95,7 @@ def test_result(sarif):
 == "lock a is now held by thread 1"
 assert tf0['locations'][2]['executionOrder'] == 5
 assert tf0['locations'][2]['location']['message']['text'] \
-== "deadlocked due to waiting for lock b in thread 1..."
+== "deadlocked due to waiting for lock b in thread 1 (acquired by 
thread 2 at (4))..."
 
 assert len(tf1['locations']) == 3
 assert tf1['locations'][0]['executionOrder'] == 3
@@ -106,4 +106,4 @@ def test_result(sarif):
 == "lock b is now held by thread 2"
 assert tf1['locations'][2]['executionOrder'] == 6
 assert tf1['locations'][2]['location']['message']['text'] \
-== "...whilst waiting for lock a in thread 2"
+== "...whilst waiting for lock a in thread 2 (acquired by thread 1 at 
(2))"
diff --git 
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c
 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c
index 914918bb9e16..90464320b8e7 100644
--- 
a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c
+++ 
b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-multithreaded-separate-events.c
@@ -7,12 +7,12 @@ extern void acquire_lock_b(void);
 void foo ()
 { /* { dg-message "\\(1\\) entering 'foo'" } */
   acquire_lock_a (); /* { dg-message "\\(2\\) lock a is now held by thread 1" 
} */
-  acquire_lock_b (); /* { dg-message "\\(5\\) deadlocked due to waiting for 
lock b in thread 1\.\.\." } */
+  acquire_lock_b (); /* { dg-message "\\(5\\) deadlocked due to waiting for 
lock b in thread 1 \\(acquired by thread 2 at \\(4\\)\\)\.\.\." } */
 }
 
 void bar ()
 { /* { dg-message "\\(3\\) entering 'bar'" } */
   acquire_lock_b (); /* { dg-message "\\(4\\) lock b is now held by thread 2" 
} */
   acquire_lock_a (); /* { dg-warning "deadlock due to inconsistent lock 
acquisition order" } */
-  /* { dg-message "\\(6\\) \.\.\.whilst waiting for lock a in thread 2" "" { 
target *-*-* } .-1 } */
+  /* { dg-message "\\(6\\) \.\.\.whilst waiting for lock a in thread 2 
\\(acquired by 

[gcc r15-3197] pretty-print: fixes to selftests

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:276cc4324b9e8d97fb1018d7b78cc0ed7e77f902

commit r15-3197-g276cc4324b9e8d97fb1018d7b78cc0ed7e77f902
Author: David Malcolm 
Date:   Mon Aug 26 12:24:21 2024 -0400

pretty-print: fixes to selftests

Add selftest coverage for %{ and %} in pretty-print.cc

No functional change intended.

gcc/ChangeLog:
* pretty-print.cc (selftest::test_urls): Make static.
(selftest::test_urls_from_braces): New.
(selftest::test_null_urls): Make static.
(selftest::test_urlification): Likewise.
(selftest::pretty_print_cc_tests): Call test_urls_from_braces.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/pretty-print.cc | 39 +++
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 64713803dbe7..1d91da828212 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -3135,7 +3135,7 @@ test_prefixes_and_wrapping ()
 
 /* Verify that URL-printing works as expected.  */
 
-void
+static void
 test_urls ()
 {
   {
@@ -3169,9 +3169,40 @@ test_urls ()
   }
 }
 
+static void
+test_urls_from_braces ()
+{
+  {
+pretty_printer pp;
+pp.set_url_format (URL_FORMAT_NONE);
+pp_printf (&pp, "before %{text%} after",
+   "http://example.com";);
+ASSERT_STREQ ("before text after",
+ pp_formatted_text (&pp));
+  }
+
+  {
+pretty_printer pp;
+pp.set_url_format (URL_FORMAT_ST);
+pp_printf (&pp, "before %{text%} after",
+   "http://example.com";);
+ASSERT_STREQ ("before \33]8;;http://example.com\33\\text\33]8;;\33\\ 
after",
+ pp_formatted_text (&pp));
+  }
+
+  {
+pretty_printer pp;
+pp.set_url_format (URL_FORMAT_BEL);
+pp_printf (&pp, "before %{text%} after",
+   "http://example.com";);
+ASSERT_STREQ ("before \33]8;;http://example.com\atext\33]8;;\a after",
+ pp_formatted_text (&pp));
+  }
+}
+
 /* Verify that we gracefully reject null URLs.  */
 
-void
+static void
 test_null_urls ()
 {
   {
@@ -3221,8 +3252,7 @@ pp_printf_with_urlifier (pretty_printer *pp,
   va_end (ap);
 }
 
-
-void
+static void
 test_urlification ()
 {
   class test_urlifier : public urlifier
@@ -3424,6 +3454,7 @@ pretty_print_cc_tests ()
   test_pp_format ();
   test_prefixes_and_wrapping ();
   test_urls ();
+  test_urls_from_braces ();
   test_null_urls ();
   test_urlification ();
   test_utf8 ();


[gcc r15-3196] json.h: fix typo in comment

2024-08-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:b835710328847a8b1bc0c1258dd4a6d059988f79

commit r15-3196-gb835710328847a8b1bc0c1258dd4a6d059988f79
Author: David Malcolm 
Date:   Mon Aug 26 12:24:21 2024 -0400

json.h: fix typo in comment

gcc/ChangeLog:
* json.h: Fix typo in comment about missing INCLUDE_MEMORY.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/json.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/json.h b/gcc/json.h
index 21f71fe1c4ab..0bafa5fbea3f 100644
--- a/gcc/json.h
+++ b/gcc/json.h
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
json.h.  */
 
 #ifndef INCLUDE_MEMORY
-# error "You must define INCLUDE_MEMORY before including system.h to use 
make-unique.h"
+# error "You must define INCLUDE_MEMORY before including system.h to use 
json.h"
 #endif
 
 /* Implementation of JSON, a lightweight data-interchange format.


[gcc r15-2769] diagnostics: SARIF output: fix "executionSuccessful" §3.20.14 [PR116177]

2024-08-06 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:77f36e8016e11c051aa8264f3c43ab2c27aece55

commit r15-2769-g77f36e8016e11c051aa8264f3c43ab2c27aece55
Author: David Malcolm 
Date:   Tue Aug 6 18:24:45 2024 -0400

diagnostics: SARIF output: fix "executionSuccessful" §3.20.14 [PR116177]

Previously the invocation's "executionSuccessful" property (§3.20.14)
was only false if there was an ICE.

Update it so that it will also be false if we will exit with a non-zero
exit code (due to errors, Werror, and "sorry").

gcc/ChangeLog:
PR other/116177
* diagnostic-format-sarif.cc (sarif_invocation::prepare_to_flush):
If the diagnostics would lead to us exiting with a failure code,
then emit "executionSuccessful": False (SARIF v2.1.0 section
§3.20.14).
* diagnostic.cc (diagnostic_context::execution_failed_p): New.
* diagnostic.h (diagnostic_context::execution_failed_p): New decl.
* toplev.cc (toplev::main): Use it for determining returned value.

gcc/testsuite/ChangeLog:
PR other/116177
* gcc.dg/sarif-output/include-chain-2.c: Remove pruning of
"exit status is 1", as we expect this to exit with 0.
* gcc.dg/sarif-output/no-diagnostics.c: New test.
* gcc.dg/sarif-output/test-include-chain-1.py
(test_execution_unsuccessful): Add.
* gcc.dg/sarif-output/test-include-chain-2.py
(test_execution_successful): Add.
* gcc.dg/sarif-output/test-missing-semicolon.py
(test_execution_unsuccessful): Add.
* gcc.dg/sarif-output/test-no-diagnostics.py: New test.
* gcc.dg/sarif-output/test-werror.py: New test.
* gcc.dg/sarif-output/werror.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc |  2 ++
 gcc/diagnostic.cc  | 13 
 gcc/diagnostic.h   |  2 ++
 .../gcc.dg/sarif-output/include-chain-2.c  |  5 ---
 gcc/testsuite/gcc.dg/sarif-output/no-diagnostics.c | 13 
 .../gcc.dg/sarif-output/test-include-chain-1.py| 11 ++
 .../gcc.dg/sarif-output/test-include-chain-2.py| 11 ++
 .../gcc.dg/sarif-output/test-missing-semicolon.py  | 11 ++
 .../gcc.dg/sarif-output/test-no-diagnostics.py | 31 +
 gcc/testsuite/gcc.dg/sarif-output/test-werror.py   | 39 ++
 gcc/testsuite/gcc.dg/sarif-output/werror.c | 18 ++
 gcc/toplev.cc  |  2 +-
 12 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 7c2e96f4f746..963a185f6ced 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -811,6 +811,8 @@ void
 sarif_invocation::prepare_to_flush (diagnostic_context &context)
 {
   /* "executionSuccessful" property (SARIF v2.1.0 section 3.20.14).  */
+  if (context.execution_failed_p ())
+m_success = false;
   set_bool ("executionSuccessful", m_success);
 
   /* "toolExecutionNotifications" property (SARIF v2.1.0 section 3.20.21).  */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 71d2f44e40c8..3fc81ad47f56 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -399,6 +399,19 @@ diagnostic_context::finish ()
   m_original_argv = nullptr;
 }
 
+/* Return true if sufficiently severe diagnostics have been seen that
+   we ought to exit with a non-zero exit code.  */
+
+bool
+diagnostic_context::execution_failed_p () const
+{
+  /* Equivalent to (seen_error () || werrorcount), but on
+ this context, rather than global_dc.  */
+  return (m_diagnostic_count [DK_ERROR]
+ || m_diagnostic_count [DK_SORRY]
+ || m_diagnostic_count [DK_WERROR]);
+}
+
 void
 diagnostic_context::set_output_format (diagnostic_output_format *output_format)
 {
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 79386ccbf856..83180ded414d 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -392,6 +392,8 @@ public:
 
   void finish ();
 
+  bool execution_failed_p () const;
+
   void set_original_argv (unique_argv original_argv);
   const char * const *get_original_argv ()
   {
diff --git a/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c 
b/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c
index 3f984f48979b..a04b647d259e 100644
--- a/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c
+++ b/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c
@@ -27,11 +27,6 @@ PATH/include-chain-2.h:6:3: warning: double-'free' of 'ptr' 
[CWE-415] [-Wanalyze
 
 #include "include-chain-2.h"
 
-/* We expect a failing compile due to the errors, but the use of 
-   -fdiagnostics-format=sarif-file means there should be no output to stderr.
-   DejaGnu injects this message; ignore it:
-   { dg-prune-output "exit status is 1" } */
-
 /* Verify that some JSON wa

[gcc r15-2468] testsuite: split out parts of jit.dg/jit.exp into a new lib/valgrind.exp

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:64fbaf36a3834c394422cdf86985c7cc45179925

commit r15-2468-g64fbaf36a3834c394422cdf86985c7cc45179925
Author: David Malcolm 
Date:   Wed Jul 31 20:38:41 2024 -0400

testsuite: split out parts of jit.dg/jit.exp into a new lib/valgrind.exp

I want to reuse some of the support for valgrind in jit.exp
in my upcoming testsuite for https://gcc.gnu.org/wiki/libdiagnostics
so this patch splits that out into a valgrind.exp.

No functional change intended.

gcc/testsuite/ChangeLog:
* jit.dg/jit.exp: Add load_lib valgrind.exp.
(proc report_leak): Move to valgrind.exp, and add argument
leak_report_function rather than hardcoding xfail.
(parse_valgrind_logfile): Likewise.
(fixed_host_execute): Pass xfail to parse_valgrind_logfile.
* lib/valgrind.exp: New file, based on the above.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/testsuite/jit.dg/jit.exp   | 47 +++---
 gcc/testsuite/lib/valgrind.exp | 58 ++
 2 files changed, 62 insertions(+), 43 deletions(-)

diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 893ff5f6dd05..57b133b6d8c6 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -38,6 +38,7 @@ load_lib gcc.exp
 load_lib g++.exp
 load_lib dejagnu.exp
 load_lib target-supports-dg.exp
+load_lib valgrind.exp
 
 # Skip these tests for targets that don't support -lgccjit
 if { ![check_effective_target_lgccjit] } {
@@ -47,48 +48,6 @@ if { ![check_effective_target_lgccjit] } {
 # The default do-what keyword.
 set dg-do-what-default compile
 
-# Look for lines of the form:
-#   definitely lost: 11,316 bytes in 235 blocks
-#   indirectly lost: 352 bytes in 4 blocks
-# Ideally these would report zero bytes lost (which is a PASS);
-# for now, report non-zero leaks as XFAILs.
-proc report_leak {kind name logfile line} {
-set match [regexp "$kind lost: .*" $line result]
-if $match {
-   verbose "Saw \"$result\" within \"$line\"" 4
-   # Extract bytes and blocks.
-   # These can contain commas as well as numerals,
-   # but we only care about whether we have zero.
-   regexp "$kind lost: (.+) bytes in (.+) blocks" \
-   $result -> bytes blocks
-   verbose "bytes: '$bytes'" 4
-   verbose "blocks: '$blocks'" 4
-   if { $bytes == 0 } {
-   pass "$name: $logfile: $result"
-   } else {
-   xfail "$name: $logfile: $result"
-   }
-}
-}
-
-proc parse_valgrind_logfile {name logfile} {
-verbose "parse_valgrind_logfile: $logfile" 2
-if [catch {set f [open $logfile]}] {
-   fail "$name: unable to read $logfile"
-   return
-}
-
-while { [gets $f line] >= 0 } {
-   # Strip off the PID prefix e.g. ==7675==
-   set line [regsub "==\[0-9\]*== " $line ""]
-   verbose $line 2
-
-   report_leak "definitely" $name $logfile $line
-   report_leak "indirectly" $name $logfile $line
-}
-close $f
-}
-
 # Given WRES, the result from "wait", issue a PASS
 # if the spawnee exited cleanly, or a FAIL for various kinds of
 # unexpected exits.
@@ -327,7 +286,9 @@ proc fixed_host_execute {args} {
  
 if $run_under_valgrind {
upvar 2 name name
-   parse_valgrind_logfile $name $valgrind_logfile
+   # Use xfail to report leaks, as libgccjit isn't yet clean of
+   # memory leaks (PR jit/63854)
+   parse_valgrind_logfile $name $valgrind_logfile xfail
 }
 
 # force a close of the executable to be safe.
diff --git a/gcc/testsuite/lib/valgrind.exp b/gcc/testsuite/lib/valgrind.exp
new file mode 100644
index ..7d4f7ce51da1
--- /dev/null
+++ b/gcc/testsuite/lib/valgrind.exp
@@ -0,0 +1,58 @@
+# Copyright (C) 2014-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# Look for lines of the form:
+#   definitely lost: 11,316 bytes in 235 blocks
+#   indirectly lost: 352 bytes in 4 blocks
+# Report zero bytes lost as a a PASS.
+# Use LEAK_REPORT_FUNCTION to report non-zero bytes lost (either fail or xfail)
+
+proc report_leak {kind name logfile line leak_report_function} {
+set match [regexp "$kind lost: .*" $line result]
+if $match {
+   verbose "Saw \"$result\" within \"$line\"" 4
+   # Extract b

[gcc r15-2467] diagnostics: handle logical locations with NULL name

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:55982d1682921fdaf595c28f84f63d600558d150

commit r15-2467-g55982d1682921fdaf595c28f84f63d600558d150
Author: David Malcolm 
Date:   Wed Jul 31 20:38:41 2024 -0400

diagnostics: handle logical locations with NULL name

gcc/ChangeLog:
* diagnostic-path.cc
(thread_event_printer::print_swimlane_for_event_range): Gracefully
handle logical_location::get_name_for_path_output returning null.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/diagnostic-path.cc b/gcc/diagnostic-path.cc
index b497d89d0594..37751843f9ae 100644
--- a/gcc/diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -860,7 +860,8 @@ public:
 if (const logical_location *logical_loc = range->m_logical_loc)
   {
label_text name (logical_loc->get_name_for_path_output ());
-   pp_printf (pp, "%qs: ", name.get ());
+   if (name.get ())
+ pp_printf (pp, "%qs: ", name.get ());
   }
 if (range->m_start_idx == range->m_end_idx)
   pp_printf (pp, "event %i",


[gcc r15-2466] testsuite: drop unused import within sarif.py

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:5cb7adeaf5420c7a4e07f70ac09ee087b2e60654

commit r15-2466-g5cb7adeaf5420c7a4e07f70ac09ee087b2e60654
Author: David Malcolm 
Date:   Wed Jul 31 20:38:41 2024 -0400

testsuite: drop unused import within sarif.py

No functional change intended.

gcc/testsuite/ChangeLog:
* gcc.dg/sarif-output/sarif.py: Drop unused import of gzip.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/testsuite/gcc.dg/sarif-output/sarif.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/sarif-output/sarif.py 
b/gcc/testsuite/gcc.dg/sarif-output/sarif.py
index a34678791aca..7daf35b58190 100644
--- a/gcc/testsuite/gcc.dg/sarif-output/sarif.py
+++ b/gcc/testsuite/gcc.dg/sarif-output/sarif.py
@@ -1,4 +1,3 @@
-import gzip
 import json
 import os


[gcc r15-2465] diagnostics: SARIF output: capture unlabelled secondary locations

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a874b8301d9aa0421522d5aa11736f1510edb13a

commit r15-2465-ga874b8301d9aa0421522d5aa11736f1510edb13a
Author: David Malcolm 
Date:   Wed Jul 31 20:38:41 2024 -0400

diagnostics: SARIF output: capture unlabelled secondary locations

This patch extends
* the work done in r15-2291-gd7a688fc960f78 to capture labels
  on location ranges in rich_locations in SARIF form as
  "annotations" (§3.28.6)
* the work done in r15-2354-g4d1f71d49e396c to support
  related locations (§3.27.22 and §3.34)

so that all location ranges in a rich_location now get captured in
the SARIF output:
- those with a label are handled as before as "annotations" (§3.28.6),
  per r15-2291-gd7a688fc960f78
- those without a label now get captured, in the result's
  "relatedLocations" (§3.27.22)

For example, given:

  int missing_semicolon (void)
  {
return 42
  }

for which the textual output looks like this:

  PATH/missing-semicolon.c: In function 'missing_semicolon':
  PATH/missing-semicolon.c:9:12: error: expected ';' before '}' token
  9 |   return 42
|^
|;
 10 | }
| ~

with this patch the SARIF output now has this for the result's location:

   "relationships": [{"target": 0,
  "kinds": ["relevant"]}]}],

where the result gains a related location :

  "relatedLocations": [{"physicalLocation": {"artifactLocation": { 
[...snip...] },
 "region": {"startLine": 10,
"startColumn": 1,
"endColumn": 2},
 "contextRegion": {"startLine": 
10,
   "snippet": 
{"text": "}\n"}}},
"id": 0}]}]}]}

i.e. that the error also has the secondary location at the trailing
close brace which has the relationship "relevant" to the primary
location (at the suggested insertion point).

The patch also adds test coverage for the SARIF encoding of the fix-it hint.

gcc/ChangeLog:
* diagnostic-format-sarif.cc

(sarif_location_manager::worklist_item::unlabelled_secondary_location):
New enum value.
(sarif_location_manager::m_unlabelled_secondary_locations): New
field.
(sarif_location_manager::process_worklist_item): Handle unlabelled
secondary locations.
(sarif_builder::make_location_object): Generalize code to handle
ranges within a rich_location so as well as using annotations for
those with labels, we now add related locations for those without
labels.

gcc/testsuite/ChangeLog:
* gcc.dg/sarif-output/missing-semicolon.c: New test.
* gcc.dg/sarif-output/sarif.py (get_location_physical_region): New.
(get_location_snippet_text): New.
* gcc.dg/sarif-output/test-missing-semicolon.py: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 54 +--
 .../gcc.dg/sarif-output/missing-semicolon.c| 22 ++
 gcc/testsuite/gcc.dg/sarif-output/sarif.py |  3 +
 .../gcc.dg/sarif-output/test-missing-semicolon.py  | 79 ++
 4 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 2232883281bf..7c2e96f4f746 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -323,7 +323,11 @@ public:
 {
  /* Process a #include relationship where m_location_obj
was #included-d at m_where.  */
- included_from
+ included_from,
+
+ /* Process a location_t that was added as a secondary location
+   to a rich_location without a label.  */
+ unlabelled_secondary_location
 };
 
 worklist_item (sarif_location &location_obj,
@@ -369,6 +373,7 @@ private:
 
   std::list m_worklist;
   std::map m_included_from_locations;
+  std::map m_unlabelled_secondary_locations;
 };
 
 /* Subclass of sarif_object for SARIF "result" objects
@@ -559,6 +564,7 @@ public:
- diagnostic groups (see limitations below)
- logical locations (e.g. cfun)
- labelled ranges (as annotations)
+   - secondary ranges without labels (as related locations)
 
Known limitations:
- GCC supports one-deep nesting of diagnostics (via auto_diagnostic_group),
@@ -566,9 +572,6 @@ public:
  diagnostics (e.g. we ignore fix-it hints on them)
- although we capture command-line arguments (section 3.20.2), we don't
  yet capture response files.
-   - doesn't capture secondary locations within a rich_loca

[gcc r15-2464] diagnostics: SARIF output: eliminate some uses of "line_table" global

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:c990667996ff79cc5be6c898621811eeed4ad0a4

commit r15-2464-gc990667996ff79cc5be6c898621811eeed4ad0a4
Author: David Malcolm 
Date:   Wed Jul 31 20:38:40 2024 -0400

diagnostics: SARIF output: eliminate some uses of "line_table" global

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_builder::sarif_builder): Assert
that m_line_maps is nonnull.
(diagnostic_output_format_init_sarif_stderr): Add "line_maps"
param and pass to format ctor.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* diagnostic.cc (diagnostic_output_format_init): Pass "line_table"
as line_maps param to the above.
* diagnostic.h (diagnostic_output_format_init_sarif_stderr): Add
"line_maps" param.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 14 +++---
 gcc/diagnostic.cc  |  2 ++
 gcc/diagnostic.h   |  3 +++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 5900b9ea9b75..2232883281bf 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1302,6 +1302,8 @@ sarif_builder::sarif_builder (diagnostic_context &context,
   m_tabstop (context.m_tabstop),
   m_formatted (formatted)
 {
+  gcc_assert (m_line_maps);
+
   /* 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,
@@ -2988,13 +2990,15 @@ diagnostic_output_format_init_sarif (diagnostic_context 
&context)
 
 void
 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);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_stream_output_format (context,
-line_table,
+line_maps,
 main_input_filename_,
 formatted,
 stderr));
@@ -3005,14 +3009,16 @@ diagnostic_output_format_init_sarif_stderr 
(diagnostic_context &context,
 
 void
 diagnostic_output_format_init_sarif_file (diagnostic_context &context,
+ const line_maps *line_maps,
  const char *main_input_filename_,
  bool formatted,
  const char *base_file_name)
 {
+  gcc_assert (line_maps);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_file_output_format (context,
-  line_table,
+  line_maps,
   main_input_filename_,
   formatted,
   base_file_name));
@@ -3022,14 +3028,16 @@ diagnostic_output_format_init_sarif_file 
(diagnostic_context &context,
 
 void
 diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
+   const line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
FILE *stream)
 {
+  gcc_assert (line_maps);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_stream_output_format (context,
-line_table,
+line_maps,
 main_input_filename_,
 formatted,
 stream));
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 46cddfe94d1d..71d2f44e40c8 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -1857,12 +1857,14 @@ diagnostic_output_format_init (diagnostic_context 
&context,
 
 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
   diagnostic_output_format_init_sarif_stderr (context,
+ line_table,
  main_input_filename_,
  json_formatting);
   break;
 
 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
   diagnostic_output_format_init_sarif_file (context,
+  

[gcc r15-2463] diagnostics: SARIF output: tweak ASCII art in comment

2024-07-31 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:f829e627f40c95855df1c1b6a2903e360f37715b

commit r15-2463-gf829e627f40c95855df1c1b6a2903e360f37715b
Author: David Malcolm 
Date:   Wed Jul 31 20:38:40 2024 -0400

diagnostics: SARIF output: tweak ASCII art in comment

gcc/ChangeLog:
* diagnostic-format-sarif.cc: Tweak ASCII art in comment
to show edges for both directions in the digraph.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 84b3e651e462..5900b9ea9b75 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -290,17 +290,17 @@ private:
. |  have 'char'"|| | with type 'int'")|
. | in include-chain-1-2.h| | in include-chain-1-1.h   |
. +---+ +--+
-   .   |  |
-   .   | included-by  | included-by
-   .   V  V
+   .^ |^ |
+   .   includes | | included-by   includes | | included-by
+   .| V| V
.  ++++
.  |"id": 1 ||"id": 3 |
.  | #include "include-chain-1-2.h" || #include "include-chain-1-1.h" |
.  | in include-chain-1.h   || in include-chain-1.h   |
.  ++++
-   . |  |
-   . | included-by  | included-by
-   . V  V
+   .   ^ |   ^|
+   .  includes | | included-by  includes || included-by
+   .   | V   |V
.  ++
.  |"id": 4 |
.  | The  #include "include-chain-1.h"  |


[gcc r15-2354] diagnostics: SARIF output: capture #include information (PR 107941; §3.34)

2024-07-26 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:4d1f71d49e396cb879d43dc96dc591079af66bbe

commit r15-2354-g4d1f71d49e396cb879d43dc96dc591079af66bbe
Author: David Malcolm 
Date:   Fri Jul 26 20:37:31 2024 -0400

diagnostics: SARIF output: capture #include information (PR 107941; §3.34)

This patch extends our SARIF output to capture relationships between
locations within a result (§3.34).  In particular, this captures
chains of #includes relating to diagnostics and to events within
diagnostic paths.

For example, consider:

include-chain-1.c:

  #include "include-chain-1.h"

include-chain-1.h:

  /* First set of decls, which will be referenced in notes.  */
  #include "include-chain-1-1.h"

  /* Second set of decls, which will trigger the errors.  */
  #include "include-chain-1-2.h"

include-chain-1-1.h:

  int p;
  int q;

include-chain-1-1.h:

  char p;
  char q;

GCC's textual output emits:

  In file included from PATH/include-chain-1.h:5,
   from PATH/include-chain-1.c:30:
  PATH/include-chain-1-2.h:1:6: error: conflicting types for 'p'; have 
'char'
  1 | char p;
|  ^
  In file included from PATH/include-chain-1.h:2:
  PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type 
'int'
  1 | int p;
| ^
  PATH/include-chain-1-2.h:2:6: error: conflicting types for 'q'; have 
'char'
  2 | char q;
|  ^
  PATH/include-chain-1-1.h:2:5: note: previous declaration of 'q' with type 
'int'
  2 | int q;
| ^

With this patch, the SARIF output captures the include information for
the two results, so that e.g. result[0]'s location[0] has:

  "relationships": [{"target": 0,
 "kinds": ["isIncludedBy"]}],
  "id": 0

and the "note" in relatedLocations[0] has:

  "message": {"text": "previous declaration of 'q' with type 'int'"},
  "relationships": [{"target": 2,
"kinds": ["isIncludedBy"]}],
  "id": 2},

where these reference new locations within relatedLocations, such as this 
for
the "#include "include-chain-1-1.h" line in include-chain-1.h:

  {"physicalLocation": {"artifactLocation": {"uri": include-chain-1.h",
 "uriBaseId": "PWD"},
"region": {"startLine": 5},
"contextRegion": {"startLine": 5,
  "snippet": {"text": "#include 
\"include-chain-1-2.h\"\n"}}},
   "id": 1,
   "relationships": [{"target": 0,
  "kinds": ["includes"]},
 {"target": 4,
  "kinds": ["isIncludedBy"]}]},

effectively capturing the inclusion digraph in SARIF form:

 +---+ +--+
 |"id": 0| |"id": 2   |
 | error: "conflicting types for 'p';| | note: previous declaration of 'p'|
 |  have 'char'"|| | with type 'int'")|
 | in include-chain-1-2.h| | in include-chain-1-1.h   |
 +---+ +--+
   |  |
   | included-by  | included-by
   V  V
  ++++
  |"id": 1 ||"id": 3 |
  | #include "include-chain-1-2.h" || #include "include-chain-1-1.h" |
  | in include-chain-1.h   || in include-chain-1.h   |
  ++++
 |  |
 | included-by  | included-by
 V  V
  ++
  |"id": 4 |
  | The  #include "include-chain-1.h"  |
  | in include-chain-1.c   |
  ++

Locations only gain "id" fields if they need one, and the precise
numbering of the IDs within a result is an implementation detail (the
order in which references to the locations are made).

To test all this non-trivial JSON from DejaGnu I needed to adapt the
python testing code used by gcov, adding a new run-sarif-pytest based
on run-gcov-pytest.

gcc/ChangeLog:
PR middle-end/107941
* diagno

[gcc r15-2293] diagnostics: SARIF output: tweak output for UNKNOWN_LOCATION

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:142003df61b45ba8fcd17a68909a8ea0782a6679

commit r15-2293-g142003df61b45ba8fcd17a68909a8ea0782a6679
Author: David Malcolm 
Date:   Wed Jul 24 18:07:57 2024 -0400

diagnostics: SARIF output: tweak output for UNKNOWN_LOCATION

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_builder::make_locations_arr):
Don't add entirely empty location objects, such as for
UNKNOWN_LOCATION.
(test_sarif_diagnostic_context::test_sarif_diagnostic_context):
Add param "main_input_filename".
(selftest::test_simple_log): Provide above param.  Verify that
"locations" is empty.
(selftest::test_simple_log_2): New.
(selftest::diagnostic_format_sarif_cc_tests): Call it.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 123 ++---
 1 file changed, 115 insertions(+), 8 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 816f3210036e..1fc45c9b4b39 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1134,8 +1134,12 @@ sarif_builder::make_locations_arr (const diagnostic_info 
&diagnostic,
   if (auto client_data_hooks = m_context.get_client_data_hooks ())
 logical_loc = client_data_hooks->get_current_logical_location ();
 
-  locations_arr->append
-(make_location_object (*diagnostic.richloc, logical_loc, role));
+  auto location_obj
+= make_location_object (*diagnostic.richloc, logical_loc, role);
+  /* Don't add entirely empty location objects to the array.  */
+  if (!location_obj->is_empty ())
+locations_arr->append (std::move (location_obj));
+
   return locations_arr;
 }
 
@@ -2452,12 +2456,12 @@ namespace selftest {
 class test_sarif_diagnostic_context : public test_diagnostic_context
 {
 public:
-  test_sarif_diagnostic_context ()
+  test_sarif_diagnostic_context (const char *main_input_filename)
   {
 diagnostic_output_format_init_sarif (*this);
 
 m_format = new buffered_output_format (*this,
-  "MAIN_INPUT_FILENAME",
+  main_input_filename,
   true);
 set_output_format (m_format); // give ownership;
   }
@@ -2609,14 +2613,14 @@ test_make_location_object (const line_table_case &case_)
   }
 }
 
-/* Test of reporting a diagnostic to a diagnostic_context and
-   examining the generated sarif_log.
+/* Test of reporting a diagnostic at UNKNOWN_LOCATION to a
+   diagnostic_context and examining the generated sarif_log.
Verify various basic properties. */
 
 static void
 test_simple_log ()
 {
-  test_sarif_diagnostic_context dc;
+  test_sarif_diagnostic_context dc ("MAIN_INPUT_FILENAME");
 
   rich_location richloc (line_table, UNKNOWN_LOCATION);
   dc.report (DK_ERROR, richloc, nullptr, 0, "this is a test: %i", 42);
@@ -2719,7 +2723,109 @@ test_simple_log ()
   }
 
   // 3.27.12:
-  EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
+  auto locations
+   = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
+  ASSERT_EQ (locations->size (), 0);
+}
+  }
+}
+
+/* As above, but with a "real" location_t.  */
+
+static void
+test_simple_log_2 (const line_table_case &case_)
+{
+  auto_fix_quotes fix_quotes;
+
+  const char *const content
+/* 011
+   123456789012345.  */
+= "unsinged int i;\n";
+  diagnostic_show_locus_fixture f (case_, content);
+  location_t line_end = linemap_position_for_column (line_table, 31);
+
+  /* Don't attempt to run the tests if column data might be unavailable.  */
+  if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+return;
+
+  test_sarif_diagnostic_context dc (f.get_filename ());
+
+  const location_t typo_loc
+= make_location (linemap_position_for_column (line_table, 1),
+linemap_position_for_column (line_table, 1),
+linemap_position_for_column (line_table, 8));
+
+  rich_location richloc (line_table, typo_loc);
+  dc.report (DK_ERROR, richloc, nullptr, 0,
+"did you misspell %qs again?",
+"unsigned");
+
+  auto log_ptr = dc.flush_to_object ();
+
+  // 3.13 sarifLog:
+  auto log = log_ptr.get ();
+
+  auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
+  ASSERT_EQ (runs->size (), 1);
+
+  // 3.14 "run" object:
+  auto run = (*runs)[0];
+
+  {
+// 3.14.23:
+auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
+ASSERT_EQ (results->size (), 1);
+
+{
+  // 3.27 "result" object:
+  auto result = (*results)[0];
+  ASSERT_JSON_STRING_PROPERTY_EQ (result, "ruleId", "error");
+  ASSERT_JSON_STRING_PROPERTY_EQ (result, "level", "error"); // 3.27.10
+
+  {
+   // 3.27.11:
+   auto message
+ = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result, "message")

[gcc r15-2292] diagnostics: add selftests for SARIF output

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:68c7747dd29016d51e6f04e7fe1d8543423f093f

commit r15-2292-g68c7747dd29016d51e6f04e7fe1d8543423f093f
Author: David Malcolm 
Date:   Wed Jul 24 18:07:56 2024 -0400

diagnostics: add selftests for SARIF output

The existing DejaGnu-based tests for our SARIF output used regexes
to verify the JSON at the string level, which lets us test for
the presence of properties, but doesn't check the overall structure.

This patch uses the selftest framework to verify the structure of
the tree of JSON values for a log containing one diagnostic.

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_builder::flush_to_object):
New, using code moved from...
(sarif_builder::end_group): ...here.
(class selftest::test_sarif_diagnostic_context): New.
(selftest::test_simple_log): New.
(selftest::diagnostic_format_sarif_cc_tests): Call it.
* json.h (json::object::is_empty): New.
* selftest-diagnostic.cc (test_diagnostic_context::report): New.
* selftest-diagnostic.h (test_diagnostic_context::report): New
decl.
* selftest-json.cc (selftest::assert_json_string_eq): New.
(selftest::expect_json_object_with_string_property): New.
(selftest::assert_json_string_property_eq): New.
* selftest-json.h (selftest::assert_json_string_eq): New decl.
(ASSERT_JSON_STRING_EQ): New macro.
(selftest::expect_json_object_with_string_property): New decl.
(EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY): New macro.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 185 +++--
 gcc/json.h |   2 +
 gcc/selftest-diagnostic.cc |  14 
 gcc/selftest-diagnostic.h  |  10 +++
 gcc/selftest-json.cc   |  34 +++-
 gcc/selftest-json.h|  27 ++
 6 files changed, 264 insertions(+), 8 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index afb29eab5839..816f3210036e 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -380,6 +380,7 @@ public:
 const diagnostic_diagram &diagram);
   void end_group ();
 
+  std::unique_ptr flush_to_object ();
   void flush_to_file (FILE *outf);
 
   std::unique_ptr
@@ -860,6 +861,20 @@ sarif_builder::end_group ()
   m_cur_group_result = nullptr;
 }
 
+/* Create a top-level object, and add it to all the results
+   (and other entities) we've seen so far, moving ownership
+   to the object.  */
+
+std::unique_ptr
+sarif_builder::flush_to_object ()
+{
+  m_invocation_obj->prepare_to_flush (m_context);
+  std::unique_ptr top
+= make_top_level_object (std::move (m_invocation_obj),
+std::move (m_results_array));
+  return top;
+}
+
 /* Create a top-level object, and add it to all the results
(and other entities) we've seen so far.
 
@@ -868,12 +883,8 @@ sarif_builder::end_group ()
 void
 sarif_builder::flush_to_file (FILE *outf)
 {
-  m_invocation_obj->prepare_to_flush (m_context);
-  std::unique_ptr top
-= make_top_level_object (std::move (m_invocation_obj),
-std::move (m_results_array));
+  std::unique_ptr top = flush_to_object ();
   top->dump (outf, m_formatted);
-  m_invocation_obj = nullptr;
   fprintf (outf, "\n");
 }
 
@@ -2434,6 +2445,54 @@ diagnostic_output_format_init_sarif_stream 
(diagnostic_context &context,
 
 namespace selftest {
 
+/* A subclass of sarif_output_format for writing selftests.
+   The JSON output is cached internally, rather than written
+   out to a file.  */
+
+class test_sarif_diagnostic_context : public test_diagnostic_context
+{
+public:
+  test_sarif_diagnostic_context ()
+  {
+diagnostic_output_format_init_sarif (*this);
+
+m_format = new buffered_output_format (*this,
+  "MAIN_INPUT_FILENAME",
+  true);
+set_output_format (m_format); // give ownership;
+  }
+
+  std::unique_ptr flush_to_object ()
+  {
+return m_format->flush_to_object ();
+  }
+
+private:
+  class buffered_output_format : public sarif_output_format
+  {
+  public:
+buffered_output_format (diagnostic_context &context,
+   const char *main_input_filename_,
+   bool formatted)
+  : sarif_output_format (context, main_input_filename_, formatted)
+{
+}
+bool machine_readable_stderr_p () const final override
+{
+  return false;
+}
+std::unique_ptr flush_to_object ()
+{
+  return m_builder.flush_to_object ();
+}
+  };
+
+  buffered_output_format *m_format; // borrowed
+};
+
+/* Test making a sarif_location for a complex rich_location
+   with labels and escape-on-output.  */
+
 static vo

[gcc r15-2291] diagnostics: SARIF output: add "annotations" property (§3.28.6)

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d7a688fc960f78c62aacdc5acb8432873fed300e

commit r15-2291-gd7a688fc960f78c62aacdc5acb8432873fed300e
Author: David Malcolm 
Date:   Wed Jul 24 18:07:56 2024 -0400

diagnostics: SARIF output: add "annotations" property (§3.28.6)

This patch extends our SARIF output so that if a diagnostic has any
labelled source ranges, the "location" object gains an "annotations"
property capturing them (§3.28.6).

For example, given this textual output:

../../src/gcc/testsuite/gcc.dg/bad-binary-ops.c: In function ‘test_2’:
../../src/gcc/testsuite/gcc.dg/bad-binary-ops.c:31:11: error: invalid 
operands to binary + (have ‘struct s’ and ‘struct t’)
   30 |   return (some_function ()
  |   
  |   |
  |   struct s
   31 |   + some_other_function ());
  |   ^ ~~
  | |
  | struct t

the SARIF output gains this within the result's location[0]:

   "annotations": [{"startLine": 30,
"startColumn": 11,
"endColumn": 27,
"message": {"text": "struct s"}},
   {"startLine": 31,
"startColumn": 13,
"endColumn": 35,
"message": {"text": "struct t"}}]}]},

gcc/ChangeLog:
* diagnostic-format-sarif.cc
(sarif_builder::make_location_object): Add "annotations" property if
there are any labelled ranges (§3.28.6).
(selftest::test_make_location_object): Verify annotations are added
to location_obj.
* json.h (json::array::size): New.
(json::array::operator[]): New.
* selftest-json.cc
(selftest::expect_json_object_with_array_property): New.
* selftest-json.h
(selftest::expect_json_object_with_array_property): New decl.
(EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY): New macro.

gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-sarif-file-Wbidi-chars.c: Verify
that we have an "annotations" property for the labelled
ranges (§3.28.6).

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 70 +-
 gcc/json.h |  3 +
 gcc/selftest-json.cc   | 16 +
 gcc/selftest-json.h| 14 +
 .../diagnostic-format-sarif-file-Wbidi-chars.c |  8 +++
 5 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 775d01f75744..afb29eab5839 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -345,6 +345,7 @@ public:
- CWE metadata
- diagnostic groups (see limitations below)
- logical locations (e.g. cfun)
+   - labelled ranges (as annotations)
 
Known limitations:
- GCC supports one-deep nesting of diagnostics (via auto_diagnostic_group),
@@ -361,7 +362,6 @@ public:
  ("artifact.hashes" property (SARIF v2.1.0 section 3.24.11).
- doesn't capture the "analysisTarget" property
  (SARIF v2.1.0 section 3.27.13).
-   - doesn't capture labelled ranges
- doesn't capture -Werror cleanly
- doesn't capture inlining information (can SARIF handle this?)
- doesn't capture macro expansion information (can SARIF handle this?).  */
@@ -1210,6 +1210,38 @@ sarif_builder::make_location_object (const rich_location 
&rich_loc,
   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
   set_any_logical_locs_arr (*location_obj, logical_loc);
 
+  /* "annotations" property (SARIF v2.1.0 section 3.28.6).  */
+  {
+/* Create annotations for any labelled ranges.  */
+std::unique_ptr annotations_arr = nullptr;
+for (unsigned int i = 0; i < rich_loc.get_num_locations (); i++)
+  {
+   const location_range *range = rich_loc.get_range (i);
+   if (const range_label *label = range->m_label)
+ {
+   label_text text = label->get_text (i);
+   if (text.get ())
+ {
+   location_t range_loc = rich_loc.get_loc (i);
+   auto region
+ = maybe_make_region_object (range_loc,
+ rich_loc.get_column_override ());
+   if (region)
+ {
+   if (!annotations_arr)
+ annotations_arr = ::make_unique ();
+   region->set
+ ("message", make_message_object (text.get ()));
+   annotations_arr->append (std::move (region));
+ }
+ }
+ }
+  }
+if (annotations_arr)
+  location_obj->set ("annotations",
+ 

[gcc r15-2289] diagnostics: SARIF output: add "arguments" property (§3.20.2)

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:29ee588129bf07d3adb62b6c2c189ba932c00ff4

commit r15-2289-g29ee588129bf07d3adb62b6c2c189ba932c00ff4
Author: David Malcolm 
Date:   Wed Jul 24 18:07:55 2024 -0400

diagnostics: SARIF output: add "arguments" property (§3.20.2)

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_invocation::sarif_invocation):
Add "original_argv" param and use it to populate "arguments"
property (§3.20.2).
(sarif_builder::sarif_builder): Pass argv to m_invocation_obj's
ctor.
* diagnostic.cc (diagnostic_context::initialize): Initialize
m_original_argv.
(diagnostic_context::finish): Clean up m_original_argv.
(diagnostic_context::set_original_argv): New.
* diagnostic.h: Include "unique-argv.h".
(diagnostic_context::set_original_argv): New decl.
(diagnostic_context::get_original_argv): New decl.
(diagnostic_context::m_original_argv): New field.
* toplev.cc: Include "unique-argv.h".
(general_init): Add "original_argv" param and move it to global_dc.
(toplev::main): Stash a copy of the original argv before expansion,
and pass it to general_init for use by SARIF output.
* unique-argv.h: New file.

gcc/jit/ChangeLog:
* jit-playback.cc (jit::playback_context::compile) Add a trailing
null to argvec.

gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-sarif-file-1.c: Verify that we
have an "arguments" property (§3.20.2).

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 25 +---
 gcc/diagnostic.cc  | 17 ++
 gcc/diagnostic.h   | 10 
 gcc/jit/jit-playback.cc|  6 +-
 .../c-c++-common/diagnostic-format-sarif-file-1.c  |  5 ++
 gcc/toplev.cc  | 13 -
 gcc/unique-argv.h  | 67 ++
 7 files changed, 132 insertions(+), 11 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 9be84fb268a5..6c7216651627 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -125,7 +125,8 @@ class sarif_tool_component : public sarif_object {};
 class sarif_invocation : public sarif_object
 {
 public:
-  sarif_invocation (sarif_builder &builder);
+  sarif_invocation (sarif_builder &builder,
+   const char * const *original_argv);
 
   void add_notification_for_ice (diagnostic_context &context,
 const diagnostic_info &diagnostic,
@@ -329,10 +330,8 @@ public:
- GCC supports one-deep nesting of diagnostics (via auto_diagnostic_group),
  but we only capture location and message information from such nested
  diagnostics (e.g. we ignore fix-it hints on them)
-   - doesn't yet capture command-line arguments: would be run.invocations
- property (SARIF v2.1.0 section 3.14.11), as invocation objects
- (SARIF v2.1.0 section 3.20), but we'd want to capture the arguments to
- toplev::main, and the response files.
+   - although we capture command-line arguments (section 3.20.2), we don't
+ yet capture response files.
- doesn't capture secondary locations within a rich_location
  (perhaps we should use the "relatedLocations" property: SARIF v2.1.0
  section 3.27.22)
@@ -513,10 +512,20 @@ sarif_object::get_or_create_properties ()
 
 /* class sarif_invocation : public sarif_object.  */
 
-sarif_invocation::sarif_invocation (sarif_builder &builder)
+sarif_invocation::sarif_invocation (sarif_builder &builder,
+   const char * const *original_argv)
 : m_notifications_arr (::make_unique ()),
   m_success (true)
 {
+  // "arguments" property (SARIF v2.1.0 section 3.20.2)
+  if (original_argv)
+{
+  auto arguments_arr = ::make_unique ();
+  for (size_t i = 0; original_argv[i]; ++i)
+   arguments_arr->append_string (original_argv[i]);
+  set ("arguments", std::move (arguments_arr));
+}
+
   // "workingDirectory" property (SARIF v2.1.0 section 3.20.19)
   if (const char *pwd = getpwd ())
 set ("workingDirectory",
@@ -752,7 +761,9 @@ sarif_builder::sarif_builder (diagnostic_context &context,
  const char *main_input_filename_,
  bool formatted)
 : m_context (context),
-  m_invocation_obj (::make_unique (*this)),
+  m_invocation_obj
+(::make_unique (*this,
+ context.get_original_argv ())),
   m_results_array (new json::array ()),
   m_cur_group_result (nullptr),
   m_seen_any_relative_paths (false),
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index aa8afd521fa2..c70c394f7ccd 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/di

[gcc r15-2290] diagnostics: SARIF output: add "{start,end}TimeUtc" properties (§§3.20.7-8)

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:b4693ce3a0565bb75d0d5698f2ce2ffc53d1ff84

commit r15-2290-gb4693ce3a0565bb75d0d5698f2ce2ffc53d1ff84
Author: David Malcolm 
Date:   Wed Jul 24 18:07:55 2024 -0400

diagnostics: SARIF output: add "{start,end}TimeUtc" properties (§§3.20.7-8)

gcc/ChangeLog:
* diagnostic-format-sarif.cc
(make_date_time_string_for_current_time): New.
(sarif_invocation::sarif_invocation): Set "startTimeUtc"
property (§3.20.7).
(sarif_invocation::prepare_to_flush): Set "endTimeUtc"
property (§3.20.8).

gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-sarif-file-1.c: Verify that we have
"startTimeUtc" and "endTimeUtc" properties of the correct form.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 28 ++
 .../c-c++-common/diagnostic-format-sarif-file-1.c  |  5 
 2 files changed, 33 insertions(+)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 6c7216651627..775d01f75744 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -119,6 +119,26 @@ class sarif_tool : public sarif_object {};
 
 class sarif_tool_component : public sarif_object {};
 
+/* Make a JSON string for the current date and time.
+   See SARIF v2.1.0 section 3.9 "Date/time properties".
+   Given that we don't run at the very beginning/end of the
+   process, it doesn't make sense to be more accurate than
+   the current second.  */
+
+static std::unique_ptr
+make_date_time_string_for_current_time ()
+{
+  time_t t = time (nullptr);
+  struct tm *tm = gmtime (&t);
+  char buf[256];
+  snprintf (buf, sizeof (buf) - 1,
+   ("%04i-%02i-%02iT"
+"%02i:%02i:%02iZ"),
+   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+   tm->tm_hour, tm->tm_min, tm->tm_sec);
+  return ::make_unique (buf);
+}
+
 /* Subclass of sarif_object for SARIF "invocation" objects
(SARIF v2.1.0 section 3.20).  */
 
@@ -530,6 +550,10 @@ sarif_invocation::sarif_invocation (sarif_builder &builder,
   if (const char *pwd = getpwd ())
 set ("workingDirectory",
  builder.make_artifact_location_object (pwd));
+
+  // "startTimeUtc" property (SARIF v2.1.0 section 3.20.7)
+  set ("startTimeUtc",
+make_date_time_string_for_current_time ());
 }
 
 /* Handle an internal compiler error DIAGNOSTIC occurring on CONTEXT.
@@ -559,6 +583,10 @@ sarif_invocation::prepare_to_flush (diagnostic_context 
&context)
  this object (SARIF v2.1.0 section 3.8) e.g. for recording time vars.  */
   if (auto client_data_hooks = context.get_client_data_hooks ())
 client_data_hooks->add_sarif_invocation_properties (*this);
+
+  // "endTimeUtc" property (SARIF v2.1.0 section 3.20.8);
+  set ("endTimeUtc",
+make_date_time_string_for_current_time ());
 }
 
 /* class sarif_artifact : public sarif_object.  */
diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c 
b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
index c9ad0d238195..fdf602eaae7b 100644
--- a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
+++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
@@ -37,6 +37,11 @@
3.20.2 invocation "arguments" property:
{ dg-final { scan-sarif-file {"arguments": \[} } }
 
+   Expect "startTimeUtc" and "endTimeUtc" properties of the form
+   "-nn-nnTnn:nn:nnZ" (3.20.7 and 3.20.8):
+   { dg-final { scan-sarif-file {"startTimeUtc": 
"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z"} 
} }
+   { dg-final { scan-sarif-file {"endTimeUtc": 
"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z"} 
} }
+
{ dg-final { scan-sarif-file {"workingDirectory": } } }
{ dg-final { scan-sarif-file "\"toolExecutionNotifications\": \\\[\\\]" 
} }
{ dg-final { scan-sarif-file "\"executionSuccessful\": true" } }


[gcc r15-2288] diagnostics: SARIF output: add "workingDirectory" property (§3.20.19)

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:8c07814f46ca617ccc5f9fbf2b220dc41ae228c2

commit r15-2288-g8c07814f46ca617ccc5f9fbf2b220dc41ae228c2
Author: David Malcolm 
Date:   Wed Jul 24 18:07:55 2024 -0400

diagnostics: SARIF output: add "workingDirectory" property (§3.20.19)

gcc/ChangeLog:
* diagnostic-format-sarif.cc
(sarif_builder::make_artifact_location_object): Make public.
(sarif_invocation::sarif_invocation): Add param "builder".
Use it to potentially populate the "workingDirectory" property
with the result of pwd (§3.20.19).
(sarif_builder::sarif_builder): Pass *this to m_invocation_obj's
ctor.

gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-sarif-file-1.c: Verify that we have
a "workingDirectory" property.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc| 15 ++-
 .../c-c++-common/diagnostic-format-sarif-file-1.c |  1 +
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 847e1eb9bdfc..9be84fb268a5 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -125,7 +125,7 @@ class sarif_tool_component : public sarif_object {};
 class sarif_invocation : public sarif_object
 {
 public:
-  sarif_invocation ();
+  sarif_invocation (sarif_builder &builder);
 
   void add_notification_for_ice (diagnostic_context &context,
 const diagnostic_info &diagnostic,
@@ -378,6 +378,9 @@ public:
   std::unique_ptr
   maybe_make_artifact_content_object (const char *filename) const;
 
+  std::unique_ptr
+  make_artifact_location_object (const char *filename);
+
 private:
   std::unique_ptr
   make_result_object (diagnostic_context &context,
@@ -404,8 +407,6 @@ private:
   std::unique_ptr
   make_artifact_location_object (location_t loc);
   std::unique_ptr
-  make_artifact_location_object (const char *filename);
-  std::unique_ptr
   make_artifact_location_object_for_pwd () const;
   std::unique_ptr
   maybe_make_region_object (location_t loc,
@@ -512,10 +513,14 @@ sarif_object::get_or_create_properties ()
 
 /* class sarif_invocation : public sarif_object.  */
 
-sarif_invocation::sarif_invocation ()
+sarif_invocation::sarif_invocation (sarif_builder &builder)
 : m_notifications_arr (::make_unique ()),
   m_success (true)
 {
+  // "workingDirectory" property (SARIF v2.1.0 section 3.20.19)
+  if (const char *pwd = getpwd ())
+set ("workingDirectory",
+ builder.make_artifact_location_object (pwd));
 }
 
 /* Handle an internal compiler error DIAGNOSTIC occurring on CONTEXT.
@@ -747,7 +752,7 @@ sarif_builder::sarif_builder (diagnostic_context &context,
  const char *main_input_filename_,
  bool formatted)
 : m_context (context),
-  m_invocation_obj (::make_unique ()),
+  m_invocation_obj (::make_unique (*this)),
   m_results_array (new json::array ()),
   m_cur_group_result (nullptr),
   m_seen_any_relative_paths (false),
diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c 
b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
index 50375465483d..0a3778323792 100644
--- a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
+++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
@@ -32,6 +32,7 @@
  { dg-final { scan-sarif-file "\"informationUri\": \"" } }
 
  { dg-final { scan-sarif-file "\"invocations\": \\\[" } }
+   { dg-final { scan-sarif-file {"workingDirectory": } } }
{ dg-final { scan-sarif-file "\"toolExecutionNotifications\": \\\[\\\]" 
} }
{ dg-final { scan-sarif-file "\"executionSuccessful\": true" } }


[gcc r15-2287] diagnostics: SARIF output: potentially add escaped renderings of source (§3.3.4)

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:148066bd0560b5136692991dacba15c9f21caf96

commit r15-2287-g148066bd0560b5136692991dacba15c9f21caf96
Author: David Malcolm 
Date:   Wed Jul 24 18:07:54 2024 -0400

diagnostics: SARIF output: potentially add escaped renderings of source 
(§3.3.4)

This patch adds support to our SARIF output for cases where
rich_loc.escape_on_output_p () is true, such as for -Wbidi-chars.

In such cases, the pertinent SARIF "location" object gains a property
bag with property "gcc/escapeNonAscii": true, and the "artifactContent"
within the location's physical location's snippet" gains a "rendered"
property (§3.3.4) that escapes non-ASCII text in the snippet, such as:

"rendered": {"text":

where "text" has a string value such as (for a "trojan source" attack):

  "9 | /* } if (isAdmin)  begin admins 
only */\n"
  "  |      
 ^\n"
  "  |   |   |  
 |\n"
  "  |   |   |  
 end of bidirectional context\n"
  "  |   U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT 
ISOLATE)\n"

where the escaping is affected by -fdiagnostics-escape-format=; with
-fdiagnostics-escape-format=bytes, the rendered text of the above is:

  "9 | /*<80> } <81>if (isAdmin)<81> 
<81> begin admins only */\n"
  "  |   
^\n"
  "  |   |   |  
 |\n"
  "  |   U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 
(LEFT-TO-RIGHT ISOLATE)  end of bidirectional context\n"

The patch also refactors/adds enough selftest machinery to be able to
test the snippet generation from within the selftest framework, rather
than just within DejaGnu (where the regex-based testing isn't
sophisticated enough to verify such properties as the above).

gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add selftest-json.o.
* diagnostic-format-sarif.cc: Include "selftest.h",
"selftest-diagnostic.h", "selftest-diagnostic-show-locus.h",
"selftest-json.h", and "text-range-label.h".
(class content_renderer): New.
(sarif_builder::m_rules_arr): Convert to std::unique_ptr.
(sarif_builder::make_location_object): Add class
escape_nonascii_renderer.  If rich_loc.escape_on_output_p (),
pass a nonnull escape_nonascii_renderer to
maybe_make_physical_location_object as its snippet_renderer, and
add a property bag property "gcc/escapeNonAscii" to the SARIF
location object.  For other overloads of make_location_object,
pass nullptr for the snippet_renderer.
(sarif_builder::maybe_make_region_object_for_context): Add
"snippet_renderer" param and pass it to
maybe_make_artifact_content_object.
(sarif_builder::make_tool_object): Drop "const".
(sarif_builder::make_driver_tool_component_object): Likewise.
Use typesafe unique_ptr variant of object::set for setting "rules"
property on driver_obj.
(sarif_builder::maybe_make_artifact_content_object): Add param "r"
and use it to potentially set the "rendered" property (§3.3.4).
(selftest::test_make_location_object): New.
(selftest::diagnostic_format_sarif_cc_tests): New.
* diagnostic-show-locus.cc: Include "text-range-label.h" and
"selftest-diagnostic-show-locus.h".

(selftests::diagnostic_show_locus_fixture::diagnostic_show_locus_fixture):
New.
(selftests::test_layout_x_offset_display_utf8): Use
diagnostic_show_locus_fixture to simplify and consolidate setup
code.
(selftests::test_diagnostic_show_locus_one_liner): Likewise.
(selftests::test_one_liner_colorized_utf8): Likewise.
(selftests::test_diagnostic_show_locus_one_liner_utf8): Likewise.
* gcc-rich-location.h (class text_range_label): Move to new file
text-range-label.h.
* selftest-diagnostic-show-locus.h: New file, based on material in
diagnostic-show-locus.cc.
* selftest-json.cc: New file.
* selftest-json.h: New file.
* selftest-run-tests.cc (selftest::run_tests): Call
selftest::diagnostic_format_sarif_cc_tests.
* selftest.h (selftest::diagnostic_format_sarif_cc_tests): New decl.

gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-sarif-file-Wbidi-chars.c: Verify
that we have a property bag with property "gcc/escapeNonAsc

[gcc r15-2286] diagnostics: JSON output: use std::unique_ptr throughout

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:ae4f4f767efc156aac4b2e7a874648fdc60307f3

commit r15-2286-gae4f4f767efc156aac4b2e7a874648fdc60307f3
Author: David Malcolm 
Date:   Wed Jul 24 18:07:54 2024 -0400

diagnostics: JSON output: use std::unique_ptr throughout

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc: Include "make-unique.h".
(json_output_format::m_toplevel_array): Convert to
std::unique_ptr.
(json_output_format::json_output_format): Update accordingly.
(json_output_format::~json_output_format): Remove manual
"delete" of field.
(json_from_expanded_location): Convert return type to
std::unique_ptr.
(json_from_location_range): Likewise.  Use nullptr rather than
NULL.
(json_from_fixit_hint): Convert return type to std::unique_ptr.
(json_from_metadata): Likewise.
(make_json_for_path): Likewise.
(json_output_format::on_end_diagnostic): Use std::unique_ptr
throughout.
(json_file_output_format::~json_file_output_format): Use nullptr.
(selftest::test_unknown_location): Update to use std::unique_ptr.
(selftest::test_bad_endpoints): Likewise.  Replace NULL with
nullptr.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc | 122 +-
 1 file changed, 62 insertions(+), 60 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 55ba39e0c532..b78cb92cfd7a 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "json.h"
 #include "selftest.h"
 #include "logical-location.h"
+#include "make-unique.h"
 
 /* Subclass of diagnostic_output_format for JSON output.  */
 
@@ -62,7 +63,7 @@ protected:
   json_output_format (diagnostic_context &context,
  bool formatted)
   : diagnostic_output_format (context),
-m_toplevel_array (new json::array ()),
+m_toplevel_array (::make_unique ()),
 m_cur_group (nullptr),
 m_cur_children_array (nullptr),
 m_formatted (formatted)
@@ -75,31 +76,30 @@ protected:
   {
 m_toplevel_array->dump (outf, m_formatted);
 fprintf (outf, "\n");
-delete m_toplevel_array;
 m_toplevel_array = nullptr;
   }
 
 private:
   /* The top-level JSON array of pending diagnostics.  */
-  json::array *m_toplevel_array;
+  std::unique_ptr m_toplevel_array;
 
   /* The JSON object for the current diagnostic group.  */
-  json::object *m_cur_group;
+  json::object *m_cur_group; // borrowed
 
   /* The JSON array for the "children" array within the current diagnostic
  group.  */
-  json::array *m_cur_children_array;
+  json::array *m_cur_children_array; // borrowed
 
   bool m_formatted;
 };
 
 /* Generate a JSON object for LOC.  */
 
-static json::value *
+static std::unique_ptr
 json_from_expanded_location (diagnostic_context &context, location_t loc)
 {
   expanded_location exploc = expand_location (loc);
-  json::object *result = new json::object ();
+  std::unique_ptr result = ::make_unique  ();
   if (exploc.file)
 result->set_string ("file", exploc.file);
   result->set_integer ("line", exploc.line);
@@ -130,26 +130,29 @@ json_from_expanded_location (diagnostic_context &context, 
location_t loc)
 
 /* Generate a JSON object for LOC_RANGE.  */
 
-static json::object *
+static std::unique_ptr
 json_from_location_range (diagnostic_context &context,
  const location_range *loc_range, unsigned range_idx)
 {
   location_t caret_loc = get_pure_location (loc_range->m_loc);
 
   if (caret_loc == UNKNOWN_LOCATION)
-return NULL;
+return nullptr;
 
   location_t start_loc = get_start (loc_range->m_loc);
   location_t finish_loc = get_finish (loc_range->m_loc);
 
-  json::object *result = new json::object ();
-  result->set ("caret", json_from_expanded_location (context, caret_loc));
+  std::unique_ptr result = ::make_unique  ();
+  result->set ("caret",
+  json_from_expanded_location (context, caret_loc));
   if (start_loc != caret_loc
   && start_loc != UNKNOWN_LOCATION)
-result->set ("start", json_from_expanded_location (context, start_loc));
+result->set ("start",
+json_from_expanded_location (context, start_loc));
   if (finish_loc != caret_loc
   && finish_loc != UNKNOWN_LOCATION)
-result->set ("finish", json_from_expanded_location (context, finish_loc));
+result->set ("finish",
+json_from_expanded_location (context, finish_loc));
 
   if (loc_range->m_label)
 {
@@ -163,15 +166,17 @@ json_from_location_range (diagnostic_context &context,
 
 /* Generate a JSON object for HINT.  */
 
-static json::object *
+static std::unique_ptr
 json_from_fixit_hint (diagnostic_context &context, const fixit_hint

[gcc r15-2285] diagnostics: SARIF output: use std::unique_ptr throughout

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:ee2dad94acc88c2ea78a91b7eb8914e7c1bae829

commit r15-2285-gee2dad94acc88c2ea78a91b7eb8914e7c1bae829
Author: David Malcolm 
Date:   Wed Jul 24 18:07:53 2024 -0400

diagnostics: SARIF output: use std::unique_ptr throughout

No functional change intended.

gcc/analyzer/ChangeLog:
* checker-event.cc (maybe_add_sarif_properties): Update setting
of "original_fndecl" to use typesafe unique_ptr variant of
json::object::set.

gcc/ChangeLog:
* diagnostic-format-sarif.cc: Include "make-unique.h".  Convert
raw pointers to std::unique_ptr throughout to indicate ownership,
adding comments in the few places where pointers are borrowed.
Use typesafe unique_ptr variants of json::object::set and
json::array::append throughout to make types of properties more
explicit, whilst using "auto" to reduce typing.
Use "nullptr" rather than "NULL" throughout.
* diagnostic-format-sarif.h (make_sarif_logical_location_object):
Use std::unique_ptr for return type.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/checker-event.cc  |   5 +-
 gcc/diagnostic-format-sarif.cc | 667 -
 gcc/diagnostic-format-sarif.h  |   2 +-
 3 files changed, 337 insertions(+), 337 deletions(-)

diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 593f364e1d66..2f1438c983a5 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -161,8 +161,9 @@ maybe_add_sarif_properties (sarif_object 
&thread_flow_loc_obj) const
   if (m_original_fndecl != m_effective_fndecl)
 {
   tree_logical_location logical_loc (m_original_fndecl);
-  props.set (PROPERTY_PREFIX "original_fndecl",
-make_sarif_logical_location_object (logical_loc));
+  props.set
+   (PROPERTY_PREFIX "original_fndecl",
+make_sarif_logical_location_object (logical_loc));
 }
   if (m_original_depth != m_effective_depth)
 props.set_integer (PROPERTY_PREFIX "original_depth", m_original_depth);
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 6aba81c6ac9b..6f61d89363f2 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-format-sarif.h"
 #include "ordered-hash-map.h"
 #include "sbitmap.h"
+#include "make-unique.h"
 
 /* Forward decls.  */
 class sarif_builder;
@@ -125,7 +126,7 @@ public:
   void prepare_to_flush (diagnostic_context &context);
 
 private:
-  json::array *m_notifications_arr;
+  std::unique_ptr m_notifications_arr;
   bool m_success;
 };
 
@@ -180,7 +181,7 @@ private:
 class sarif_result : public sarif_object
 {
 public:
-  sarif_result () : m_related_locations_arr (NULL) {}
+  sarif_result () : m_related_locations_arr (nullptr) {}
 
   void
   on_nested_diagnostic (diagnostic_context &context,
@@ -193,9 +194,9 @@ public:
 
 private:
   void
-  add_related_location (sarif_location *location_obj);
+  add_related_location (std::unique_ptr location_obj);
 
-  json::array *m_related_locations_arr;
+  json::array *m_related_locations_arr; // borrowed
 };
 
 /* Subclass of sarif_object for SARIF "location" objects
@@ -226,10 +227,12 @@ class sarif_thread_flow : public sarif_object
 public:
   sarif_thread_flow (const diagnostic_thread &thread);
 
-  void add_location (sarif_thread_flow_location *thread_flow_loc_obj);
+  void
+  add_location
+(std::unique_ptr thread_flow_loc_obj);
 
 private:
-  json::array *m_locations_arr;
+  json::array *m_locations_arr; // borrowed
 };
 
 /* Subclass of sarif_object for SARIF "threadFlowLocation" objects
@@ -340,80 +343,81 @@ public:
 
   void flush_to_file (FILE *outf);
 
-  json::array *make_locations_arr (const diagnostic_info &diagnostic,
-  enum diagnostic_artifact_role role);
-  sarif_location *
+  std::unique_ptr
+  make_locations_arr (const diagnostic_info &diagnostic,
+ enum diagnostic_artifact_role role);
+  std::unique_ptr
   make_location_object (const rich_location &rich_loc,
const logical_location *logical_loc,
enum diagnostic_artifact_role role);
-  sarif_message *
+  std::unique_ptr
   make_message_object (const char *msg) const;
-  sarif_message *
+  std::unique_ptr
   make_message_object_for_diagram (diagnostic_context &context,
   const diagnostic_diagram &diagram);
-  sarif_artifact_content *
+  std::unique_ptr
   maybe_make_artifact_content_object (const char *filename) const;
 
 private:
-  sarif_result *
+  std::unique_ptr
   make_result_object (diagnostic_context &context,
  const diagnostic_info &diagnostic,
  diagnostic_t orig_diag_kind);
   void
-  set_any_logical_locs_a

[gcc r15-2284] json: support std::unique_ptr in array::append and object::set

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:2486234b5ae0d71ca7bbdc6e216b4707cd5bef15

commit r15-2284-g2486234b5ae0d71ca7bbdc6e216b4707cd5bef15
Author: David Malcolm 
Date:   Wed Jul 24 18:07:53 2024 -0400

json: support std::unique_ptr in array::append and object::set

This patch uses templates to add overloads of json::array::append and
json::object::set taking std::unique_ptr where T is a subclass of
json::value.

Doing so makes it much easier to track memory ownership and enforce
schema validity when constructing non-trivial JSON; using the wrong
kind of JSON value leads to compile-time errors like the following:

error: cannot convert ‘unique_ptr’ to ‘unique_ptr’
  629 |   location_obj->set ("message", std::move (message_obj));
  |~~^
  |  |
  |  
unique_ptr

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc: Define INCLUDE_MEMORY.
* diagnostic-format-sarif.cc: Likewise.
* dumpfile.cc: Likewise.
* gcov.cc: Likewise.
* json.cc: Likewise.  Include "make-unique.h".
(selftest::test_formatting): Exercise overloads of
array::append and object::set that use unique_ptr.
* json.h: Require INCLUDE_MEMORY to have been defined.
(json::object::set): Add a template to add a family of overloads
taking a std::unique_ptr
(json::array::append): Likewise.
* optinfo-emit-json.cc: Define INCLUDE_MEMORY.
* optinfo.cc: Likewise.
* timevar.cc: Likewise.
* toplev.cc: Likewise.
* tree-diagnostic-client-data-hooks.cc: Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc|  1 +
 gcc/diagnostic-format-sarif.cc   |  1 +
 gcc/dumpfile.cc  |  1 +
 gcc/gcov.cc  |  1 +
 gcc/json.cc  | 17 +-
 gcc/json.h   | 38 
 gcc/optinfo-emit-json.cc |  1 +
 gcc/optinfo.cc   |  1 +
 gcc/timevar.cc   |  1 +
 gcc/toplev.cc|  1 +
 gcc/tree-diagnostic-client-data-hooks.cc |  1 +
 11 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 1bf8da663cc2..55ba39e0c532 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "diagnostic.h"
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index d6de5806f5ac..6aba81c6ac9b 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 82bd8b06bebf..6353c0857449 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "options.h"
diff --git a/gcc/gcov.cc b/gcc/gcov.cc
index 85fdac4368e8..aa016c658ce0 100644
--- a/gcc/gcov.cc
+++ b/gcc/gcov.cc
@@ -32,6 +32,7 @@ along with Gcov; see the file COPYING3.  If not see
 
 #include "config.h"
 #define INCLUDE_ALGORITHM
+#define INCLUDE_MEMORY
 #define INCLUDE_VECTOR
 #define INCLUDE_STRING
 #define INCLUDE_MAP
diff --git a/gcc/json.cc b/gcc/json.cc
index 86490259dabf..275ef486faf1 100644
--- a/gcc/json.cc
+++ b/gcc/json.cc
@@ -19,11 +19,13 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "json.h"
 #include "pretty-print.h"
 #include "math.h"
+#include "make-unique.h"
 #include "selftest.h"
 
 using namespace json;
@@ -499,28 +501,31 @@ test_writing_literals ()
   ASSERT_PRINT_EQ (literal (false), true, "false");
 }
 
-/* Verify that nested values are formatted correctly when written.  */
+/* Verify that nested values are formatted correctly when written.
+
+   Also, make use of array::append(std::unique_ptr) and
+   object::set (const char *key, std::unique_ptr v).*/
 
 static void
 test_formatting ()
 {
   object obj;
   object *child = new object;
-  object *grandchild = new object;
+  std::unique_ptr grandchild = ::make_unique ();
 
   obj.set_str

[gcc r15-2283] diagnostics: output formats: use references for non-null pointers

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:29522bff8f4940a6b4307da0021e257c98eeecea

commit r15-2283-g29522bff8f4940a6b4307da0021e257c98eeecea
Author: David Malcolm 
Date:   Wed Jul 24 18:07:53 2024 -0400

diagnostics: output formats: use references for non-null pointers

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc (json_from_expanded_location): Make
"static". Pass param "context" by reference, as it cannot be null.
(json_from_location_range): Likewise for param "context".
(json_from_fixit_hint): Likewise.
(make_json_for_path): Likewise.
(json_output_format::on_end_diagnostic): Update for above changes.

(diagnostic_output_format_init_json::diagnostic_output_format_init_json):
Pass param "context" by reference, as it cannot be null.
(diagnostic_output_format_init_json_stderr): Likewise.
(diagnostic_output_format_init_json_file): Likewise.
(selftest::test_unknown_location): Update for above changes.
(selftest::test_bad_endpoints): Likewise.
* diagnostic-format-sarif.cc (sarif_builder::m_context): Convert
from pointer to reference.
(sarif_invocation::add_notification_for_ice): Convert both params
from pointers to references.
(sarif_invocation::prepare_to_flush): Likewise for "context".
(sarif_result::on_nested_diagnostic): Likewise for "context" and
"builder".
(sarif_result::on_diagram): Likewise.
(sarif_ice_notification::sarif_ice_notification): Likewise.
(sarif_builder::sarif_builder): Likewise for "context".
(sarif_builder::end_diagnostic): Likewise.
(sarif_builder::emit_diagram): Likewise.
(sarif_builder::make_result_object): Likewise.
(make_reporting_descriptor_object_for_warning): Likewise.
(sarif_builder::make_locations_arr): Update for change to m_context.
(sarif_builder::get_sarif_column): Likewise.
(sarif_builder::make_message_object_for_diagram): Convert "context"
from pointer to reference.
(sarif_builder::make_tool_object): Likewise for "m_context".
(sarif_builder::make_driver_tool_component_object): Likewise.
(sarif_builder::get_or_create_artifact): Likewise.
(sarif_builder::maybe_make_artifact_content_object): Likewise.
(sarif_builder::get_source_lines): Likewise.
(sarif_output_format::on_end_diagnostic): Update for above changes.
(sarif_output_format::on_diagram): Likewise.
(sarif_output_format::sarif_output_format): Likewise.
(diagnostic_output_format_init_sarif): Convert param "context"
from pointer to reference.
(diagnostic_output_format_init_sarif_stderr): Likewise.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* diagnostic.cc (diagnostic_output_format_init): Likewise.
* diagnostic.h (diagnostic_output_format_init): Likewise.
(diagnostic_output_format_init_json_stderr): Likewise.
(diagnostic_output_format_init_json_file): Likewise.
(diagnostic_output_format_init_sarif_stderr): Likewise.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
(json_from_expanded_location): Delete decl.
* gcc.cc (driver_handle_option): Update for change to
diagnostic_output_format_init.
* opts.cc (common_handle_option): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc  |  56 +++---
 gcc/diagnostic-format-sarif.cc | 166 -
 gcc/diagnostic.cc  |   2 +-
 gcc/diagnostic.h   |  15 ++--
 gcc/gcc.cc |   3 +-
 gcc/opts.cc|   3 +-
 6 files changed, 122 insertions(+), 123 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 4dc0f264fc70..1bf8da663cc2 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -94,8 +94,8 @@ private:
 
 /* Generate a JSON object for LOC.  */
 
-json::value *
-json_from_expanded_location (diagnostic_context *context, location_t loc)
+static json::value *
+json_from_expanded_location (diagnostic_context &context, location_t loc)
 {
   expanded_location exploc = expand_location (loc);
   json::object *result = new json::object ();
@@ -103,7 +103,7 @@ json_from_expanded_location (diagnostic_context *context, 
location_t loc)
 result->set_string ("file", exploc.file);
   result->set_integer ("line", exploc.line);
 
-  const enum diagnostics_column_unit orig_unit = context->m_column_unit;
+  co

[gcc r15-2282] diagnostics: SARIF output: add sarif_object subclasses throughout

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:5342c63f4fb49c110c6252538cb954779c6ff156

commit r15-2282-g5342c63f4fb49c110c6252538cb954779c6ff156
Author: David Malcolm 
Date:   Wed Jul 24 18:07:52 2024 -0400

diagnostics: SARIF output: add sarif_object subclasses throughout

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-sarif.cc: Introduce subclasses of sarif_object
for all aspects of the spec that we're using.  Replace almost all
usage of json::object with uses of these subclasses, the only
remaining use of json::object being for originalUriBaseIds, as per
SARIF 2.1.0 §3.14.14.  This stronger typing makes it considerably
easier to maintain validity against the schema.
* diagnostic-format-sarif.h (class sarif_logical_location): New.
(make_sarif_logical_location_object): Convert return type from
json::object * to sarif_logical_location *.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 605 ++---
 gcc/diagnostic-format-sarif.h  |   9 +-
 2 files changed, 399 insertions(+), 215 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 7105f7853318..c35d8788d6de 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -36,18 +36,87 @@ along with GCC; see the file COPYING3.  If not see
 #include "ordered-hash-map.h"
 #include "sbitmap.h"
 
+/* Forward decls.  */
 class sarif_builder;
 
-/* Subclass of json::object for SARIF invocation objects
+/* Subclasses of sarif_object.
+   Keep these in order of their descriptions in the specification.  */
+class sarif_artifact_content; // 3.3
+class sarif_artifact_location; // 3.4
+class sarif_message; // 3.11
+class sarif_multiformat_message_string; // 3.12
+class sarif_log; // 3.13
+class sarif_run; // 3.14
+class sarif_tool; // 3.18
+class sarif_tool_component; // 3.19
+class sarif_invocation; // 3.20
+class sarif_artifact; // 3.24
+class sarif_result; // 3.27
+class sarif_location; // 3.28
+class sarif_physical_location; // 3.29
+class sarif_region; // 3.30
+class sarif_logical_location; // 3.33
+class sarif_code_flow; // 3.36
+class sarif_thread_flow; // 3.37
+class sarif_thread_flow_location; // 3.38
+class sarif_reporting_descriptor; // 3.49
+class sarif_reporting_descriptor_reference; // 3.53
+class sarif_tool_component_reference; // 3.54
+class sarif_fix; // 3.55
+class sarif_artifact_change; // 3.56
+class sarif_replacement; // 3.57
+class sarif_ice_notification; // 3.58
+
+/* Declarations of subclasses of sarif_object.
+   Keep these in order of their descriptions in the specification.  */
+
+/* Subclass of sarif_object for SARIF "artifactContent" objects
+   (SARIF v2.1.0 section 3.3).  */
+
+class sarif_artifact_content : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "artifactLocation" objects
+   (SARIF v2.1.0 section 3.4).  */
+
+class sarif_artifact_location : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "message" objects
+   (SARIF v2.1.0 section 3.11).  */
+
+class sarif_message : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "multiformatMessageString" objects
+   (SARIF v2.1.0 section 3.12).  */
+
+class sarif_multiformat_message_string : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "log" objects
+   (SARIF v2.1.0 section 3.13).  */
+
+class sarif_log : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "run" objects
+   (SARIF v2.1.0 section 3.14).  */
+
+class sarif_run : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "tool" objects
+   (SARIF v2.1.0 section 3.18).  */
+
+class sarif_tool : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "toolComponent" objects
+   (SARIF v2.1.0 section 3.19).  */
+
+class sarif_tool_component : public sarif_object {};
+
+/* Subclass of sarif_object for SARIF "invocation" objects
(SARIF v2.1.0 section 3.20).  */
 
 class sarif_invocation : public sarif_object
 {
 public:
-  sarif_invocation ()
-  : m_notifications_arr (new json::array ()),
-m_success (true)
-  {}
+  sarif_invocation ();
 
   void add_notification_for_ice (diagnostic_context *context,
 const diagnostic_info &diagnostic,
@@ -104,7 +173,7 @@ private:
   bool m_embed_contents;
 };
 
-/* Subclass of sarif_object for SARIF result objects
+/* Subclass of sarif_object for SARIF "result" objects
(SARIF v2.1.0 section 3.27).  */
 
 class sarif_result : public sarif_object
@@ -122,42 +191,95 @@ public:
   sarif_builder *builder);
 
 private:
-  void add_related_location (json::object *location_obj);
+  void
+  add_related_location (sarif_location *location_obj);
 
   json::array *m_related_locations_arr;
 };
 
-/* Subclass of sarif_object for SARIF notification objects
-   (SARIF v2.1.0 section 3.58).
+/* Subclass of sar

[gcc r15-2281] gcov: reduce use of naked "new" for json output

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:da0def223e82a4a9400915b2957e96f9f060f5af

commit r15-2281-gda0def223e82a4a9400915b2957e96f9f060f5af
Author: David Malcolm 
Date:   Wed Jul 24 18:07:52 2024 -0400

gcov: reduce use of naked "new" for json output

No functional change intended.

gcc/ChangeLog:
* gcov.cc (output_intermediate_json_line): Use
json::object::set_integer to avoid naked "new".

Signed-off-by: David Malcolm 

Diff:
---
 gcc/gcov.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/gcov.cc b/gcc/gcov.cc
index e76a314041cd..85fdac4368e8 100644
--- a/gcc/gcov.cc
+++ b/gcc/gcov.cc
@@ -1285,8 +1285,8 @@ output_intermediate_json_line (json::array *object,
const int covered = info.popcount ();
 
json::object *cond = new json::object ();
-   cond->set ("count", new json::integer_number (count));
-   cond->set ("covered", new json::integer_number (covered));
+   cond->set_integer ("count", count);
+   cond->set_integer ("covered", covered);
 
json::array *mtrue = new json::array ();
json::array *mfalse = new json::array ();


[gcc r15-2280] analyzer: reduce use of naked "new" for json dumps

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:78d1906c982ad49a0742a7bc1624762159ca165c

commit r15-2280-g78d1906c982ad49a0742a7bc1624762159ca165c
Author: David Malcolm 
Date:   Wed Jul 24 18:07:52 2024 -0400

analyzer: reduce use of naked "new" for json dumps

No functional change intended.

gcc/analyzer/ChangeLog:
* call-string.cc (call_string::to_json): Avoid naked "new".
* constraint-manager.cc (bounded_range::set_json_attr): Likewise.
(equiv_class::to_json): Likewise.
(constraint::to_json): Likewise.
(bounded_ranges_constraint::to_json): Likewise.
* diagnostic-manager.cc (saved_diagnostic::to_json): Likewise.
(saved_diagnostic::maybe_add_sarif_properties): Likewise.
* engine.cc (exploded_node::to_json): Likewise.
(exploded_edge::to_json): Likewise.
* program-point.cc (program_point::to_json): Likewise.
* program-state.cc (program_state::to_json): Likewise.
* sm.cc (state_machine::to_json): Likewise.
* store.cc (binding_cluster::to_json): Likewise.
(store::to_json): Likewise.
* supergraph.cc (supernode::to_json): Likewise.
(superedge::to_json): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/call-string.cc|  9 +++--
 gcc/analyzer/constraint-manager.cc | 12 ++--
 gcc/analyzer/diagnostic-manager.cc | 14 +++---
 gcc/analyzer/engine.cc | 13 ++---
 gcc/analyzer/program-point.cc  | 11 ---
 gcc/analyzer/program-state.cc  |  2 +-
 gcc/analyzer/sm.cc |  2 +-
 gcc/analyzer/store.cc  |  6 +++---
 gcc/analyzer/supergraph.cc | 17 -
 9 files changed, 39 insertions(+), 47 deletions(-)

diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
index 23880e3f5419..c404c09ca0df 100644
--- a/gcc/analyzer/call-string.cc
+++ b/gcc/analyzer/call-string.cc
@@ -111,12 +111,9 @@ call_string::to_json () const
   for (const call_string::element_t &e : m_elements)
 {
   json::object *e_obj = new json::object ();
-  e_obj->set ("src_snode_idx",
- new json::integer_number (e.m_callee->m_index));
-  e_obj->set ("dst_snode_idx",
- new json::integer_number (e.m_caller->m_index));
-  e_obj->set ("funcname",
- new json::string (function_name (e.m_caller->m_fun)));
+  e_obj->set_integer ("src_snode_idx", e.m_callee->m_index);
+  e_obj->set_integer ("dst_snode_idx", e.m_caller->m_index);
+  e_obj->set_string ("funcname", function_name (e.m_caller->m_fun));
   arr->append (e_obj);
 }
 
diff --git a/gcc/analyzer/constraint-manager.cc 
b/gcc/analyzer/constraint-manager.cc
index 29539060ebdd..62d3b84bb745 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -479,7 +479,7 @@ bounded_range::set_json_attr (json::object *obj, const char 
*name, tree value)
   pretty_printer pp;
   pp_format_decoder (&pp) = default_tree_printer;
   pp_printf (&pp, "%E", value);
-  obj->set (name, new json::string (pp_formatted_text (&pp)));
+  obj->set_string (name, pp_formatted_text (&pp));
 }
 
 
@@ -1140,7 +1140,7 @@ equiv_class::to_json () const
   pretty_printer pp;
   pp_format_decoder (&pp) = default_tree_printer;
   pp_printf (&pp, "%qE", m_constant);
-  ec_obj->set ("constant", new json::string (pp_formatted_text (&pp)));
+  ec_obj->set_string ("constant", pp_formatted_text (&pp));
 }
 
   return ec_obj;
@@ -1397,9 +1397,9 @@ constraint::to_json () const
 {
   json::object *con_obj = new json::object ();
 
-  con_obj->set ("lhs", new json::integer_number (m_lhs.as_int ()));
-  con_obj->set ("op", new json::string (constraint_op_code (m_op)));
-  con_obj->set ("rhs", new json::integer_number (m_rhs.as_int ()));
+  con_obj->set_integer ("lhs", m_lhs.as_int ());
+  con_obj->set_string ("op", constraint_op_code (m_op));
+  con_obj->set_integer ("rhs", m_rhs.as_int ());
 
   return con_obj;
 }
@@ -1485,7 +1485,7 @@ bounded_ranges_constraint::to_json () const
 {
   json::object *con_obj = new json::object ();
 
-  con_obj->set ("ec", new json::integer_number (m_ec_id.as_int ()));
+  con_obj->set_integer ("ec", m_ec_id.as_int ());
   con_obj->set ("ranges", m_ranges->to_json ());
 
   return con_obj;
diff --git a/gcc/analyzer/diagnostic-manager.cc 
b/gcc/analyzer/diagnostic-manager.cc
index 51304b0795b6..92e30bd049bd 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -746,17 +746,17 @@ saved_diagnostic::to_json () const
   json::object *sd_obj = new json::object ();
 
   if (m_sm)
-sd_obj->set ("sm", new json::string (m_sm->get_name ()));
-  sd_obj->set ("enode", new json::integer_number (m_enode->m_index));
-  sd_obj->set ("snode", new json::integer_number (m_snode->m_index));
+sd_obj->set_string ("sm", m_sm->get_name ());
+  sd_

[gcc r15-2278] json: add dump overload for easier debugging

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:6baa26c3d6ceec1aba5f143dbfef00e24aa795bb

commit r15-2278-g6baa26c3d6ceec1aba5f143dbfef00e24aa795bb
Author: David Malcolm 
Date:   Wed Jul 24 18:07:51 2024 -0400

json: add dump overload for easier debugging

This has saved me a lot of typing in the debugger.

gcc/ChangeLog:
* json.cc (value::dump): New overload, taking no params.
* json.h (value::dump): New decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/json.cc | 10 ++
 gcc/json.h  |  1 +
 2 files changed, 11 insertions(+)

diff --git a/gcc/json.cc b/gcc/json.cc
index b3106f39cedf..53edca520556 100644
--- a/gcc/json.cc
+++ b/gcc/json.cc
@@ -90,6 +90,16 @@ value::dump (FILE *outf, bool formatted) const
   pp_flush (&pp);
 }
 
+/* A convenience function for debugging.
+   Dump to stderr with formatting, and a trailing newline. */
+
+void
+value::dump () const
+{
+  dump (stderr, true);
+  fprintf (stderr, "\n");
+}
+
 /* class json::object, a subclass of json::value, representing
an ordered collection of key/value pairs.  */
 
diff --git a/gcc/json.h b/gcc/json.h
index 97c68116b329..ad4f8c448f8c 100644
--- a/gcc/json.h
+++ b/gcc/json.h
@@ -83,6 +83,7 @@ class value
   virtual void print (pretty_printer *pp, bool formatted) const = 0;
 
   void dump (FILE *, bool formatted) const;
+  void DEBUG_FUNCTION dump () const;
 };
 
 /* Subclass of value for objects: a collection of key/value pairs


[gcc r15-2279] json: add array::append_string

2024-07-24 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3f14878fbfcd69b316e2be195c3377a750ad6031

commit r15-2279-g3f14878fbfcd69b316e2be195c3377a750ad6031
Author: David Malcolm 
Date:   Wed Jul 24 18:07:51 2024 -0400

json: add array::append_string

No functional change intended.

gcc/analyzer/ChangeLog:
* supergraph.cc (supernode::to_json): Avoid naked "new" by using
json::array::append_string.
(supernode::to_json): Likewise.

gcc/ChangeLog:
* diagnostic-format-sarif.cc (sarif_artifact::populate_roles):
Avoid naked "new" by using json::array::append_string.
(sarif_builder::maybe_make_kinds_array): Likewise.
* json.cc (json::array::append_string): New.
(selftest::test_writing_arrays): Use it.
* json.h (json::array::append_string): New decl.
* optinfo-emit-json.cc (optrecord_json_writer::pass_to_json):
Avoid naked "new" by using json::array::append_string.
(optrecord_json_writer::optinfo_to_json): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/supergraph.cc | 4 ++--
 gcc/diagnostic-format-sarif.cc | 8 
 gcc/json.cc| 9 -
 gcc/json.h | 1 +
 gcc/optinfo-emit-json.cc   | 4 ++--
 5 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index 4dc7942b26aa..20c62856d4b6 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -747,7 +747,7 @@ supernode::to_json () const
pretty_printer pp;
pp_format_decoder (&pp) = default_tree_printer;
pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
-   phi_arr->append (new json::string (pp_formatted_text (&pp)));
+   phi_arr->append_string (pp_formatted_text (&pp));
   }
 snode_obj->set ("phis", phi_arr);
   }
@@ -762,7 +762,7 @@ supernode::to_json () const
pretty_printer pp;
pp_format_decoder (&pp) = default_tree_printer;
pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
-   stmt_arr->append (new json::string (pp_formatted_text (&pp)));
+   stmt_arr->append_string (pp_formatted_text (&pp));
   }
 snode_obj->set ("stmts", stmt_arr);
   }
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 225476995d13..7105f7853318 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -435,7 +435,7 @@ sarif_artifact::populate_roles ()
 if (bitmap_bit_p (m_roles, i))
   {
enum diagnostic_artifact_role role = (enum diagnostic_artifact_role)i;
-   roles_arr->append (new json::string (get_artifact_role_string (role)));
+   roles_arr->append_string (get_artifact_role_string (role));
   }
   set ("roles", roles_arr);
 }
@@ -1394,13 +1394,13 @@ sarif_builder::maybe_make_kinds_array 
(diagnostic_event::meaning m) const
   json::array *kinds_arr = new json::array ();
   if (const char *verb_str
= diagnostic_event::meaning::maybe_get_verb_str (m.m_verb))
-kinds_arr->append (new json::string (verb_str));
+kinds_arr->append_string (verb_str);
   if (const char *noun_str
= diagnostic_event::meaning::maybe_get_noun_str (m.m_noun))
-kinds_arr->append (new json::string (noun_str));
+kinds_arr->append_string (noun_str);
   if (const char *property_str
= diagnostic_event::meaning::maybe_get_property_str (m.m_property))
-kinds_arr->append (new json::string (property_str));
+kinds_arr->append_string (property_str);
   return kinds_arr;
 }
 
diff --git a/gcc/json.cc b/gcc/json.cc
index 53edca520556..86490259dabf 100644
--- a/gcc/json.cc
+++ b/gcc/json.cc
@@ -286,6 +286,13 @@ array::append (value *v)
   m_elements.safe_push (v);
 }
 
+void
+array::append_string (const char *utf8_value)
+{
+  gcc_assert (utf8_value);
+  append (new json::string (utf8_value));
+}
+
 /* class json::float_number, a subclass of json::value, wrapping a double.  */
 
 /* Implementation of json::value::print for json::float_number.  */
@@ -432,7 +439,7 @@ test_writing_arrays ()
   arr.append (new json::string ("foo"));
   ASSERT_PRINT_EQ (arr, true, "[\"foo\"]");
 
-  arr.append (new json::string ("bar"));
+  arr.append_string ("bar");
   ASSERT_PRINT_EQ (arr, true,
   "[\"foo\",\n"
   " \"bar\"]");
diff --git a/gcc/json.h b/gcc/json.h
index ad4f8c448f8c..d3493a72d525 100644
--- a/gcc/json.h
+++ b/gcc/json.h
@@ -130,6 +130,7 @@ class array : public value
   void print (pretty_printer *pp, bool formatted) const final override;
 
   void append (value *v);
+  void append_string (const char *utf8_value);
 
  private:
   auto_vec m_elements;
diff --git a/gcc/optinfo-emit-json.cc b/gcc/optinfo-emit-json.cc
index 1fa82d438db9..faae95fc232a 100644
--- a/gcc/optinfo-emit-json.cc
+++ b/gcc/optinfo-emit-json.cc
@@ -259,7 +259,7 @@ optrecord_json_writer::pass_to_json (opt_pass *pass)
 optgroup

[gcc r15-2015] diagnostics: add highlight-a vs highlight-b in colorization and pp_markup

2024-07-13 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3

commit r15-2015-g7d73c01ce6d1ab28157a7dadcd3be14f96a7c8f3
Author: David Malcolm 
Date:   Sat Jul 13 10:34:51 2024 -0400

diagnostics: add highlight-a vs highlight-b in colorization and pp_markup

Since r6-4582-g8a64515099e645 (which added class rich_location), ranges
of quoted source code have been colorized using the following rules:
- the primary range used the same color of the kind of the diagnostic
i.e. "error" vs "warning" etc (defaulting to bold red and bold magenta
respectively)
- secondary ranges alternate between "range1" and "range2" (defaulting
to green and blue respectively)

This works for cases with large numbers of highlighted ranges, but is
suboptimal for common cases.

The following patch adds a pair of color names: "highlight-a" and
"highlight-b", and uses them whenever it makes sense to highlight and
contrast two different things in the source code (e.g. a type mismatch).
These are used by diagnostic-show-locus.cc for highlighting quoted
source.  In addition the patch adds colorization to fragments within the
corresponding diagnostic messages themselves, using consistent
colorization between the message and the quoted source code for the two
different things being contrasted.

For example, consider:

demo.c: In function ‘test_bad_format_string_args’:
../../src/demo.c:25:18: warning: format ‘%i’ expects argument of
  type ‘int’, but argument 2 has type ‘const char *’ [-Wformat=]
   25 |   printf("hello %i", msg);
  | ~^   ~~~
  |  |   |
  |  int const char *
  | %s

Previously, the types within the message in quotes would be in bold but
not colorized, and the labelled ranges of quoted source code would use
bold magenta for the "int" and non-bold green for the "const char *".

With this patch:
- the "%i" and "int" in the message and the "int" in the quoted source
  are all colored bold green
- the "const char *" in the message and in the quoted source are both
  colored bold blue
so that the consistent use of contrasting color draws the reader's eyes
to the relationships between the diagnostic message and the source.

I've tried this with gnome-terminal with many themes, including a
variety of light versus dark backgrounds, solarized versus non-solarized
themes, etc, and it was readable in all.

My initial version of the patch used the existing %r and %R facilities
within pretty-print.cc for the messages, but this turned out to be very
uncomfortable, leading to error-prone format strings such as:

  error_at (richloc,
"invalid operands to binary %s (have %<%r%T%R%> and 
%<%r%T%R%>)",
opname,
"highlight-a", type0,
"highlight-b", type1);

To avoid requiring monstrosities such as the above, the patch adds a new
"%e" format code to pretty-print.cc, which expects a pp_element *, where
pp_element is a new abstract base class (actually a pp_markup::element),
along with various useful subclasses.  This lets the above be written
as:

  pp_markup::element_quoted_type element_0 (type0, highlight_colors::lhs);
  pp_markup::element_quoted_type element_1 (type1, highlight_colors::rhs);
  error_at (richloc,
"invalid operands to binary %s (have %e and %e)",
opname, &element_0, &element_1);

which I feel is maintainable and clear to translators; the use of %e and
pp_element * captures the type-unsafe part of the variadic call, and the
subclasses allow for type-safety (so e.g. an element_quoted_type expects
a type and a highlighting color).  This approach allows for some nice
simplifications within c-format.cc.

The patch also extends -Wformat to "teach" it about the new %e and
pp_element *.  Doing so requires c-format.cc to be able to determine
if a T * is a pp_element * (i.e. if T is a subclass).  To do so I added
a new comp_types callback for comparing types, where the C++ frontend
supplies a suitable implementation (and %e will always be wrong for C).

I've manually tested this on many diagnostics with both C and C++ and it
seems a subtle but significant improvement in readability.

I've added a new option -fno-diagnostics-show-highlight-colors in case
people prefer the old behavior.

gcc/c-family/ChangeLog:
* c-common.cc: Include "tree-pretty-print-markup.h".
(binary_op_error): Use pp_markup::element_quoted_type and %e.
(check_function_arguments): Add "comp_types" param and pass it to
check_function_format.
* c-common.h (check_function_arguments): Add "comp_types" param.
  

[gcc r15-1913] diagnostics: use refs rather than pointers for diagnostic_{path, context}

2024-07-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:2d6e6a77e840b7b93d1f18708aa08ced8b46282e

commit r15-1913-g2d6e6a77e840b7b93d1f18708aa08ced8b46282e
Author: David Malcolm 
Date:   Tue Jul 9 11:22:32 2024 -0400

diagnostics: use refs rather than pointers for diagnostic_{path,context}

Use const & rather than const * in various places where it can't be null
and can't change.

No functional change intended.

gcc/ChangeLog:
* diagnostic-path.cc: Replace "const diagnostic_path *" with
"const diagnostic_path &" throughout, and "diagnostic_context *"
with "diagnostic context &".
* diagnostic.cc (diagnostic_context::show_any_path): Pass
reference in call to print_path.
* diagnostic.h (diagnostic_context::print_path): Convert param
to a reference.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.cc | 101 -
 gcc/diagnostic.cc  |   2 +-
 gcc/diagnostic.h   |   2 +-
 3 files changed, 52 insertions(+), 53 deletions(-)

diff --git a/gcc/diagnostic-path.cc b/gcc/diagnostic-path.cc
index e470bd29fdd9..f279aead6c59 100644
--- a/gcc/diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -225,7 +225,7 @@ class path_label : public range_label
 {
  public:
   path_label (const diagnostic_context &ctxt,
- const diagnostic_path *path,
+ const diagnostic_path &path,
  unsigned start_idx)
   : m_ctxt (ctxt), m_path (path), m_start_idx (start_idx), m_effects (*this)
   {}
@@ -233,7 +233,7 @@ class path_label : public range_label
   label_text get_text (unsigned range_idx) const final override
   {
 unsigned event_idx = m_start_idx + range_idx;
-const diagnostic_event &event = m_path->get_event (event_idx);
+const diagnostic_event &event = m_path.get_event (event_idx);
 
 /* Get the description of the event, perhaps with colorization:
normally, we don't colorize within a range_label, but this
@@ -305,7 +305,7 @@ class path_label : public range_label
   const diagnostic_event &get_event (unsigned range_idx) const
   {
 unsigned event_idx = m_start_idx + range_idx;
-return m_path->get_event (event_idx);
+return m_path.get_event (event_idx);
   }
 
   const diagnostic_event *get_prev_event (unsigned range_idx) const
@@ -313,11 +313,11 @@ class path_label : public range_label
 if (m_start_idx + range_idx == 0)
   return nullptr;
 unsigned event_idx = m_start_idx + range_idx - 1;
-return &m_path->get_event (event_idx);
+return &m_path.get_event (event_idx);
   }
 
   const diagnostic_context &m_ctxt;
-  const diagnostic_path *m_path;
+  const diagnostic_path &m_path;
   unsigned m_start_idx;
   path_label_effects m_effects;
 };
@@ -508,7 +508,7 @@ struct event_range
   };
 
   event_range (const diagnostic_context &ctxt,
-  const diagnostic_path *path, unsigned start_idx,
+  const diagnostic_path &path, unsigned start_idx,
   const diagnostic_event &initial_event,
   per_thread_summary &t,
   bool show_event_links)
@@ -559,7 +559,7 @@ struct event_range
unsigned new_ev_idx,
bool check_rich_locations)
   {
-if (!can_consolidate_events (*m_path,
+if (!can_consolidate_events (m_path,
 m_initial_event, m_start_idx,
 new_ev, new_ev_idx,
 check_rich_locations))
@@ -574,7 +574,7 @@ struct event_range
   = get_per_source_line_info (exploc.line);
 const diagnostic_event *prev_event = nullptr;
 if (new_ev_idx > 0)
-  prev_event = &m_path->get_event (new_ev_idx - 1);
+  prev_event = &m_path.get_event (new_ev_idx - 1);
 const bool has_in_edge = (prev_event
  ? prev_event->connect_to_next_event_p ()
  : false);
@@ -604,7 +604,7 @@ struct event_range
   /* Print the events in this range to DC, typically as a single
  call to the printer's diagnostic_show_locus.  */
 
-  void print (diagnostic_context *dc, pretty_printer *pp,
+  void print (diagnostic_context &dc, pretty_printer *pp,
  diagnostic_source_effect_info *effect_info)
   {
 location_t initial_loc = m_initial_event.get_location ();
@@ -612,13 +612,13 @@ struct event_range
 /* Emit a span indicating the filename (and line/column) if the
line has changed relative to the last call to
diagnostic_show_locus.  */
-if (dc->m_source_printing.enabled)
+if (dc.m_source_printing.enabled)
   {
expanded_location exploc
  = linemap_client_expand_location_to_spelling_point
  (line_table, initial_loc, LOCATION_ASPECT_CARET);
-   if (exploc.file != LOCATION_FILE (dc->m_last_location))
- diagnostic_start_span (dc) (dc, exploc);
+   if (exploc.file != LOCATION_FILE (dc.m_last_location

[gcc r15-1900] c-format.cc: add ctors to format_check_results and format_check_context

2024-07-08 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:113b5ce0610207717f651a3f8a3f1123d93f97af

commit r15-1900-g113b5ce0610207717f651a3f8a3f1123d93f97af
Author: David Malcolm 
Date:   Mon Jul 8 18:55:28 2024 -0400

c-format.cc: add ctors to format_check_results and format_check_context

This is a minor cleanup I spotted whilst working on another patch.
No functional change intended.

gcc/c-family/ChangeLog:
* c-format.cc (format_check_results::format_check_results): New
ctor.
(struct format_check_context): Add ctor; add "m_" prefix to all
fields.
(check_format_info): Use above ctors.
(check_format_arg): Update for "m_" prefix to
format_check_context.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/c-family/c-format.cc | 63 
 1 file changed, 37 insertions(+), 26 deletions(-)

diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index 7a5ffc25602c..5bfd2fc4469e 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -1021,6 +1021,20 @@ static int n_format_types = ARRAY_SIZE 
(format_types_orig);
many leaves resulting from nested conditional expressions.  */
 struct format_check_results
 {
+  format_check_results (location_t format_string_loc_)
+  : number_non_literal (0),
+number_extra_args (0),
+extra_arg_loc (UNKNOWN_LOCATION),
+number_dollar_extra_args (0),
+number_wide (0),
+number_non_char (0),
+number_empty (0),
+number_unterminated (0),
+number_other (0),
+format_string_loc (format_string_loc_)
+  {
+  }
+
   /* Number of leaves of the format argument that could not be checked
  as they were not string literals.  */
   int number_non_literal;
@@ -1050,10 +1064,21 @@ struct format_check_results
 
 struct format_check_context
 {
-  format_check_results *res;
-  function_format_info *info;
-  tree params;
-  vec *arglocs;
+  format_check_context (format_check_results *res,
+   function_format_info *info,
+   tree params,
+   vec *arglocs)
+  : m_res (res),
+m_info (info),
+m_params (params),
+m_arglocs (arglocs)
+  {
+  }
+
+  format_check_results *m_res;
+  function_format_info *m_info;
+  tree m_params;
+  vec *m_arglocs;
 };
 
 /* Return the format name (as specified in the original table) for the format
@@ -1539,10 +1564,8 @@ static void
 check_format_info (function_format_info *info, tree params,
   vec *arglocs)
 {
-  format_check_context format_ctx;
   unsigned HOST_WIDE_INT arg_num;
   tree format_tree;
-  format_check_results res;
   /* Skip to format argument.  If the argument isn't available, there's
  no work for us to do; prototype checking will catch the problem.  */
   for (arg_num = 1; ; ++arg_num)
@@ -1558,26 +1581,14 @@ check_format_info (function_format_info *info, tree 
params,
   if (format_tree == 0)
 return;
 
-  res.number_non_literal = 0;
-  res.number_extra_args = 0;
-  res.extra_arg_loc = UNKNOWN_LOCATION;
-  res.number_dollar_extra_args = 0;
-  res.number_wide = 0;
-  res.number_non_char = 0;
-  res.number_empty = 0;
-  res.number_unterminated = 0;
-  res.number_other = 0;
-  res.format_string_loc = input_location;
-
-  format_ctx.res = &res;
-  format_ctx.info = info;
-  format_ctx.params = params;
-  format_ctx.arglocs = arglocs;
+  format_check_results res (input_location);
+
+  format_check_context format_ctx (&res, info, params, arglocs);
 
   check_function_arguments_recurse (check_format_arg, &format_ctx,
format_tree, arg_num, OPT_Wformat_);
 
-  location_t loc = format_ctx.res->format_string_loc;
+  location_t loc = format_ctx.m_res->format_string_loc;
 
   if (res.number_non_literal > 0)
 {
@@ -1659,10 +1670,10 @@ check_format_arg (void *ctx, tree format_tree,
  unsigned HOST_WIDE_INT arg_num)
 {
   format_check_context *format_ctx = (format_check_context *) ctx;
-  format_check_results *res = format_ctx->res;
-  function_format_info *info = format_ctx->info;
-  tree params = format_ctx->params;
-  vec *arglocs = format_ctx->arglocs;
+  format_check_results *res = format_ctx->m_res;
+  function_format_info *info = format_ctx->m_info;
+  tree params = format_ctx->m_params;
+  vec *arglocs = format_ctx->m_arglocs;
 
   int format_length;
   HOST_WIDE_INT offset;


gcc-cvs@gcc.gnu.org

2024-07-04 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:f8c130cdf531653e5c041d247729851419bc7bde

commit r15-1846-gf8c130cdf531653e5c041d247729851419bc7bde
Author: David Malcolm 
Date:   Thu Jul 4 14:44:51 2024 -0400

analyzer: convert sm_context * to sm_context &

These are never nullptr and never change, so use a reference rather
than a pointer.

No functional change intended.

gcc/analyzer/ChangeLog:
* diagnostic-manager.cc
(diagnostic_manager::add_events_for_eedge): Pass sm_ctxt by
reference.
* engine.cc (impl_region_model_context::on_condition): Likewise.
(impl_region_model_context::on_bounded_ranges): Likewise.
(impl_region_model_context::on_phi): Likewise.
(exploded_node::on_stmt): Likewise.
* sm-fd.cc: Update all uses of sm_context * to sm_context &.
* sm-file.cc: Likewise.
* sm-malloc.cc: Likewise.
* sm-pattern-test.cc: Likewise.
* sm-sensitive.cc: Likewise.
* sm-signal.cc: Likewise.
* sm-taint.cc: Likewise.
* sm.h: Likewise.
* varargs.cc: Likewise.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_gil_plugin.c: Update all uses of
sm_context * to sm_context &.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/diagnostic-manager.cc|   2 +-
 gcc/analyzer/engine.cc|   8 +-
 gcc/analyzer/sm-fd.cc | 318 +++---
 gcc/analyzer/sm-file.cc   |  38 +--
 gcc/analyzer/sm-malloc.cc | 194 ++---
 gcc/analyzer/sm-pattern-test.cc   |  14 +-
 gcc/analyzer/sm-sensitive.cc  |  22 +-
 gcc/analyzer/sm-signal.cc |  20 +-
 gcc/analyzer/sm-taint.cc  | 122 -
 gcc/analyzer/sm.h |   8 +-
 gcc/analyzer/varargs.cc   |  54 ++--
 gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c |  46 ++--
 12 files changed, 419 insertions(+), 427 deletions(-)

diff --git a/gcc/analyzer/diagnostic-manager.cc 
b/gcc/analyzer/diagnostic-manager.cc
index 20e793d72c1..fe943ac61c9 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -2239,7 +2239,7 @@ diagnostic_manager::add_events_for_eedge (const 
path_builder &pb,
&iter_point,
emission_path,
pb.get_ext_state 
());
-   sm.on_stmt (&sm_ctxt, dst_point.get_supernode (), stmt);
+   sm.on_stmt (sm_ctxt, dst_point.get_supernode (), stmt);
// TODO: what about phi nodes?
  }
  }
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index f5fad5b2e47..c9f204b13e7 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -969,7 +969,7 @@ impl_region_model_context::on_condition (const svalue *lhs,
   m_old_state->m_checker_states[sm_idx],
   m_new_state->m_checker_states[sm_idx],
   m_path_ctxt);
-  sm.on_condition (&sm_ctxt,
+  sm.on_condition (sm_ctxt,
   (m_enode_for_diag
? m_enode_for_diag->get_supernode ()
: NULL),
@@ -996,7 +996,7 @@ impl_region_model_context::on_bounded_ranges (const svalue 
&sval,
   m_old_state->m_checker_states[sm_idx],
   m_new_state->m_checker_states[sm_idx],
   m_path_ctxt);
-  sm.on_bounded_ranges (&sm_ctxt,
+  sm.on_bounded_ranges (sm_ctxt,
(m_enode_for_diag
 ? m_enode_for_diag->get_supernode ()
 : NULL),
@@ -1037,7 +1037,7 @@ impl_region_model_context::on_phi (const gphi *phi, tree 
rhs)
   m_old_state->m_checker_states[sm_idx],
   m_new_state->m_checker_states[sm_idx],
   m_path_ctxt);
-  sm.on_phi (&sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
+  sm.on_phi (sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
 }
 }
 
@@ -1559,7 +1559,7 @@ exploded_node::on_stmt (exploded_graph &eg,
   unknown_side_effects);
 
   /* Allow the state_machine to handle the stmt.  */
-  if (sm.on_stmt (&sm_ctxt, snode, stmt))
+  if (sm.on_stmt (sm_ctxt, snode, stmt))
unknown_side_effects = false;
 }
 
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index ded20576fd1..3396b1d1122 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -119,

[gcc r15-1845] analyzer: handle at -O0 [PR115724]

2024-07-04 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a6fdb1a2a2906103afd70fa68cf7c45e896b8fbb

commit r15-1845-ga6fdb1a2a2906103afd70fa68cf7c45e896b8fbb
Author: David Malcolm 
Date:   Thu Jul 4 14:44:51 2024 -0400

analyzer: handle  at -O0 [PR115724]

At -O0, glibc's:

__extern_always_inline void
error (int __status, int __errnum, const char *__format, ...)
{
  if (__builtin_constant_p (__status) && __status != 0)
__error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack 
());
  else
__error_alias (__status, __errnum, __format, __builtin_va_arg_pack ());
}

becomes just:

__extern_always_inline void
error (int __status, int __errnum, const char *__format, ...)
{
  if (0)
__error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack 
());
  else
__error_alias (__status, __errnum, __format, __builtin_va_arg_pack ());
}

and thus calls to "error" are calls to "__error_alias" by the
time -fanalyzer "sees" them.

Handle them with more special-casing in kf.cc.

gcc/analyzer/ChangeLog:
PR analyzer/115724
* kf.cc (register_known_functions): Add __error_alias and
__error_at_line_alias.

gcc/testsuite/ChangeLog:
PR analyzer/115724
* c-c++-common/analyzer/error-pr115724.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/kf.cc |  4 +
 .../c-c++-common/analyzer/error-pr115724.c | 86 ++
 2 files changed, 90 insertions(+)

diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index 4213b89ac9f..5c3a71fbb49 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -2325,6 +2325,10 @@ register_known_functions (known_function_manager &kfm,
 kfm.add ("__errno_location", make_unique ());
 kfm.add ("error", make_unique (3));
 kfm.add ("error_at_line", make_unique (5));
+/* Variants of "error" and "error_at_line" seen by the
+   analyzer at -O0 (PR analyzer/115724).  */
+kfm.add ("__error_alias", make_unique (3));
+kfm.add ("__error_at_line_alias", make_unique (5));
   }
 
   /* Other implementations of C standard library.  */
diff --git a/gcc/testsuite/c-c++-common/analyzer/error-pr115724.c 
b/gcc/testsuite/c-c++-common/analyzer/error-pr115724.c
new file mode 100644
index 000..ae606ad89d6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/error-pr115724.c
@@ -0,0 +1,86 @@
+/* Verify that the analyzer handles the no-optimization case in
+   glibc's  when error,error_at_line calls become
+   __error_alias and __error_at_line_alias.  */
+
+typedef __SIZE_TYPE__ size_t;
+#define EXIT_FAILURE 1
+#define __extern_always_inline  extern inline __attribute__ 
((__always_inline__)) __attribute__ ((__gnu_inline__))
+
+int errno;
+
+/* Adapted from glibc's bits/error.h.  */
+
+extern void __error_alias (int __status, int __errnum,
+  const char *__format, ...)
+  __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_noreturn (int __status, int __errnum,
+  const char *__format, ...)
+  __attribute__ ((__noreturn__, __format__ (__printf__, 3, 4)));
+
+/* If we know the function will never return make sure the compiler
+   realizes that, too.  */
+__extern_always_inline void
+error (int __status, int __errnum, const char *__format, ...)
+{
+  if (__builtin_constant_p (__status) && __status != 0)
+__error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack ());
+  else
+__error_alias (__status, __errnum, __format, __builtin_va_arg_pack ());
+}
+
+extern void __error_at_line_alias (int __status, int __errnum,
+  const char *__fname,
+  unsigned int __line,
+  const char *__format, ...)
+  __attribute__ ((__format__ (__printf__, 5, 6)));
+extern void __error_at_line_noreturn (int __status, int __errnum,
+ const char *__fname,
+ unsigned int __line,
+ const char *__format,
+ ...)
+  __attribute__ ((__noreturn__, __format__ (__printf__, 5, 6)));
+
+/* If we know the function will never return make sure the compiler
+   realizes that, too.  */
+__extern_always_inline void
+error_at_line (int __status, int __errnum, const char *__fname,
+  unsigned int __line, const char *__format, ...)
+{
+  if (__builtin_constant_p (__status) && __status != 0)
+__error_at_line_noreturn (__status, __errnum, __fname, __line, __format,
+ __builtin_va_arg_pack ());
+  else
+__error_at_line_alias (__status, __errnum, __fname, __line,
+  __format, __builtin_va_arg_pack ());
+}
+
+
+struct list {
+size_t size;
+void (*destroy)(void *data);
+   

[gcc r15-1635] diagnostics: introduce diagnostic-global-context.cc

2024-06-25 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3800a78a767f463bed6948c640eee4250781e62e

commit r15-1635-g3800a78a767f463bed6948c640eee4250781e62e
Author: David Malcolm 
Date:   Tue Jun 25 20:26:35 2024 -0400

diagnostics: introduce diagnostic-global-context.cc

This moves all of the uses of global_dc within diagnostic.cc (including
the definition) to a new diagnostic-global-context.cc.  My intent is to
make clearer those parts of our internal API that implicitly use
global_dc, and to perhaps avoid linking global_dc into a future
libdiagnostics.so.

No functional change intended.

gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add diagnostic-global-context.o.
* diagnostic-global-context.cc: New file, taken from material in
diagnostic.cc.
* diagnostic.cc (global_diagnostic_context): Move to
diagnostic-global-context.cc.
(global_dc): Likewise.
(verbatim): Likewise.
(emit_diagnostic): Likewise.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
(inform): Likewise.
(inform_n): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror): Likewise.
(permerror_opt): Likewise.
(error): Likewise.
(error_n): Likewise.
(error_at): Likewise.
(error_meta): Likewise.
(sorry): Likewise.
(sorry_at): Likewise.
(seen_error): Likewise.
(fatal_error): Likewise.
(internal_error): Likewise.
(internal_error_no_backtrace): Likewise.
(fnotice): Likewise.
(auto_diagnostic_group::auto_diagnostic_group): Likewise.
(auto_diagnostic_group::~auto_diagnostic_group): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in  |   1 +
 gcc/diagnostic-global-context.cc | 553 +++
 gcc/diagnostic.cc| 521 
 3 files changed, 554 insertions(+), 521 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9eacb21bf54..7d3ea27a6ab 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1824,6 +1824,7 @@ OBJS = \
 OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
diagnostic-format-json.o \
diagnostic-format-sarif.o \
+   diagnostic-global-context.o \
diagnostic-macro-unwinding.o \
diagnostic-path.o \
diagnostic-show-locus.o \
diff --git a/gcc/diagnostic-global-context.cc b/gcc/diagnostic-global-context.cc
new file mode 100644
index 000..497eb9e727c
--- /dev/null
+++ b/gcc/diagnostic-global-context.cc
@@ -0,0 +1,553 @@
+/* Language-independent diagnostic subroutines that implicitly use global_dc.
+   Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   Contributed by Gabriel Dos Reis 
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+
+/* This file implements the parts of the language independent aspect
+   of diagnostic messages that implicitly use global_dc.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "intl.h"
+#include "diagnostic.h"
+
+/* A diagnostic_context surrogate for stderr.  */
+static diagnostic_context global_diagnostic_context;
+diagnostic_context *global_dc = &global_diagnostic_context;
+
+/* Standard error reporting routines in increasing order of severity.  */
+
+/* Text to be emitted verbatim to the error message stream; this
+   produces no prefix and disables line-wrapping.  Use rarely.  */
+void
+verbatim (const char *gmsgid, ...)
+{
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  text_info text (_(gmsgid), &ap, errno);
+  pp_format_verbatim (global_dc->printer, &text);
+  pp_newline_and_flush (global_dc->printer);
+  va_end (ap);
+}
+
+/* Wrapper around diagnostic_context::diagnostic_impl
+   implying global_dc and taking a variable argument list.  */
+
+bool
+emit_diagnostic (diagnostic_t kind, location_t location, int opt,
+const char *gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, location);
+  bool ret = global_dc->d

[gcc r15-1634] diagnostics: eliminate various implicit uses of global_dc

2024-06-25 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d681c5211e613c64d149e734b15cdcf7d542342e

commit r15-1634-gd681c5211e613c64d149e734b15cdcf7d542342e
Author: David Malcolm 
Date:   Tue Jun 25 20:26:30 2024 -0400

diagnostics: eliminate various implicit uses of global_dc

This patch eliminates all implicit uses of "global_dc" from
the path-printing logic and from
gcc_rich_location::add_location_if_nearby.

No functional change intended.

gcc/c/ChangeLog:
* c-parser.cc (c_parser_require): Pass *global_dc to
gcc_rich_location::add_location_if_nearby.

gcc/cp/ChangeLog:
* parser.cc (cp_parser_error_1): Pass *global_dc to
gcc_rich_location::add_location_if_nearby.
(cp_parser_decl_specifier_seq): Likewise.
(cp_parser_set_storage_class): Likewise.
(cp_parser_set_storage_class): Likewise.

gcc/ChangeLog:
* diagnostic-path.cc (class path_label): Add m_path field,
and use it to replace all uses of global_dc.
(event_range::event_range): Add "ctxt" param and use it to
construct m_path_label.
(event_range::maybe_add_event): Add "ctxt" param and pass it to
gcc_rich_location::add_location_if_nearby.
(path_summary::path_summary): Add "ctxt" param and pass it to
event_range::maybe_add_event.
(diagnostic_context::print_path): Pass *this to path_summary ctor.
(selftest::test_empty_path): Use "dc" when constructing
path_summary rather than implicitly using global_dc.
(selftest::test_intraprocedural_path): Likewise.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(selftest::assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.
(selftest::diagnostic_path_cc_tests): Eliminate use of global_dc.
* diagnostic-show-locus.cc
(gcc_rich_location::add_location_if_nearby): Add "ctxt" param and
use it instead of implicitly using global_dc.
(selftest::test_add_location_if_nearby): Use
test_diagnostic_context rather than implicitly using global_dc.
* diagnostic.cc (pedantic_warning_kind): Delete macro.
(permissive_error_kind): Delete macro.
(permissive_error_option): Delete macro.
(diagnostic_context::diagnostic_enabled): Remove use of
permissive_error_option.
(diagnostic_context::report_diagnostic): Remove use of
pedantic_warning_kind.
(diagnostic_impl): Convert to...
(diagnostic_context::diagnostic_impl): ...this.
(diagnostic_n_impl): Convert to...
(diagnostic_context::diagnostic_n_impl): ...this.
(emit_diagnostic): Explicitly use global_dc for method call.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
(inform): Likewise.
(inform_n): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror): Likewise.
(permerror_opt): Likewise.
(error): Likewise.
(error_n): Likewise.
(error_at): Likewise.
(error_meta): Likewise.
(sorry): Likewise.
(sorry_at): Likewise.
(fatal_error): Likewise.
(internal_error): Likewise.
(internal_error_no_backtrace): Likewise.
* diagnostic.h (diagnostic_context::diagnostic_impl): New decl.
(diagnostic_context::diagnostic_n_impl): New decl.
* gcc-rich-location.h (gcc_rich_location::add_location_if_nearby):
Add "ctxt" param.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/c/c-parser.cc|   2 +-
 gcc/cp/parser.cc |  11 ++--
 gcc/diagnostic-path.cc   | 125 ---
 gcc/diagnostic-show-locus.cc |  25 
 gcc/diagnostic.cc| 136 +--
 gcc/diagnostic.h |   8 +++
 gcc/gcc-rich-location.h  |   6 +-
 7 files changed, 166 insertions(+), 147 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 33643ec910a..6a3f96d5b61 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1248,7 +1248,7 @@ c_parser_require (c_parser *parser,
   bool added_matching_location = false;
   if (matching_location != UNKNOWN_LOCATION)
added_ma

[gcc r15-1633] testsuite: use check-jsonschema for validating .sarif files [PR109360]

2024-06-25 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:17967907102099806dc80c71ee7665ffb22ffa23

commit r15-1633-g17967907102099806dc80c71ee7665ffb22ffa23
Author: David Malcolm 
Date:   Tue Jun 25 20:26:21 2024 -0400

testsuite: use check-jsonschema for validating .sarif files [PR109360]

As reported here:
  https://gcc.gnu.org/pipermail/gcc-patches/2024-June/655434.html
the schema validation I added for generated .sarif files in
r15-1541-ga84fe222029ff2 used the "jsonschema" command line tool, which
has been deprecated by more recent versions of the Python 3 "jsonschema"
module.

This patch updates the validation to use the more recent
"check-jsonschema" command line tool, from the Python 3 "check-jsonschema"
module, fixing the testsuite FAILs due to the deprecation message.

As an added bonus, the output on validation failures is *much* nicer, e.g.
if I undo r15-1540-g9f4fdc3acebcf6, the error messages begin like this:
verify-sarif-file: res: Schema validation errors were encountered.
  
diagnostic-format-sarif-file-bad-utf8-pr109098-1.c.sarif::$.runs[0].results[0].locations[0].physicalLocation.region.startColumn:
 0 is less than the minimum of 1
  
diagnostic-format-sarif-file-bad-utf8-pr109098-1.c.sarif::$.runs[0].results[0].relatedLocations[0].physicalLocation.region.startColumn:
 0 is less than the minimum of 1
  
diagnostic-format-sarif-file-bad-utf8-pr109098-1.c.sarif::$.runs[0].results[0].relatedLocations[1].physicalLocation.region.startColumn:
 0 is less than the minimum of 1
  
diagnostic-format-sarif-file-bad-utf8-pr109098-1.c.sarif::$.runs[0].results[0].relatedLocations[2].physicalLocation.region.startColumn:
 0 is less than the minimum of 1
child process exited abnormally
FAIL: c-c++-common/diagnostic-format-sarif-file-bad-utf8-pr109098-1.c  
-Wc++-compat   (test .sarif output against SARIF schema)

Tested with Python 3.8 with check_jsonschema 0.28.6

gcc/ChangeLog:
PR testsuite/109360
* doc/install.texi (Python3 modules): Update SARIF validation
requirement to use check-jsonschema rather than jsonschema.

gcc/testsuite/ChangeLog:
PR testsuite/109360
* lib/scansarif.exp (verify-sarif-file): Use check-jsonschema
rather than jsonschema, updating the invocation accordingly.
* lib/target-supports.exp (check_effective_target_jsonschema): 
Convert
to...
(check_effective_target_check_jsonschema): ...this.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/doc/install.texi  | 7 ---
 gcc/testsuite/lib/scansarif.exp   | 8 
 gcc/testsuite/lib/target-supports.exp | 6 +++---
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 0c769165146..b5456992583 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -461,9 +461,10 @@ is shown below:
 @code{gcov}, @code{gzip}, @code{json}, @code{os} and @code{pytest}.
 
 @item SARIF testsuite
-Tests of SARIF output will use the @code{jsonschema} program from the
-@code{jsonschema} module (if available) to validate generated .sarif files.
-If this tool is not found, the validation parts of those tests are skipped.
+Tests of SARIF output will use the @code{check-jsonschema} program from
+the @code{check-jsonschema} module (if available) to validate generated
+.sarif files.  If this tool is not found, the validation parts of those
+tests are skipped.
 
 @item c++ cxx api generation
 @code{csv}, @code{os}, @code{sys} and @code{time}.
diff --git a/gcc/testsuite/lib/scansarif.exp b/gcc/testsuite/lib/scansarif.exp
index 3eb38b8102e..cc0890ef5d8 100644
--- a/gcc/testsuite/lib/scansarif.exp
+++ b/gcc/testsuite/lib/scansarif.exp
@@ -57,7 +57,7 @@ proc scan-sarif-file-not { args } {
 # Assuming python3 is available, use verify-sarif-file.py to check
 # that the .sarif file is UTF-8 encoded and is parseable as JSON.
 #
-# Assuming "jsonschema" is available, use it to verify that the .sarif
+# Assuming "check-jsonschema" is available, use it to verify that the .sarif
 # file complies with the SARIF schema.
 
 proc verify-sarif-file { args } {
@@ -86,8 +86,8 @@ proc verify-sarif-file { args } {
 # Verify that the file complies with the SARIF schema.
 
 # Check that jsonschema is installed.
-if { ![check_effective_target_jsonschema] } {
-   unsupported "$testcase verify-sarif-file: jsonschema is missing"
+if { ![check_effective_target_check_jsonschema] } {
+   unsupported "$testcase verify-sarif-file: check-jsonschema is missing"
return  
 }
 
@@ -95,7 +95,7 @@ proc verify-sarif-file { args } {
 verbose "schema_file: $schema_file" 2
 
 set what "$testcase (test .sarif output against SARIF schema)"
-if [catch {exec jsonschema --instance $output_file $schema_file} res ] {
+if [catch {exec check-jsonschema --schemafile $schema_file $output_file

[gcc r15-1556] diagnostics: remove duplicate copies of diagnostic_kind_text

2024-06-21 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:ccbcde5ec0e481e1ea775649d59691b6f5fcc5a1

commit r15-1556-gccbcde5ec0e481e1ea775649d59691b6f5fcc5a1
Author: David Malcolm 
Date:   Fri Jun 21 18:20:38 2024 -0400

diagnostics: remove duplicate copies of diagnostic_kind_text

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc
(json_output_format::on_end_diagnostic): Use
get_diagnostic_kind_text rather than embedding a duplicate copy of
the table.
* diagnostic-format-sarif.cc
(make_rule_id_for_diagnostic_kind): Likewise.
* diagnostic.cc (get_diagnostic_kind_text): New.
* diagnostic.h (get_diagnostic_kind_text): New decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc  | 8 +---
 gcc/diagnostic-format-sarif.cc | 8 +---
 gcc/diagnostic.cc  | 8 
 gcc/diagnostic.h   | 2 ++
 4 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index ec03ac15aeb..8f2ff6cfde2 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -231,14 +231,8 @@ json_output_format::on_end_diagnostic (const 
diagnostic_info &diagnostic,
 
   /* Get "kind" of diagnostic.  */
   {
-static const char *const diagnostic_kind_text[] = {
-#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
-#include "diagnostic.def"
-#undef DEFINE_DIAGNOSTIC_KIND
-  "must-not-happen"
-};
 /* Lose the trailing ": ".  */
-const char *kind_text = diagnostic_kind_text[diagnostic.kind];
+const char *kind_text = get_diagnostic_kind_text (diagnostic.kind);
 size_t len = strlen (kind_text);
 gcc_assert (len > 2);
 gcc_assert (kind_text[len - 2] == ':');
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 5581aa1579e..2745c72ea3e 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -662,14 +662,8 @@ maybe_get_sarif_level (diagnostic_t diag_kind)
 static char *
 make_rule_id_for_diagnostic_kind (diagnostic_t diag_kind)
 {
-  static const char *const diagnostic_kind_text[] = {
-#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
-#include "diagnostic.def"
-#undef DEFINE_DIAGNOSTIC_KIND
-"must-not-happen"
-  };
   /* Lose the trailing ": ".  */
-  const char *kind_text = diagnostic_kind_text[diag_kind];
+  const char *kind_text = get_diagnostic_kind_text (diag_kind);
   size_t len = strlen (kind_text);
   gcc_assert (len > 2);
   gcc_assert (kind_text[len - 2] == ':');
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index c66aa5af5ff..8fc22466b92 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -590,6 +590,14 @@ static const char *const diagnostic_kind_text[] = {
   "must-not-happen"
 };
 
+/* Get unlocalized string describing KIND.  */
+
+const char *
+get_diagnostic_kind_text (diagnostic_t kind)
+{
+  return diagnostic_kind_text[kind];
+}
+
 /* Return a malloc'd string describing a location and the severity of the
diagnostic, e.g. "foo.c:42:10: error: ".  The caller is responsible for
freeing the memory.  */
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index c6846525da3..4969f07836c 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -1121,4 +1121,6 @@ option_unspecified_p (int opt)
 
 extern char *get_cwe_url (int cwe);
 
+extern const char *get_diagnostic_kind_text (diagnostic_t kind);
+
 #endif /* ! GCC_DIAGNOSTIC_H */


[gcc r15-1555] diagnostics: move diagnostic_{event, path} functions to diagnostic-path.cc

2024-06-21 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:4819dc7d4b84afa98881ffb8471cf19bc362221b

commit r15-1555-g4819dc7d4b84afa98881ffb8471cf19bc362221b
Author: David Malcolm 
Date:   Fri Jun 21 18:20:38 2024 -0400

diagnostics: move diagnostic_{event,path} functions to diagnostic-path.cc

No functional change intended.

gcc/ChangeLog:
* diagnostic-path.cc (diagnostic_event::meaning::dump_to_pp): Move
here from diagnostic.cc.
(diagnostic_event::meaning::maybe_get_verb_str): Likewise.
(diagnostic_event::meaning::maybe_get_noun_str): Likewise.
(diagnostic_event::meaning::maybe_get_property_str): Likewise.
(diagnostic_path::get_first_event_in_a_function): Likewise.
(diagnostic_path::interprocedural_p): Likewise.
(debug): Likewise for diagnostic_path * overload.
* diagnostic.cc (diagnostic_event::meaning::dump_to_pp): Move from
here to diagnostic-path.cc.
(diagnostic_event::meaning::maybe_get_verb_str): Likewise.
(diagnostic_event::meaning::maybe_get_noun_str): Likewise.
(diagnostic_event::meaning::maybe_get_property_str): Likewise.
(diagnostic_path::get_first_event_in_a_function): Likewise.
(diagnostic_path::interprocedural_p): Likewise.
(debug): Likewise for diagnostic_path * overload.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.cc | 168 +
 gcc/diagnostic.cc  | 168 -
 2 files changed, 168 insertions(+), 168 deletions(-)

diff --git a/gcc/diagnostic-path.cc b/gcc/diagnostic-path.cc
index 882dc1c5805..ea5b1f65e02 100644
--- a/gcc/diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -45,6 +45,174 @@ along with GCC; see the file COPYING3.  If not see
 #  pragma GCC diagnostic ignored "-Wformat-diag"
 #endif
 
+/* class diagnostic_event.  */
+
+/* struct diagnostic_event::meaning.  */
+
+void
+diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
+{
+  bool need_comma = false;
+  pp_character (pp, '{');
+  if (const char *verb_str = maybe_get_verb_str (m_verb))
+{
+  pp_printf (pp, "verb: %qs", verb_str);
+  need_comma = true;
+}
+  if (const char *noun_str = maybe_get_noun_str (m_noun))
+{
+  if (need_comma)
+   pp_string (pp, ", ");
+  pp_printf (pp, "noun: %qs", noun_str);
+  need_comma = true;
+}
+  if (const char *property_str = maybe_get_property_str (m_property))
+{
+  if (need_comma)
+   pp_string (pp, ", ");
+  pp_printf (pp, "property: %qs", property_str);
+  need_comma = true;
+}
+  pp_character (pp, '}');
+}
+
+/* Get a string (or NULL) for V suitable for use within a SARIF
+   threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+
+const char *
+diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
+{
+  switch (v)
+{
+default:
+  gcc_unreachable ();
+case VERB_unknown:
+  return NULL;
+case VERB_acquire:
+  return "acquire";
+case VERB_release:
+  return "release";
+case VERB_enter:
+  return "enter";
+case VERB_exit:
+  return "exit";
+case VERB_call:
+  return "call";
+case VERB_return:
+  return "return";
+case VERB_branch:
+  return "branch";
+case VERB_danger:
+  return "danger";
+}
+}
+
+/* Get a string (or NULL) for N suitable for use within a SARIF
+   threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+
+const char *
+diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
+{
+  switch (n)
+{
+default:
+  gcc_unreachable ();
+case NOUN_unknown:
+  return NULL;
+case NOUN_taint:
+  return "taint";
+case NOUN_sensitive:
+  return "sensitive";
+case NOUN_function:
+  return "function";
+case NOUN_lock:
+  return "lock";
+case NOUN_memory:
+  return "memory";
+case NOUN_resource:
+  return "resource";
+}
+}
+
+/* Get a string (or NULL) for P suitable for use within a SARIF
+   threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+
+const char *
+diagnostic_event::meaning::maybe_get_property_str (enum property p)
+{
+  switch (p)
+{
+default:
+  gcc_unreachable ();
+case PROPERTY_unknown:
+  return NULL;
+case PROPERTY_true:
+  return "true";
+case PROPERTY_false:
+  return "false";
+}
+}
+
+/* class diagnostic_path.  */
+
+/* Subroutine of diagnostic_path::interprocedural_p.
+   Look for the first event in this path that is within a function
+   i.e. has a non-null logical location for which function_p is true.
+   If found, write its index to *OUT_IDX and return true.
+   Otherwise return false.  */
+
+bool
+diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
+{
+  const unsigned num = num_events ();
+  for (unsigned i = 0; i < num; i++)

[gcc r15-1541] testsuite: check that generated .sarif files validate against the SARIF schema [PR109360]

2024-06-21 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a84fe222029ff21903283cc8ee4bc760ebf80ec2

commit r15-1541-ga84fe222029ff21903283cc8ee4bc760ebf80ec2
Author: David Malcolm 
Date:   Fri Jun 21 08:46:14 2024 -0400

testsuite: check that generated .sarif files validate against the SARIF 
schema [PR109360]

This patch extends the dg directive verify-sarif-file so that if
the "jsonschema" tool is available, it will be used to validate the
generated .sarif file.

Tested with jsonschema 3.2 with Python 3.8

gcc/ChangeLog:
PR testsuite/109360
* doc/install.texi: Mention optional usage of "jsonschema" tool.

gcc/testsuite/ChangeLog:
PR testsuite/109360
* lib/sarif-schema-2.1.0.json: New file, downloaded from

https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json
Licensing information can be seen at
https://github.com/oasis-tcs/sarif-spec/issues/583
which states "They are free to incorporate it into their
implementation. No need for special permission or paperwork from
OASIS."
* lib/scansarif.exp (verify-sarif-file): If "jsonschema" is
available, use it to verify that the .sarif file complies with the
SARIF schema.
* lib/target-supports.exp (check_effective_target_jsonschema):
New.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/doc/install.texi  |5 +
 gcc/testsuite/lib/sarif-schema-2.1.0.json | 3370 +
 gcc/testsuite/lib/scansarif.exp   |   23 +
 gcc/testsuite/lib/target-supports.exp |   12 +
 4 files changed, 3410 insertions(+)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 1774a010889..0c769165146 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -460,6 +460,11 @@ is shown below:
 @item g++ testsuite
 @code{gcov}, @code{gzip}, @code{json}, @code{os} and @code{pytest}.
 
+@item SARIF testsuite
+Tests of SARIF output will use the @code{jsonschema} program from the
+@code{jsonschema} module (if available) to validate generated .sarif files.
+If this tool is not found, the validation parts of those tests are skipped.
+
 @item c++ cxx api generation
 @code{csv}, @code{os}, @code{sys} and @code{time}.
 
diff --git a/gcc/testsuite/lib/sarif-schema-2.1.0.json 
b/gcc/testsuite/lib/sarif-schema-2.1.0.json
new file mode 100644
index 000..e0b65245710
--- /dev/null
+++ b/gcc/testsuite/lib/sarif-schema-2.1.0.json
@@ -0,0 +1,3370 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#";,
+  "title": "Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema",
+  "$id": 
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json";,
+  "description": "Static Analysis Results Format (SARIF) Version 2.1.0 JSON 
Schema: a standard format for the output of static analysis tools.",
+  "additionalProperties": false,
+  "type": "object",
+  "properties": {
+
+"$schema": {
+  "description": "The URI of the JSON schema corresponding to the 
version.",
+  "type": "string",
+  "format": "uri"
+},
+
+"version": {
+  "description": "The SARIF format version of this log file.",
+  "enum": [ "2.1.0" ]
+},
+
+"runs": {
+  "description": "The set of runs contained in this log file.",
+  "type": "array",
+  "minItems": 0,
+  "uniqueItems": false,
+  "items": {
+"$ref": "#/definitions/run"
+  }
+},
+
+"inlineExternalProperties": {
+  "description": "References to external property files that share data 
between runs.",
+  "type": "array",
+  "minItems": 0,
+  "uniqueItems": true,
+  "items": {
+"$ref": "#/definitions/externalProperties"
+  }
+},
+
+"properties": {
+  "description": "Key/value pairs that provide additional information 
about the log file.",
+  "$ref": "#/definitions/propertyBag"
+}
+  },
+
+  "required": [ "version", "runs" ],
+
+  "definitions": {
+
+"address": {
+  "description": "A physical or virtual address, or a range of addresses, 
in an 'addressable region' (memory or a binary file).",
+  "additionalProperties": false,
+  "type": "object",
+  "properties": {
+
+"absoluteAddress": {
+  "description": "The address expressed as a byte offset from the 
start of the addressable region.",
+  "type": "integer",
+  "minimum": -1,
+  "default": -1
+
+},
+
+"relativeAddress": {
+  "description": "The address expressed as a byte offset from the 
absolute address of the top-most parent object.",
+  "type": "integer"
+
+},
+
+"length": {
+  "description": "The number of bytes in this range of addresses.",
+  "type": "integer"
+},
+
+"kind": {
+  "description": "An open-ended string that i

[gcc r15-1540] diagnostics: fixes to SARIF output [PR109360]

2024-06-21 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:9f4fdc3acebcf6b045edea1361570658da4bc0ab

commit r15-1540-g9f4fdc3acebcf6b045edea1361570658da4bc0ab
Author: David Malcolm 
Date:   Fri Jun 21 08:46:13 2024 -0400

diagnostics: fixes to SARIF output [PR109360]

When adding validation of .sarif files against the schema
(PR testsuite/109360) I discovered various issues where we were
generating invalid .sarif files.

Specifically, in
  c-c++-common/diagnostic-format-sarif-file-bad-utf8-pr109098-1.c
the relatedLocations for the "note" diagnostics were missing column
numbers, leading to validation failure due to non-unique elements,
such as multiple:
"message": {"text": "invalid UTF-8 character "}},
on line 25 with no column information.

Root cause is that for some diagnostics in libcpp we have a location_t
representing the line as a whole, setting a column_override on the
rich_location (since the line hasn't been fully read yet).  We were
handling this column override for plain text output, but not for .sarif
output.

Similarly, in diagnostic-format-sarif-file-pr111700.c there is a warning
emitted on "line 0" of the file, whereas SARIF requires line numbers to
be positive.

We also use column == 0 internally to mean "the line as a whole",
whereas SARIF required column numbers to be positive.

This patch fixes these various issues.

gcc/ChangeLog:
PR testsuite/109360
* diagnostic-format-sarif.cc
(sarif_builder::make_location_object): Pass any column override
from rich_loc to maybe_make_physical_location_object.
(sarif_builder::maybe_make_physical_location_object): Add
"column_override" param and pass it to maybe_make_region_object.
(sarif_builder::maybe_make_region_object): Add "column_override"
param and use it when the location has 0 for a column.  Don't
add "startLine", "startColumn", "endLine", or "endColumn" if
the values aren't positive.
(sarif_builder::maybe_make_region_object_for_context): Don't
add "startLine" or "endLine" if the values aren't positive.

libcpp/ChangeLog:
PR testsuite/109360
* include/rich-location.h (rich_location::get_column_override):
New accessor.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 75 ++
 libcpp/include/rich-location.h |  2 ++
 2 files changed, 56 insertions(+), 21 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 5f438dd38a8..5581aa1579e 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -243,11 +243,13 @@ private:
   json::array *maybe_make_kinds_array (diagnostic_event::meaning m) const;
   json::object *
   maybe_make_physical_location_object (location_t loc,
-  enum diagnostic_artifact_role role);
+  enum diagnostic_artifact_role role,
+  int column_override);
   json::object *make_artifact_location_object (location_t loc);
   json::object *make_artifact_location_object (const char *filename);
   json::object *make_artifact_location_object_for_pwd () const;
-  json::object *maybe_make_region_object (location_t loc) const;
+  json::object *maybe_make_region_object (location_t loc,
+ int column_override) const;
   json::object *maybe_make_region_object_for_context (location_t loc) const;
   json::object *make_region_object_for_hint (const fixit_hint &hint) const;
   json::object *make_multiformat_message_string (const char *msg) const;
@@ -924,8 +926,9 @@ sarif_builder::make_location_object (const rich_location 
&rich_loc,
   location_t loc = rich_loc.get_loc ();
 
   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
-  if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc,
-  role))
+  if (json::object *phs_loc_obj
+   = maybe_make_physical_location_object (loc, role,
+  rich_loc.get_column_override ()))
 location_obj->set ("physicalLocation", phs_loc_obj);
 
   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
@@ -946,7 +949,7 @@ sarif_builder::make_location_object (const diagnostic_event 
&event,
   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
   location_t loc = event.get_location ();
   if (json::object *phs_loc_obj
-   = maybe_make_physical_location_object (loc, role))
+   = maybe_make_physical_location_object (loc, role, 0))
 location_obj->set ("physicalLocation", phs_loc_obj);
 
   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
@@ -961,7 +964,10 @@ sarif_build

[gcc r15-1415] diagnostics: eliminate diagnostic_context::m_print_path callback

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:c371d7bdbe69201b4c91179ff6f3e2237e0e7fbe

commit r15-1415-gc371d7bdbe69201b4c91179ff6f3e2237e0e7fbe
Author: David Malcolm 
Date:   Tue Jun 18 10:59:56 2024 -0400

diagnostics: eliminate diagnostic_context::m_print_path callback

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc (diagnostic_output_format_init_json):
Replace clearing of diagnostic_context::m_print_path callback with
setting the path format to DPF_NONE.
* diagnostic-format-sarif.cc
(diagnostic_output_format_init_sarif): Likewise.
* diagnostic.cc (diagnostic_context::show_any_path): Replace call
to diagnostic_context::m_print_path callback with a direct call to
diagnostic_context::print_path.
* diagnostic.h (diagnostic_context::print_path): New decl.
(diagnostic_context::m_print_path): Delete callback.
* tree-diagnostic-path.cc (default_tree_diagnostic_path_printer):
Convert to...
(diagnostic_context::print_path): ...this.
* tree-diagnostic.cc (tree_diagnostics_defaults): Delete
initialization of m_print_path.
* tree-diagnostic.h (default_tree_diagnostic_path_printer): Delete
decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc  |  4 ++--
 gcc/diagnostic-format-sarif.cc |  4 +++-
 gcc/diagnostic.cc  |  3 +--
 gcc/diagnostic.h   |  4 ++--
 gcc/tree-diagnostic-path.cc| 23 +++
 gcc/tree-diagnostic.cc |  1 -
 gcc/tree-diagnostic.h  |  3 ---
 7 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 2bdc2c13d37b..ec03ac15aeba 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -395,8 +395,8 @@ private:
 static void
 diagnostic_output_format_init_json (diagnostic_context *context)
 {
-  /* Override callbacks.  */
-  context->m_print_path = nullptr; /* handled in json_end_diagnostic.  */
+  /* Suppress normal textual path output.  */
+  context->set_path_format (DPF_NONE);
 
   /* The metadata is handled in JSON format, rather than as text.  */
   context->set_show_cwe (false);
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 79116f051bc1..5f438dd38a88 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1991,8 +1991,10 @@ private:
 static void
 diagnostic_output_format_init_sarif (diagnostic_context *context)
 {
+  /* Suppress normal textual path output.  */
+  context->set_path_format (DPF_NONE);
+
   /* Override callbacks.  */
-  context->m_print_path = nullptr; /* handled in sarif_end_diagnostic.  */
   context->set_ice_handler_callback (sarif_ice_handler);
 
   /* The metadata is handled in SARIF format, rather than as text.  */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 844eb8e10482..471135f16dec 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -915,8 +915,7 @@ diagnostic_context::show_any_path (const diagnostic_info 
&diagnostic)
   if (!path)
 return;
 
-  if (m_print_path)
-m_print_path (this, path);
+  print_path (path);
 }
 
 /* class diagnostic_event.  */
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index ff2aa3dd9a32..c6846525da31 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -583,6 +583,8 @@ private:
   pretty_printer *pp,
   diagnostic_source_effect_info *effect_info);
 
+  void print_path (const diagnostic_path *path);
+
   /* Data members.
  Ideally, all of these would be private and have "m_" prefixes.  */
 
@@ -712,8 +714,6 @@ private:
   urlifier *m_urlifier;
 
 public:
-  void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
-
   /* Auxiliary data for client.  */
   void *m_client_aux_data;
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index adaaf30b84fd..35f8ea2b8b62 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -884,17 +884,16 @@ print_path_summary_as_text (const path_summary *ps, 
diagnostic_context *dc,
 
 } /* end of anonymous namespace for path-printing code.  */
 
-/* Print PATH to CONTEXT, according to CONTEXT's path_format.  */
+/* Print PATH according to this context's path_format.  */
 
 void
-default_tree_diagnostic_path_printer (diagnostic_context *context,
- const diagnostic_path *path)
+diagnostic_context::print_path (const diagnostic_path *path)
 {
   gcc_assert (path);
 
   const unsigned num_events = path->num_events ();
 
-  switch (context->get_path_format ())
+  switch (get_path_format ())
 {
 case DPF_NONE:
   /* Do nothing.  */
@@ -909,7 +908,7 @@ default_tree_diagnostic_path_printer (diagnostic_context 
*context,
label_text event_text (event.get_desc (false));

[gcc r15-1412] diagnostics: remove tree usage from tree-diagnostic-path.cc

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:164ac58fabc6430eed45dda7500dfba64be2bd87

commit r15-1412-g164ac58fabc6430eed45dda7500dfba64be2bd87
Author: David Malcolm 
Date:   Tue Jun 18 10:59:55 2024 -0400

diagnostics: remove tree usage from tree-diagnostic-path.cc

No functional change intended.

gcc/ChangeLog:
* Makefile.in (OBJS): Add selftest-diagnostic-path.o and
selftest-logical-location.o.
* logical-location.h: Include "label-text.h".
(class logical_location): Update leading comment.
* selftest-diagnostic-path.cc: New file, adapted from
simple-diagnostic-path.cc and from material in
tree-diagnostic-path.cc.
* selftest-diagnostic-path.h: New file, adapted from
simple-diagnostic-path.h and from material in
tree-diagnostic-path.cc.
* selftest-logical-location.cc: New file.
* selftest-logical-location.h: New file.
* tree-diagnostic-path.cc: Remove includes of "tree-pretty-print.h",
"langhooks.h", and "simple-diagnostic-path.h".  Add include of
"selftest-diagnostic-path.h".
(class test_diagnostic_path): Delete, in favor of new
implementation in selftest-diagnostic-path.{h,cc}, which is
directly derived from diagnostic_path, rather than from
simple_diagnostic_path.
(selftest::test_intraprocedural_path): Eliminate tree usage,
via change to test_diagnostic_path, using strings rather than
function_decls for identifying functions in the test.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(selftest::assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in  |   2 +
 gcc/logical-location.h   |   5 +-
 gcc/selftest-diagnostic-path.cc  | 233 +++
 gcc/selftest-diagnostic-path.h   | 163 +++
 gcc/selftest-logical-location.cc |  71 
 gcc/selftest-logical-location.h  |  58 ++
 gcc/tree-diagnostic-path.cc  | 161 ---
 7 files changed, 580 insertions(+), 113 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 35f259da858d..a2799b8d8262 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,6 +1700,8 @@ OBJS = \
ubsan.o \
sanopt.o \
sancov.o \
+   selftest-diagnostic-path.o \
+   selftest-logical-location.o \
simple-diagnostic-path.o \
tree-call-cdce.o \
tree-cfg.o \
diff --git a/gcc/logical-location.h b/gcc/logical-location.h
index c3b72081135b..bba210877862 100644
--- a/gcc/logical-location.h
+++ b/gcc/logical-location.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_LOGICAL_LOCATION_H
 #define GCC_LOGICAL_LOCATION_H
 
+#include "label-text.h"
+
 /* An enum for discriminating between different kinds of logical location
for a diagnostic.
 
@@ -46,7 +48,8 @@ enum logical_location_kind
- "within function 'foo'", or
- "within method 'bar'",
but *without* requiring knowledge of trees
-   (see tree-logical-location.h for subclasses relating to trees).  */
+   (see tree-logical-location.h for concrete subclasses relating to trees,
+   and selftest-logical-location.h for a concrete subclass for selftests).  */
 
 class logical_location
 {
diff --git a/gcc/selftest-diagnostic-path.cc b/gcc/selftest-diagnostic-path.cc
new file mode 100644
index ..6d21f2e55999
--- /dev/null
+++ b/gcc/selftest-diagnostic-path.cc
@@ -0,0 +1,233 @@
+/* Concrete classes for selftests involving diagnostic paths.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm 
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+
+#include "config.h"
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "version.h"
+#include "demangle.h"
+#inc

[gcc r15-1411] diagnostics: eliminate "tree" from diagnostic_{event, path}

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d0334e7798c4be9f6eac5fd9b6273a0ea31b1360

commit r15-1411-gd0334e7798c4be9f6eac5fd9b6273a0ea31b1360
Author: David Malcolm 
Date:   Tue Jun 18 10:59:54 2024 -0400

diagnostics: eliminate "tree" from diagnostic_{event,path}

This patch eliminates the use of "tree" from diagnostic_{event,path} in
favor of const logical_location *.

No functional change intended.

gcc/analyzer/ChangeLog:
* checker-event.h (checker_event::fndecl): Drop "final" and
"override", converting from a vfunc implementation to a plain
accessor.
* checker-path.cc (checker_path::same_function_p): New.
* checker-path.h (checker_path::same_function_p): New decl.

gcc/ChangeLog:
* diagnostic.cc: Include "logical-location.h".
(diagnostic_path::get_first_event_in_a_function): Fix typo in
leading comment.  Rewrite to use logical_location rather than
tree.  Drop test on stack depth.
(diagnostic_path::interprocedural_p): Rewrite to use
logical_location rather than tree.
(logical_location::function_p): New.
* diagnostic-path.h (diagnostic_event::get_fndecl): Eliminate
vfunc.
(diagnostic_path::same_function_p): New pure virtual func.
* logical-location.h (logical_location::get_name_for_path_output):
New pure virtual func.
* simple-diagnostic-path.cc
(simple_diagnostic_path::same_function_p): New.
(simple_diagnostic_event::simple_diagnostic_event): Initialize
m_logical_loc.
* simple-diagnostic-path.h: Include "tree-logical-location.h".
(simple_diagnostic_event::get_fndecl): Convert from a vfunc
implementation to an accessor.
(simple_diagnostic_event::get_logical_location): Use
m_logical_loc.
(simple_diagnostic_event::m_logical_loc): New field.
(simple_diagnostic_path::same_function_p): New decl.
* tree-diagnostic-path.cc: Move pragma disabling -Wformat-diag to
cover the whole file.
(can_consolidate_events): Add params "path", "ev1_idx", and
"ev2_idx".  Rewrite to use diagnostic_path::same_function_p rather
than tree.
(per_thread_summary::per_thread_summary): Add "path" param
(per_thread_summary::m_path): New field.
(event_range::event_range): Update for conversion of m_fndecl to
m_logical_loc.
(event_range::maybe_add_event): Rename param "idx" to
"new_ev_idx".  Update call to can_consolidate_events to pass in
"m_path", "m_start_idx", and "new_ev_idx".
(event_range::m_fndecl): Replace with...
(event_range::m_logical_loc): ...this.
(path_summary::get_or_create_events_for_thread_id): Pass "path" to
per_thread_summary ctor.
(per_thread_summary::interprocedural_p): Rewrite to use
diagnostic_path::same_function_p rather than tree.
(print_fndecl): Delete.
(thread_event_printer::print_swimlane_for_event_range): Update for
conversion from tree to logical_location.
(default_tree_diagnostic_path_printer): Likewise.
(default_tree_make_json_for_path): Likewise.
* tree-logical-location.cc: Include "intl.h".
(compiler_logical_location::get_name_for_tree_for_path_output):
New.
(tree_logical_location::get_name_for_path_output): New.
(current_fndecl_logical_location::get_name_for_path_output): New.
* tree-logical-location.h
(compiler_logical_location::get_name_for_tree_for_path_output):
New decl.
(tree_logical_location::get_name_for_path_output): New decl.
(current_fndecl_logical_location::get_name_for_path_output): New
decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/checker-event.h  |   2 +-
 gcc/analyzer/checker-path.cc  |   8 
 gcc/analyzer/checker-path.h   |   4 ++
 gcc/diagnostic-path.h |  10 ++--
 gcc/diagnostic.cc |  47 +++
 gcc/logical-location.h|   5 ++
 gcc/simple-diagnostic-path.cc |  11 -
 gcc/simple-diagnostic-path.h  |  13 +-
 gcc/tree-diagnostic-path.cc   | 103 --
 gcc/tree-logical-location.cc  |  25 ++
 gcc/tree-logical-location.h   |   3 ++
 11 files changed, 161 insertions(+), 70 deletions(-)

diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index d0935aca9853..4343641f441c 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -91,7 +91,6 @@ public:
   /* Implementation of diagnostic_event.  */
 
   location_t get_location () const final override { return m_loc; }
-  tree get_fndecl () c

[gcc r15-1410] diagnostics: move simple_diagnostic_{path, thread, event} to their own .h/cc

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:f89f9c7ae7190c700d1b3727a3fd66e90cfb90ac

commit r15-1410-gf89f9c7ae7190c700d1b3727a3fd66e90cfb90ac
Author: David Malcolm 
Date:   Tue Jun 18 10:59:54 2024 -0400

diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc

As work towards eliminating the dependency on "tree" from
path-printing, move these classes to a new simple-diagnostic-path.h/cc.

No functional change intended.

gcc/analyzer/ChangeLog:
* checker-path.h: Include "simple-diagnostic-path.h".

gcc/ChangeLog:
* Makefile.in (OBJS): Add simple-diagnostic-path.o.
* diagnostic-path.h (class simple_diagnostic_event): Move to
simple-diagnostic-path.h.
(class simple_diagnostic_thread): Likewise.
(class simple_diagnostic_path): Likewise.
* diagnostic.cc (simple_diagnostic_path::simple_diagnostic_path):
Move to simple-diagnostic-path.cc.
(simple_diagnostic_path::num_events): Likewise.
(simple_diagnostic_path::get_event): Likewise.
(simple_diagnostic_path::num_threads): Likewise.
(simple_diagnostic_path::get_thread): Likewise.
(simple_diagnostic_path::add_thread): Likewise.
(simple_diagnostic_path::add_event): Likewise.
(simple_diagnostic_path::add_thread_event): Likewise.
(simple_diagnostic_path::connect_to_next_event): Likewise.
(simple_diagnostic_event::simple_diagnostic_event): Likewise.
(simple_diagnostic_event::~simple_diagnostic_event): Likewise.
* selftest-run-tests.cc (selftest::run_tests): Call
selftest::simple_diagnostic_path_cc_tests.
* selftest.h (selftest::simple_diagnostic_path_cc_tests): New
decl.
* simple-diagnostic-path.cc: New file, from the above material.
* simple-diagnostic-path.h: New file, from the above material
from diagnostic-path.h.
* tree-diagnostic-path.cc: Include "simple-diagnostic-path.h".

gcc/testsuite/ChangeLog
* gcc.dg/plugin/diagnostic_plugin_test_paths.c: Include
"simple-diagnostic-path.h".

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in|   1 +
 gcc/analyzer/checker-path.h|   1 +
 gcc/diagnostic-path.h  | 104 +-
 gcc/diagnostic.cc  | 149 --
 gcc/selftest-run-tests.cc  |   1 +
 gcc/selftest.h |   1 +
 gcc/simple-diagnostic-path.cc  | 228 +
 gcc/simple-diagnostic-path.h   | 130 
 .../gcc.dg/plugin/diagnostic_plugin_test_paths.c   |   1 +
 gcc/tree-diagnostic-path.cc|   1 +
 10 files changed, 366 insertions(+), 251 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f5adb647d3fb..35f259da858d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,6 +1700,7 @@ OBJS = \
ubsan.o \
sanopt.o \
sancov.o \
+   simple-diagnostic-path.o \
tree-call-cdce.o \
tree-cfg.o \
tree-cfgcleanup.o \
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 6b3e8a34fe56..162ebb3f0d83 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_CHECKER_PATH_H
 
 #include "analyzer/checker-event.h"
+#include "simple-diagnostic-path.h"
 
 namespace ana {
 
diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index 938bd583a3da..958eb725322a 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -201,108 +201,8 @@ private:
   bool get_first_event_in_a_function (unsigned *out_idx) const;
 };
 
-/* Concrete subclasses.  */
-
-/* A simple implementation of diagnostic_event.  */
-
-class simple_diagnostic_event : public diagnostic_event
-{
- public:
-  simple_diagnostic_event (location_t loc, tree fndecl, int depth,
-  const char *desc,
-  diagnostic_thread_id_t thread_id = 0);
-  ~simple_diagnostic_event ();
-
-  location_t get_location () const final override { return m_loc; }
-  tree get_fndecl () const final override { return m_fndecl; }
-  int get_stack_depth () const final override { return m_depth; }
-  label_text get_desc (bool) const final override
-  {
-return label_text::borrow (m_desc);
-  }
-  const logical_location *get_logical_location () const final override
-  {
-return NULL;
-  }
-  meaning get_meaning () const final override
-  {
-return meaning ();
-  }
-  bool connect_to_next_event_p () const final override
-  {
-return m_connected_to_next_event;
-  }
-  diagnostic_thread_id_t get_thread_id () const final override
-  {
-ret

[gcc r15-1416] diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:524cdf4dab610e6e53b3b033eacbdb1a03687cc7

commit r15-1416-g524cdf4dab610e6e53b3b033eacbdb1a03687cc7
Author: David Malcolm 
Date:   Tue Jun 18 10:59:56 2024 -0400

diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc

Now that nothing in tree-diagnostic-path.cc uses "tree", this patch
renames it to diagnostic-path.cc and moves it from OBJS to
OBJS-libcommon.

No functional change intended.

gcc/ChangeLog:
* Makefile.in (OBJS): Move selftest-diagnostic-path.o,
selftest-logical-location.o, and tree-diagnostic-path.o to...
(OBJS-libcommon): ...here, renaming tree-diagnostic-path.o to
diagnostic-path.o.
* tree-diagnostic-path.cc: Rename to...
* diagnostic-path.cc: ...this.  Drop include of "tree.h".
(tree_diagnostic_path_cc_tests): Rename to...
(diagnostic_path_cc_tests): ...this.
* selftest-run-tests.cc (selftest::run_tests): Update for above
renaming.
* selftest.h (tree_diagnostic_path_cc_tests): Rename decl to...
(diagnostic_path_cc_tests): ...this.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in | 6 +++---
 gcc/{tree-diagnostic-path.cc => diagnostic-path.cc} | 3 +--
 gcc/selftest-run-tests.cc   | 2 +-
 gcc/selftest.h  | 2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e701d9fb0829..638ea6b2307b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,8 +1700,6 @@ OBJS = \
ubsan.o \
sanopt.o \
sancov.o \
-   selftest-diagnostic-path.o \
-   selftest-logical-location.o \
simple-diagnostic-path.o \
tree-call-cdce.o \
tree-cfg.o \
@@ -1712,7 +1710,6 @@ OBJS = \
tree-dfa.o \
tree-diagnostic.o \
tree-diagnostic-client-data-hooks.o \
-   tree-diagnostic-path.o \
tree-dump.o \
tree-eh.o \
tree-emutls.o \
@@ -1827,6 +1824,7 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o 
diagnostic-color.o \
diagnostic-format-json.o \
diagnostic-format-sarif.o \
diagnostic-macro-unwinding.o \
+   diagnostic-path.o \
diagnostic-show-locus.o \
edit-context.o \
pretty-print.o intl.o \
@@ -1834,6 +1832,8 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o 
diagnostic-color.o \
sbitmap.o \
vec.o input.o hash-table.o ggc-none.o memory-block.o \
selftest.o selftest-diagnostic.o sort.o \
+   selftest-diagnostic-path.o \
+   selftest-logical-location.o \
text-art/box-drawing.o \
text-art/canvas.o \
text-art/ruler.o \
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/diagnostic-path.cc
similarity index 99%
rename from gcc/tree-diagnostic-path.cc
rename to gcc/diagnostic-path.cc
index 35f8ea2b8b62..882dc1c5805f 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -25,7 +25,6 @@ along with GCC; see the file COPYING3.  If not see
 #define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
-#include "tree.h"
 #include "diagnostic.h"
 #include "diagnostic-macro-unwinding.h"
 #include "intl.h"
@@ -2199,7 +2198,7 @@ control_flow_tests (const line_table_case &case_)
 /* Run all of the selftests within this file.  */
 
 void
-tree_diagnostic_path_cc_tests ()
+diagnostic_path_cc_tests ()
 {
   /* In a few places we use the global dc's printer to determine
  colorization so ensure this off during the tests.  */
diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc
index 3275db38ba92..e6779206c470 100644
--- a/gcc/selftest-run-tests.cc
+++ b/gcc/selftest-run-tests.cc
@@ -102,7 +102,7 @@ selftest::run_tests ()
   spellcheck_cc_tests ();
   spellcheck_tree_cc_tests ();
   tree_cfg_cc_tests ();
-  tree_diagnostic_path_cc_tests ();
+  diagnostic_path_cc_tests ();
   simple_diagnostic_path_cc_tests ();
   attribs_cc_tests ();
 
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 2d1aa91607e3..dcb1463ed906 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -222,6 +222,7 @@ extern void cgraph_cc_tests ();
 extern void convert_cc_tests ();
 extern void diagnostic_color_cc_tests ();
 extern void diagnostic_format_json_cc_tests ();
+extern void diagnostic_path_cc_tests ();
 extern void diagnostic_show_locus_cc_tests ();
 extern void digraph_cc_tests ();
 extern void dumpfile_cc_tests ();
@@ -259,7 +260,6 @@ extern void sreal_cc_tests ();
 extern void store_merging_cc_tests ();
 extern void tree_cc_tests ();
 extern void tree_cfg_cc_tests ();
-extern void tree_diagnostic_path_cc_tests ();
 extern void tristate_cc_tests ();
 extern void typed_splay_tree_cc_tests ();
 extern void vec_cc_tests ();


[gcc r15-1414] diagnostics: introduce diagnostic-macro-unwinding.h/cc

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:bdcfe7f7f50ec64b45581a175d1eca41c74a3dfe

commit r15-1414-gbdcfe7f7f50ec64b45581a175d1eca41c74a3dfe
Author: David Malcolm 
Date:   Tue Jun 18 10:59:56 2024 -0400

diagnostics: introduce diagnostic-macro-unwinding.h/cc

Eliminate a dependency on "tree" from the code used by
diagnostic_path handling.

No functional change intended.

gcc/ChangeLog:
* Makefile.in (OBJS): Add diagnostic-macro-unwinding.o.

gcc/c-family/ChangeLog:
* c-opts.cc: Replace include of "tree-diagnostic.h" with
"diagnostic-macro-unwinding.h".

gcc/ChangeLog:
* diagnostic-macro-unwinding.cc: New file, with material taken
from tree-diagnostic.cc.
* diagnostic-macro-unwinding.h: New file, with material taken
from tree-diagnostic.h.
* tree-diagnostic-path.cc: Repalce include of "tree-diagnostic.h"
with "diagnostic-macro-unwinding.h".
* tree-diagnostic.cc (struct loc_map_pair): Move to
diagnostic-macro-unwinding.cc.
(maybe_unwind_expanded_macro_loc): Likewise.
(virt_loc_aware_diagnostic_finalizer): Likewise.
* tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer): Move
decl to diagnostic-macro-unwinding.h.
(maybe_unwind_expanded_macro_loc): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in   |   1 +
 gcc/c-family/c-opts.cc|   2 +-
 gcc/diagnostic-macro-unwinding.cc | 221 ++
 gcc/diagnostic-macro-unwinding.h  |  29 +
 gcc/tree-diagnostic-path.cc   |   2 +-
 gcc/tree-diagnostic.cc| 195 -
 gcc/tree-diagnostic.h |   5 -
 7 files changed, 253 insertions(+), 202 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a2799b8d8262..e701d9fb0829 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1826,6 +1826,7 @@ OBJS = \
 OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
diagnostic-format-json.o \
diagnostic-format-sarif.o \
+   diagnostic-macro-unwinding.o \
diagnostic-show-locus.o \
edit-context.o \
pretty-print.o intl.o \
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index faaf9ee63509..33114f13c8db 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -32,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "toplev.h"
 #include "langhooks.h"
-#include "tree-diagnostic.h" /* for virt_loc_aware_diagnostic_finalizer */
+#include "diagnostic-macro-unwinding.h" /* for 
virt_loc_aware_diagnostic_finalizer */
 #include "intl.h"
 #include "cppdefault.h"
 #include "incpath.h"
diff --git a/gcc/diagnostic-macro-unwinding.cc 
b/gcc/diagnostic-macro-unwinding.cc
new file mode 100644
index ..3056d8c8afb1
--- /dev/null
+++ b/gcc/diagnostic-macro-unwinding.cc
@@ -0,0 +1,221 @@
+/* Code for unwinding macro expansions in diagnostics.
+   Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "diagnostic.h"
+#include "diagnostic-macro-unwinding.h"
+#include "intl.h"
+
+/* This is a pair made of a location and the line map it originated
+   from.  It's used in the maybe_unwind_expanded_macro_loc function
+   below.  */
+struct loc_map_pair
+{
+  const line_map_macro *map;
+  location_t where;
+};
+
+
+/* Unwind the different macro expansions that lead to the token which
+   location is WHERE and emit diagnostics showing the resulting
+   unwound macro expansion trace.  Let's look at an example to see how
+   the trace looks like.  Suppose we have this piece of code,
+   artificially annotated with the line numbers to increase
+   legibility:
+
+$ cat -n test.c
+  1#define OPERATE(OPRD1, OPRT, OPRD2) \
+  2  OPRD1 OPRT OPRD2;
+  3
+  4#define SHIFTL(A,B) \
+  5  OPERATE (A,<<,B)
+  6
+  7#define MULT(A) \
+  8  SHIFTL (A,1)
+  9
+ 10void
+ 11g ()
+ 12{
+ 13  MULT (1.0);// 1.0 << 1; <-- so this is an error.
+ 14}
+
+   Here is the diagnostic that we want the compiler to gener

[gcc r15-1413] diagnostics: eliminate diagnostic_context::m_make_json_for_path

2024-06-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d3878c85f331c7a378245b636d5d230735b87347

commit r15-1413-gd3878c85f331c7a378245b636d5d230735b87347
Author: David Malcolm 
Date:   Tue Jun 18 10:59:55 2024 -0400

diagnostics: eliminate diagnostic_context::m_make_json_for_path

Now that the path-handling code for json_output_format no longer
needs "tree", and thus can be in OBJS-libcommon we can move it
from tree-diagnostic-path.cc to diagnostic-format-json.cc where it
should have been all along.

No functional change intended.

gcc/ChangeLog:
* diagnostic-format-json.cc: Include "diagnostic-path.h" and
"logical-location.h".
(make_json_for_path): Move tree-diagnostic-path.cc's
default_tree_make_json_for_path here, renaming it and making it
static.
(json_output_format::on_end_diagnostic): Replace call of
m_context's m_make_json_for_path callback with a direct call to
make_json_for_path.
* diagnostic.h (diagnostic_context::m_make_json_for_path): Drop
field.
* tree-diagnostic-path.cc: Drop include of "json.h".
(default_tree_make_json_for_path): Rename to make_json_for_path
and move to diagnostic-format-json.cc.
* tree-diagnostic.cc (tree_diagnostics_defaults): Drop
initialization of m_make_json_for_path.
* tree-diagnostic.h (default_tree_make_json_for): Delete decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-json.cc | 37 ++---
 gcc/diagnostic.h  |  2 --
 gcc/tree-diagnostic-path.cc   | 32 
 gcc/tree-diagnostic.cc|  1 -
 gcc/tree-diagnostic.h |  2 --
 5 files changed, 34 insertions(+), 40 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 0782ae831eba..2bdc2c13d37b 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -25,8 +25,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "selftest-diagnostic.h"
 #include "diagnostic-metadata.h"
+#include "diagnostic-path.h"
 #include "json.h"
 #include "selftest.h"
+#include "logical-location.h"
 
 /* Subclass of diagnostic_output_format for JSON output.  */
 
@@ -187,6 +189,36 @@ json_from_metadata (const diagnostic_metadata *metadata)
   return metadata_obj;
 }
 
+/* Make a JSON value for PATH.  */
+
+static json::value *
+make_json_for_path (diagnostic_context *context,
+   const diagnostic_path *path)
+{
+  json::array *path_array = new json::array ();
+  for (unsigned i = 0; i < path->num_events (); i++)
+{
+  const diagnostic_event &event = path->get_event (i);
+
+  json::object *event_obj = new json::object ();
+  if (event.get_location ())
+   event_obj->set ("location",
+   json_from_expanded_location (context,
+event.get_location ()));
+  label_text event_text (event.get_desc (false));
+  event_obj->set_string ("description", event_text.get ());
+  if (const logical_location *logical_loc = event.get_logical_location ())
+   {
+ label_text name (logical_loc->get_name_for_path_output ());
+ event_obj->set_string ("function", name.get ());
+   }
+  event_obj->set_integer ("depth", event.get_stack_depth ());
+  path_array->append (event_obj);
+}
+  return path_array;
+}
+
+
 /* Implementation of "on_end_diagnostic" vfunc for JSON output.
Generate a JSON object for DIAGNOSTIC, and store for output
within current diagnostic group.  */
@@ -291,10 +323,9 @@ json_output_format::on_end_diagnostic (const 
diagnostic_info &diagnostic,
 }
 
   const diagnostic_path *path = richloc->get_path ();
-  if (path && m_context.m_make_json_for_path)
+  if (path)
 {
-  json::value *path_value
-   = m_context.m_make_json_for_path (&m_context, path);
+  json::value *path_value = make_json_for_path (&m_context, path);
   diag_obj->set ("path", path_value);
 }
 
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 9a9571bb76d4..ff2aa3dd9a32 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -713,8 +713,6 @@ private:
 
 public:
   void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
-  json::value *(*m_make_json_for_path) (diagnostic_context *,
-   const diagnostic_path *);
 
   /* Auxiliary data for client.  */
   void *m_client_aux_data;
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 39a85d330153..40b197d971cf 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-diagnostic.h"
 #include "intl.h"
 #include "diagnostic-path.h"
-#include "json.h"
 #include "gcc-rich-location.h"

[gcc r15-1220] pretty_printer: unbreak build on aarch64 [PR115465]

2024-06-12 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:e35f4eab68773b08324f9784ca69f8ace3c657cc

commit r15-1220-ge35f4eab68773b08324f9784ca69f8ace3c657cc
Author: David Malcolm 
Date:   Wed Jun 12 14:24:47 2024 -0400

pretty_printer: unbreak build on aarch64 [PR115465]

I missed this target-specific usage of pretty_printer::buffer when
making the fields private in r15-1209-gc5e3be456888aa; sorry.

gcc/ChangeLog:
PR bootstrap/115465
* config/aarch64/aarch64-early-ra.cc (early_ra::process_block):
Update for fields of pretty_printer becoming private in
r15-1209-gc5e3be456888aa.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/config/aarch64/aarch64-early-ra.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc 
b/gcc/config/aarch64/aarch64-early-ra.cc
index 1e2c823cb2eb..99324423ee5a 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -3446,7 +3446,7 @@ early_ra::process_block (basic_block bb, bool is_isolated)
fprintf (dump_file, "\nBlock %d:\n", bb->index);
  fprintf (dump_file, "%6d:", m_current_point);
  pretty_printer rtl_slim_pp;
- rtl_slim_pp.buffer->stream = dump_file;
+ rtl_slim_pp.set_output_stream (dump_file);
  print_insn (&rtl_slim_pp, insn, 1);
  pp_flush (&rtl_slim_pp);
  fprintf (dump_file, "\n");


[gcc r15-1210] pretty_printer: convert chunk_info into a class

2024-06-12 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:1cae1a5ce088c1fa351b5752d43de52f1f116a75

commit r15-1210-g1cae1a5ce088c1fa351b5752d43de52f1f116a75
Author: David Malcolm 
Date:   Wed Jun 12 09:15:09 2024 -0400

pretty_printer: convert chunk_info into a class

No functional change intended.

gcc/cp/ChangeLog:
* error.cc (append_formatted_chunk): Move part of body into
chunk_info::append_formatted_chunk.

gcc/ChangeLog:
* dumpfile.cc (dump_pretty_printer::emit_items): Update for
changes to chunk_info.
* pretty-print.cc (chunk_info::append_formatted_chunk): New, based
on code in cp/error.cc's append_formatted_chunk.
(chunk_info::pop_from_output_buffer): New, based on code in
pp_output_formatted_text and dump_pretty_printer::emit_items.
(on_begin_quote): Convert to...
(chunk_info::on_begin_quote): ...this.
(on_end_quote): Convert to...
(chunk_info::on_end_quote): ...this.
(pretty_printer::format): Update for chunk_info becoming a class
and its fields gaining "m_" prefixes.  Update for on_begin_quote
and on_end_quote moving to chunk_info.
(quoting_info::handle_phase_3): Update for changes to chunk_info.
(pp_output_formatted_text): Likewise.  Move cleanup code to
chunk_info::pop_from_output_buffer.
* pretty-print.h (class output_buffer): New forward decl.
(class urlifier): New forward decl.
(struct chunk_info): Convert to...
(class chunk_info): ...this.  Add friend class pretty_printer.
(chunk_info::get_args): New accessor.
(chunk_info::get_quoting_info): New accessor.
(chunk_info::append_formatted_chunk): New decl.
(chunk_info::pop_from_output_buffer): New decl.
(chunk_info::on_begin_quote): New decl.
(chunk_info::on_end_quote): New decl.
(chunk_info::prev): Rename to...
(chunk_info::m_prev): ...this.
(chunk_info::args): Rename to...
(chunk_info::m_args): ...this.
(output_buffer::cur_chunk_array): Drop "struct" from decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/cp/error.cc | 10 ++
 gcc/dumpfile.cc |  9 ++---
 gcc/pretty-print.cc | 96 -
 gcc/pretty-print.h  | 30 ++---
 4 files changed, 90 insertions(+), 55 deletions(-)

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 01ad794df8e3..171a352c85fd 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -4307,14 +4307,8 @@ static void
 append_formatted_chunk (pretty_printer *pp, const char *content)
 {
   output_buffer *buffer = pp_buffer (pp);
-  struct chunk_info *chunk_array = buffer->cur_chunk_array;
-  const char **args = chunk_array->args;
-
-  unsigned int chunk_idx;
-  for (chunk_idx = 0; args[chunk_idx]; chunk_idx++)
-;
-  args[chunk_idx++] = content;
-  args[chunk_idx] = NULL;
+  chunk_info *chunk_array = buffer->cur_chunk_array;
+  chunk_array->append_formatted_chunk (content);
 }
 
 /* Create a copy of CONTENT, with quotes added, and,
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 097f9bcfff21..82bd8b06bebf 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -819,8 +819,8 @@ void
 dump_pretty_printer::emit_items (optinfo *dest)
 {
   output_buffer *buffer = pp_buffer (this);
-  struct chunk_info *chunk_array = buffer->cur_chunk_array;
-  const char **args = chunk_array->args;
+  chunk_info *chunk_array = buffer->cur_chunk_array;
+  const char * const *args = chunk_array->get_args ();
 
   gcc_assert (buffer->obstack == &buffer->formatted_obstack);
   gcc_assert (buffer->line_length == 0);
@@ -847,10 +847,7 @@ dump_pretty_printer::emit_items (optinfo *dest)
   /* Ensure that we consumed all of stashed_items.  */
   gcc_assert (stashed_item_idx == m_stashed_items.length ());
 
-  /* Deallocate the chunk structure and everything after it (i.e. the
- associated series of formatted strings).  */
-  buffer->cur_chunk_array = chunk_array->prev;
-  obstack_free (&buffer->chunk_obstack, chunk_array);
+  chunk_array->pop_from_output_buffer (*buffer);
 }
 
 /* Subroutine of dump_pretty_printer::emit_items
diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc
index 271cd650c4d1..639e2b881586 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -1239,29 +1239,53 @@ private:
   std::vector m_phase_3_quotes;
 };
 
-static void
-on_begin_quote (const output_buffer &buf,
-   unsigned chunk_idx,
-   const urlifier *urlifier)
+/* Adds a chunk to the end of formatted output, so that it
+   will be printed by pp_output_formatted_text.  */
+
+void
+chunk_info::append_formatted_chunk (const char *content)
+{
+  unsigned int chunk_idx;
+  for (chunk_idx = 0; m_args[chunk_idx]; chunk_idx++)
+;
+  m_args[chunk_idx++] = content;
+  m_args[chunk_i

[gcc r15-1209] pretty_printer: make all fields private

2024-06-12 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:c5e3be456888aa48f591512ec28183703e70978c

commit r15-1209-gc5e3be456888aa48f591512ec28183703e70978c
Author: David Malcolm 
Date:   Wed Jun 12 09:15:09 2024 -0400

pretty_printer: make all fields private

No functional change intended.

gcc/analyzer/ChangeLog:
* access-diagram.cc (access_range::dump): Update for fields of
pretty_printer becoming private.
* call-details.cc (call_details::dump): Likewise.
* call-summary.cc (call_summary::dump): Likewise.
(call_summary_replay::dump): Likewise.
* checker-event.cc (checker_event::debug): Likewise.
* constraint-manager.cc (range::dump): Likewise.
(bounded_range::dump): Likewise.
(constraint_manager::dump): Likewise.
* engine.cc (exploded_node::dump): Likewise.
(exploded_path::dump): Likewise.
(exploded_path::dump_to_file): Likewise.
* feasible-graph.cc (feasible_graph::dump_feasible_path): Likewise.
* program-point.cc (program_point::dump): Likewise.
* program-state.cc (extrinsic_state::dump_to_file): Likewise.
(sm_state_map::dump): Likewise.
(program_state::dump_to_file): Likewise.
* ranges.cc (symbolic_byte_offset::dump): Likewise.
(symbolic_byte_range::dump): Likewise.
* record-layout.cc (record_layout::dump): Likewise.
* region-model-reachability.cc (reachable_regions::dump): Likewise.
* region-model.cc (region_to_value_map::dump): Likewise.
(region_model::dump): Likewise.
(model_merger::dump): Likewise.
* region-model.h (one_way_id_map::dump): Likewise.
* region.cc (region_offset::dump): Likewise.
(region::dump): Likewise.
* sm-malloc.cc (deallocator_set::dump): Likewise.
* store.cc (uncertainty_t::dump): Likewise.
(binding_key::dump): Likewise.
(bit_range::dump): Likewise.
(byte_range::dump): Likewise.
(binding_map::dump): Likewise.
(binding_cluster::dump): Likewise.
(store::dump): Likewise.
* supergraph.cc (supergraph::dump_dot_to_file): Likewise.
(superedge::dump): Likewise.
* svalue.cc (svalue::dump): Likewise.

gcc/c-family/ChangeLog:
* c-ada-spec.cc (dump_ads): Update for fields of pretty_printer
becoming private.
* c-pretty-print.cc: Likewise throughout.

gcc/c/ChangeLog:
* c-objc-common.cc (print_type): Update for fields of
pretty_printer becoming private.
(c_tree_printer): Likewise.

gcc/cp/ChangeLog:
* cxx-pretty-print.cc: Update throughout for fields of
pretty_printer becoming private.
* error.cc: Likewise.

gcc/ChangeLog:
* diagnostic.cc (diagnostic_context::urls_init): Update for fields
of pretty_printer becoming private.
(diagnostic_context::print_any_cwe): Likewise.
(diagnostic_context::print_any_rules): Likewise.
(diagnostic_context::print_option_information): Likewise.
* diagnostic.h (diagnostic_format_decoder): Likewise.
(diagnostic_prefixing_rule): Likewise, fixing typo.
* digraph.cc (test_dump_to_dot): Likewise.
* digraph.h (digraph::dump_dot_to_file): Likewise.
* dumpfile.cc
(dump_pretty_printer::emit_any_pending_textual_chunks): Likewise.
* gimple-pretty-print.cc (print_gimple_stmt): Likewise.
(print_gimple_expr): Likewise.
(print_gimple_seq): Likewise.
(dump_ssaname_info_to_file): Likewise.
(gimple_dump_bb): Likewise.
* graph.cc (print_graph_cfg): Likewise.
(start_graph_dump): Likewise.
* langhooks.cc (lhd_print_error_function): Likewise.
* lto-wrapper.cc (print_lto_docs_link): Likewise.
* pretty-print.cc (pp_set_real_maximum_length): Convert to...
(pretty_printer::set_real_maximum_length): ...this.
(pp_clear_state): Convert to...
(pretty_printer::clear_state): ...this.
(pp_wrap_text): Update for pp_remaining_character_count_for_line
becoming a member function.
(urlify_quoted_string): Update for fields of pretty_printer becoming
private.
(pp_format): Convert to...
(pretty_printer::format): ...this.  Reduce the scope of local
variables "old_line_length" and "old_wrapping_mode" and make
const.  Reduce the scope of locals "args", "new_chunk_array",
"curarg", "any_unnumbered", and "any_numbered".
(pp_output_formatted_text): Update for fields of pretty_printer
becoming private.
(pp_flush): L

[gcc r15-1108] analyzer: eliminate cast_region::m_original_region

2024-06-07 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:70f26314b62e2d636b1f2d3db43e75abb026e535

commit r15-1108-g70f26314b62e2d636b1f2d3db43e75abb026e535
Author: David Malcolm 
Date:   Fri Jun 7 16:14:29 2024 -0400

analyzer: eliminate cast_region::m_original_region

cast_region had its own field m_original_region, rather than
simply using region::m_parent, leading to lots of pointless
special-casing of RK_CAST.

Remove the field and simply use the parent region.

Doing so revealed a bug (seen in gcc.dg/analyzer/taint-alloc-4.c)
where region_model::get_representative_path_var_1's RK_CAST case
was always failing, due to using the "parent region" (actually
that of the original region's parent), rather than the original region;
the patch fixes the bug by removing the distinction.

gcc/analyzer/ChangeLog:
* call-summary.cc
(call_summary_replay::convert_region_from_summary_1): Update
for removal of cast_region::m_original_region.
* region-model-manager.cc
(region_model_manager::get_or_create_initial_value): Likewise.
* region-model.cc (region_model::get_store_value): Likewise.
* region.cc (region::get_base_region): Likewise.
(region::descendent_of_p): Likewise.
(region::maybe_get_frame_region): Likewise.
(region::get_memory_space): Likewise.
(region::calc_offset): Likewise.
(cast_region::accept): Delete.
(cast_region::dump_to_pp): Update for removal of
cast_region::m_original_region.
(cast_region::add_dump_widget_children): Delete.
* region.h (struct cast_region::key_t): Rename "original_region"
to "parent".
(cast_region::cast_region): Likewise.  Update for removal of
cast_region::m_original_region.
(cast_region::accept): Delete.
(cast_region::add_dump_widget_children): Delete.
(cast_region::get_original_region): Delete.
(cast_region::m_original_region): Delete.
* sm-taint.cc (region_model::check_region_for_taint): Remove
special-casing for RK_CAST.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/taint-alloc-4.c: Update expected result to
reflect change in message due to
region_model::get_representative_path_var_1 now handling RK_CAST.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/call-summary.cc  | 11 +++---
 gcc/analyzer/region-model-manager.cc  |  2 +-
 gcc/analyzer/region-model.cc  |  2 +-
 gcc/analyzer/region.cc| 50 ---
 gcc/analyzer/region.h | 37 +++-
 gcc/analyzer/sm-taint.cc  |  8 -
 gcc/testsuite/gcc.dg/analyzer/taint-alloc-4.c |  4 +--
 7 files changed, 29 insertions(+), 85 deletions(-)

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index 60ca78a334d..46b4e2a3bbd 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -726,13 +726,12 @@ call_summary_replay::convert_region_from_summary_1 (const 
region *summary_reg)
   {
const cast_region *summary_cast_reg
  = as_a  (summary_reg);
-   const region *summary_original_reg
- = summary_cast_reg->get_original_region ();
-   const region *caller_original_reg
- = convert_region_from_summary (summary_original_reg);
-   if (!caller_original_reg)
+   const region *summary_parent_reg = summary_reg->get_parent_region ();
+   const region *caller_parent_reg
+ = convert_region_from_summary (summary_parent_reg);
+   if (!caller_parent_reg)
  return NULL;
-   return mgr->get_cast_region (caller_original_reg,
+   return mgr->get_cast_region (caller_parent_reg,
 summary_reg->get_type ());
   }
   break;
diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index b094b2f7e43..8154d914e81 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -327,7 +327,7 @@ region_model_manager::get_or_create_initial_value (const 
region *reg,
   /* The initial value of a cast is a cast of the initial value.  */
   if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
 {
-  const region *original_reg = cast_reg->get_original_region ();
+  const region *original_reg = cast_reg->get_parent_region ();
   return get_or_create_cast (cast_reg->get_type (),
 get_or_create_initial_value (original_reg));
 }
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index d6bcb8630cd..9f24011c17b 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2933,7 +2933,7 @@ region_model::get_store_value (const region *reg,
 

[gcc r15-1109] analyzer: add logging to get_representative_path_var

2024-06-07 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:d039eef925878e41e3df1448cac6add51dba6333

commit r15-1109-gd039eef925878e41e3df1448cac6add51dba6333
Author: David Malcolm 
Date:   Fri Jun 7 16:14:29 2024 -0400

analyzer: add logging to get_representative_path_var

This was very helpful when debugging the cast_region::m_original_region
removal, but is probably too verbose to enable except by hand on
specific calls to get_representative_tree.

gcc/analyzer/ChangeLog:
* engine.cc (impl_region_model_context::on_state_leak): Pass nullptr
to get_representative_path_var.
* region-model.cc (region_model::get_representative_path_var_1):
Add logger param and use it in both overloads.
(region_model::get_representative_path_var): Likewise.
(region_model::get_representative_tree): Likewise.
(selftest::test_get_representative_path_var): Pass nullptr to
get_representative_path_var.
* region-model.h (region_model::get_representative_tree): Add
optional logger param to both overloads.
(region_model::get_representative_path_var): Add logger param to
both overloads.
(region_model::get_representative_path_var_1): Likewise.
* store.cc (binding_cluster::get_representative_path_vars): Add
logger param and use it.
(store::get_representative_path_vars): Likewise.
* store.h (binding_cluster::get_representative_path_vars): Add
logger param.
(store::get_representative_path_vars): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/engine.cc   |   3 +-
 gcc/analyzer/region-model.cc | 109 +--
 gcc/analyzer/region-model.h  |  18 ---
 gcc/analyzer/store.cc|  12 +++--
 gcc/analyzer/store.h |   2 +
 5 files changed, 109 insertions(+), 35 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 8b3706cdfa8..30c0913c861 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -903,7 +903,8 @@ impl_region_model_context::on_state_leak (const 
state_machine &sm,
   svalue_set visited;
   path_var leaked_pv
 = m_old_state->m_region_model->get_representative_path_var (sval,
-   &visited);
+   &visited,
+   nullptr);
 
   /* Strip off top-level casts  */
   if (leaked_pv.m_tree && TREE_CODE (leaked_pv.m_tree) == NOP_EXPR)
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 9f24011c17b..a25181f2a3e 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -5343,7 +5343,8 @@ region_model::eval_condition (tree lhs,
 
 path_var
 region_model::get_representative_path_var_1 (const svalue *sval,
-svalue_set *visited) const
+svalue_set *visited,
+logger *logger) const
 {
   gcc_assert (sval);
 
@@ -5360,7 +5361,8 @@ region_model::get_representative_path_var_1 (const svalue 
*sval,
   /* Handle casts by recursion into get_representative_path_var.  */
   if (const svalue *cast_sval = sval->maybe_undo_cast ())
 {
-  path_var result = get_representative_path_var (cast_sval, visited);
+  path_var result = get_representative_path_var (cast_sval, visited,
+logger);
   tree orig_type = sval->get_type ();
   /* If necessary, wrap the result in a cast.  */
   if (result.m_tree && orig_type)
@@ -5369,7 +5371,7 @@ region_model::get_representative_path_var_1 (const svalue 
*sval,
 }
 
   auto_vec pvs;
-  m_store.get_representative_path_vars (this, visited, sval, &pvs);
+  m_store.get_representative_path_vars (this, visited, sval, logger, &pvs);
 
   if (tree cst = sval->maybe_get_constant ())
 pvs.safe_push (path_var (cst, 0));
@@ -5378,7 +5380,7 @@ region_model::get_representative_path_var_1 (const svalue 
*sval,
   if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
 {
   const region *reg = ptr_sval->get_pointee ();
-  if (path_var pv = get_representative_path_var (reg, visited))
+  if (path_var pv = get_representative_path_var (reg, visited, logger))
return path_var (build1 (ADDR_EXPR,
 sval->get_type (),
 pv.m_tree),
@@ -5391,7 +5393,7 @@ region_model::get_representative_path_var_1 (const svalue 
*sval,
   const svalue *parent_sval = sub_sval->get_parent ();
   const region *subreg = sub_sval->get_subregion ();
   if (path_var parent_pv
-   = get_representative_path_var (parent_sval, visited))
+   = get_representative_path_var (parent_sval, visited,

[gcc r15-1107] analyzer: new warning: -Wanalyzer-undefined-behavior-ptrdiff (PR analyzer/105892)

2024-06-07 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:13dcaf1bb6d4f15665a47b14ac0c12cf454e38a2

commit r15-1107-g13dcaf1bb6d4f15665a47b14ac0c12cf454e38a2
Author: David Malcolm 
Date:   Fri Jun 7 16:14:28 2024 -0400

analyzer: new warning: -Wanalyzer-undefined-behavior-ptrdiff (PR 
analyzer/105892)

Add a new warning to complain about pointer subtraction involving
different chunks of memory.

For example, given:

  #include 

  int arr[42];
  int sentinel;

  ptrdiff_t
  test_invalid_calc_of_array_size (void)
  {
return &sentinel - arr;
  }

this emits:

demo.c: In function ‘test_invalid_calc_of_array_size’:
demo.c:9:20: warning: undefined behavior when subtracting pointers 
[CWE-469] [-Wanalyzer-undefined-behavior-ptrdiff]
9 |   return &sentinel - arr;
  |^
  events 1-2
│
│3 | int arr[42];
│  | ~~~
│  | |
│  | (2) underlying object for right-hand side of subtraction 
created here
│4 | int sentinel;
│  | ^~~~
│  | |
│  | (1) underlying object for left-hand side of subtraction 
created here
│
└──> ‘test_invalid_calc_of_array_size’: event 3
   │
   │9 |   return &sentinel - arr;
   │  |^
   │  ||
   │  |(3) ⚠️  subtraction of pointers has 
undefined behavior if they do not point into the same array object
   │

gcc/analyzer/ChangeLog:
PR analyzer/105892
* analyzer.opt (Wanalyzer-undefined-behavior-ptrdiff): New option.
* analyzer.opt.urls: Regenerate.
* region-model.cc (class undefined_ptrdiff_diagnostic): New.
(check_for_invalid_ptrdiff): New.
(region_model::get_gassign_result): Call it for POINTER_DIFF_EXPR.

gcc/ChangeLog:
* doc/invoke.texi: Add -Wanalyzer-undefined-behavior-ptrdiff.

gcc/testsuite/ChangeLog:
PR analyzer/105892
* c-c++-common/analyzer/out-of-bounds-pr110387.c: Add
expected warnings about pointer subtraction.
* c-c++-common/analyzer/ptr-subtraction-1.c: New test.
* c-c++-common/analyzer/ptr-subtraction-CWE-469-example.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/analyzer.opt  |   4 +
 gcc/analyzer/analyzer.opt.urls |   3 +
 gcc/analyzer/region-model.cc   | 141 +
 gcc/doc/invoke.texi|  16 +++
 .../c-c++-common/analyzer/out-of-bounds-pr110387.c |   4 +-
 .../c-c++-common/analyzer/ptr-subtraction-1.c  |  46 +++
 .../analyzer/ptr-subtraction-CWE-469-example.c |  81 
 7 files changed, 293 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index bbf2ba670d8..5335f7e1999 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -222,6 +222,10 @@ Wanalyzer-tainted-size
 Common Var(warn_analyzer_tainted_size) Init(1) Warning
 Warn about code paths in which an unsanitized value is used as a size.
 
+Wanalyzer-undefined-behavior-ptrdiff
+Common Var(warn_analyzer_undefined_behavior_ptrdiff) Init(1) Warning
+Warn about code paths in which pointer subtraction involves undefined behavior.
+
 Wanalyzer-undefined-behavior-strtok
 Common Var(warn_analyzer_undefined_behavior_strtok) Init(1) Warning
 Warn about code paths in which a call is made to strtok with undefined 
behavior.
diff --git a/gcc/analyzer/analyzer.opt.urls b/gcc/analyzer/analyzer.opt.urls
index 5fcab720582..18a0d6926de 100644
--- a/gcc/analyzer/analyzer.opt.urls
+++ b/gcc/analyzer/analyzer.opt.urls
@@ -114,6 +114,9 @@ 
UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-offset)
 Wanalyzer-tainted-size
 UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-size)
 
+Wanalyzer-undefined-behavior-ptrdiff
+UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-undefined-behavior-ptrdiff)
+
 Wanalyzer-undefined-behavior-strtok
 
UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-undefined-behavior-strtok)
 
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index d142d851a26..d6bcb8630cd 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -841,6 +841,144 @@ private:
   tree m_count_cst;
 };
 
+/* A subclass of pending_diagnostic for complaining about pointer
+   subtractions involving unrelated buffers.  */
+
+class undefined_ptrdiff_diagnostic
+: public pending_diagnostic_subclass
+{
+public:
+  /* Region_creation_event subclass to give a custom wording when
+ talking about creation of buffers for LHS and RHS of the
+ subtraction.  */
+  class ptrdiff_region_creation_

[gcc r15-999] diagnostics: add SARIF property artifact.roles (3.24.6)

2024-06-03 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a67595d5c5d4bd4937de39158b268aed61f3d8d0

commit r15-999-ga67595d5c5d4bd4937de39158b268aed61f3d8d0
Author: David Malcolm 
Date:   Mon Jun 3 16:51:54 2024 -0400

diagnostics: add SARIF property artifact.roles (3.24.6)

Add the property "roles" (SARIF v2.1 3.24.6) to artifacts.

Populate it with:
* "analysisTarget" for the top-level input file
* "resultFile" for any other file a diagnostic is reported in
* "tracedFile" for any file a diagnostic event is reported in

gcc/ChangeLog:
* diagnostic-format-sarif.cc: Include "ordered-hash-map.h" and
"sbitmap.h".
(enum class diagnostic_artifact_role): New.
(class sarif_artifact): New.
(sarif_builder::maybe_make_artifact_content_object): Make public.
(sarif_builder::m_filenames): Replace with...
(sarif_builder::m_filename_to_artifact_map): ...this.
(sarif_artifact::add_role): New.
(sarif_artifact::populate_contents): New.
(get_artifact_role_string): New.
(sarif_artifact::populate_roles): New.
(sarif_result::on_nested_diagnostic): Pass role to
make_location_object.
(sarif_ice_notification::sarif_ice_notification): Likewise.
(sarif_builder::sarif_builder): Add "main_input_filename_" param.
Mark it as the artifact that the tool was instructed to scan.
(sarif_builder::make_result_object): Pass role to
make_locations_arr.
(sarif_builder::make_locations_arr): Add "role" param and pass it
to make_location_object.
(sarif_builder::make_location_object): Add "role" param and pass
it to maybe_make_physical_location_object.
(sarif_builder::maybe_make_physical_location_object): Add "role"
param and pass it to call to get_or_create_artifact, rather than
adding to now-removed "m_filenames".  Flag the artifact for its
contents to be embedded.
(sarif_builder::make_thread_flow_location_object): Pass role to
make_location_object.
(sarif_builder::make_run_object): Update for change from
m_filename to m_filename_to_artifact_map.  Call populate_contents
and populate_roles on each artifact_obj.
(sarif_builder::make_artifact_object): Convert to...
(sarif_builder::get_or_create_artifact): ...this, moving addition
of contents to make_run_object, and conditionalizing setting of
sourceLanguage on "role".
(sarif_output_format::sarif_output_format): Add
"main_input_filename_" param and pass to m_builder's ctor.
(sarif_stream_output_format::sarif_stream_output_format):
Likewise.
(sarif_file_output_format::sarif_file_output_format): Likewise.
(diagnostic_output_format_init_sarif_stderr): Add
"main_input_filename_" param and pass to ctor.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* diagnostic.cc (diagnostic_output_format_init): Add
"main_input_filename_" param and pass to the
diagnostic_output_format_init_sarif_* calls.
* diagnostic.h (diagnostic_output_format_init): Add
main_input_filename_" param to decl.
(diagnostic_output_format_init_sarif_stderr): Likewise.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* gcc.cc (driver_handle_option): Pass main input filename to
diagnostic_output_format_init.
* opts.cc (common_handle_option): Likewise.

gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/sarif-path-role.c: New test.
* c-c++-common/analyzer/sarif-path-role.h: New header for above
test.
* c-c++-common/diagnostic-format-sarif-file-1.c: Verify the
artifact's "role" property.
* c-c++-common/diagnostic-format-sarif-file-header-role.c: New
test.
* c-c++-common/diagnostic-format-sarif-file-header-role.h: New
header for above test.
* c-c++-common/diagnostic-format-sarif-file-no-results.c: New
test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 297 +
 gcc/diagnostic.cc  |   3 +
 gcc/diagnostic.h   |   4 +
 gcc/gcc.cc |   3 +-
 gcc/opts.cc|   3 +-
 .../c-c++-common/analyzer/sarif-path-role.c|  21 ++
 .../c-c++-common/analyzer/sarif-path-role.h|   2 +
 .../c-c++-common/diagnostic-format-sarif-file-1.c

[gcc r15-969] analyzer: detect -Wanalyzer-allocation-size at call stmts [PR106203]

2024-06-01 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:2b0a7fe3abfbd47081f714a0a1263afe00c5cfd9

commit r15-969-g2b0a7fe3abfbd47081f714a0a1263afe00c5cfd9
Author: David Malcolm 
Date:   Sat Jun 1 13:50:32 2024 -0400

analyzer: detect -Wanalyzer-allocation-size at call stmts [PR106203]

gcc/analyzer/ChangeLog:
PR analyzer/106203
* checker-event.h: Include "analyzer/event-loc-info.h".
(struct event_loc_info): Move to its own header file.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Move creation of
event_loc_info here from add_final_event, and if we have a
stmt_finder, call its update_event_loc_info method.
* engine.cc (leak_stmt_finder::update_event_loc_info): New.
(exploded_node::detect_leaks): Likewise.
(exploded_node::detect_leaks): Pass nullptr as call_stmt arg to
region_model::pop_frame.
* event-loc-info.h: New file, with content taken from
checker-event.h.
* exploded-graph.h (stmt_finder::update_event_loc_info): New pure
virtual function.
* infinite-loop.cc (infinite_loop_diagnostic::add_final_event):
Update for change to vfunc signature.
* infinite-recursion.cc
(infinite_recursion_diagnostic::add_final_event): Likewise.
* pending-diagnostic.cc (pending_diagnostic::add_final_event):
Pass in the event_loc_info from the caller, rather than generating
it from a gimple stmt and enode.
* pending-diagnostic.h (pending_diagnostic::add_final_event):
Likewise.
* region-model.cc (region_model::on_longjmp): Pass nullptr as
call_stmt arg to region_model::pop_frame.
(region_model::update_for_return_gcall): Likewise, but pass
call_stmt.
(class caller_context): New.
(region_model::pop_frame): Add "call_stmt" argument.  Use it
and the frame_region with a caller_context when setting
result_dst_reg's value so that any diagnostic is reported at the
call stmt in the caller.
(selftest::test_stack_frames): Pass nullptr as call_stmt arg to
region_model::pop_frame.
(selftest::test_alloca): Likewise.
* region-model.h (region_model::pop_frame): Add "call_stmt"
argument.

gcc/testsuite/ChangeLog:
PR analyzer/106203
* c-c++-common/analyzer/allocation-size-1.c (test_9): Remove
xfail.
* c-c++-common/analyzer/allocation-size-2.c (test_8): Likewise.
* gcc.dg/analyzer/allocation-size-multiline-4.c: New test.
* gcc.dg/plugin/analyzer_cpython_plugin.c
(refcnt_stmt_finder::update_event_loc_info): New.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/checker-event.h   | 14 +---
 gcc/analyzer/diagnostic-manager.cc | 13 +++-
 gcc/analyzer/engine.cc |  7 +-
 gcc/analyzer/event-loc-info.h  | 41 +++
 gcc/analyzer/exploded-graph.h  |  1 +
 gcc/analyzer/infinite-loop.cc  |  2 +-
 gcc/analyzer/infinite-recursion.cc |  2 +-
 gcc/analyzer/pending-diagnostic.cc |  6 +-
 gcc/analyzer/pending-diagnostic.h  |  2 +-
 gcc/analyzer/region-model.cc   | 84 --
 gcc/analyzer/region-model.h|  1 +
 .../c-c++-common/analyzer/allocation-size-1.c  |  8 +--
 .../c-c++-common/analyzer/allocation-size-2.c  |  8 +--
 .../gcc.dg/analyzer/allocation-size-multiline-4.c  | 64 +
 .../gcc.dg/plugin/analyzer_cpython_plugin.c|  5 ++
 15 files changed, 216 insertions(+), 42 deletions(-)

diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 7a4510ee81d..d0935aca985 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -23,22 +23,10 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "tree-logical-location.h"
 #include "analyzer/program-state.h"
+#include "analyzer/event-loc-info.h"
 
 namespace ana {
 
-/* A bundle of location information for a checker_event.  */
-
-struct event_loc_info
-{
-  event_loc_info (location_t loc, tree fndecl, int depth)
-  : m_loc (loc), m_fndecl (fndecl), m_depth (depth)
-  {}
-
-  location_t m_loc;
-  tree m_fndecl;
-  int m_depth;
-};
-
 /* An enum for discriminating between the concrete subclasses of
checker_event.  */
 
diff --git a/gcc/analyzer/diagnostic-manager.cc 
b/gcc/analyzer/diagnostic-manager.cc
index da98b9679cb..20e793d72c1 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -1588,8 +1588,17 @@ diagnostic_manager::emit_saved_diagnostic (const 
exploded_graph &eg,
  We use the final enode from the

[gcc r15-926] analyzer: fix a -Wunused-parameter

2024-05-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:0b3a3a66eb816b7c7e6bcb6f720813284e3eb0ef

commit r15-926-g0b3a3a66eb816b7c7e6bcb6f720813284e3eb0ef
Author: David Malcolm 
Date:   Thu May 30 08:42:01 2024 -0400

analyzer: fix a -Wunused-parameter

gcc/analyzer/ChangeLog:
* infinite-loop.cc (looping_back_event::get_desc): Fix unused
parameter warning introduced by me in r15-636-g770657d02c986c.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/infinite-loop.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc
index 04346cdfdc3..a83b8130e43 100644
--- a/gcc/analyzer/infinite-loop.cc
+++ b/gcc/analyzer/infinite-loop.cc
@@ -171,7 +171,7 @@ public:
   {
   }
 
-  label_text get_desc (bool can_colorize) const final override
+  label_text get_desc (bool) const final override
   {
 return label_text::borrow ("looping back...");
   }


[gcc r15-925] Add new text_art::tree_widget and use it in analyzer

2024-05-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:97238e4217d5cdc62686d86e784421bd0f76aa4a

commit r15-925-g97238e4217d5cdc62686d86e784421bd0f76aa4a
Author: David Malcolm 
Date:   Thu May 30 08:42:00 2024 -0400

Add new text_art::tree_widget and use it in analyzer

This patch adds a new text_art::tree_widget, which makes it easy
to generate hierarchical visualizations using either ASCII:

  +- Child 0
  |  +- Grandchild 0 0
  |  +- Grandchild 0 1
  |  `- Grandchild 0 2
  +- Child 1
  |  +- Grandchild 1 0
  |  +- Grandchild 1 1
  |  `- Grandchild 1 2
  `- Child 2
 +- Grandchild 2 0
 +- Grandchild 2 1
 `- Grandchild 2 2

or Unicode:

  Root
  ├─ Child 0
  │  ├─ Grandchild 0 0
  │  ├─ Grandchild 0 1
  │  ╰─ Grandchild 0 2
  ├─ Child 1
  │  ├─ Grandchild 1 0
  │  ├─ Grandchild 1 1
  │  ╰─ Grandchild 1 2
  ╰─ Child 2
 ├─ Grandchild 2 0
 ├─ Grandchild 2 1
 ╰─ Grandchild 2 2

potentially with colorization of the connecting lines.

It adds a new template for typename T:

  void text_art::dump (const T&);

for using this to dump any object to stderr that supports a
make_dump_widget method, with similar templates for dumping to
a pretty_printer * and a FILE *.

It uses this within the analyzer to add two new families of dumping
methods: one for program states, e.g.:

(gdb) call state->dump()
State
├─ Region Model
│  ├─ Current Frame: frame: ‘calls_malloc’@2
│  ├─ Store
│  │  ├─ m_called_unknown_fn: false
│  │  ├─ frame: ‘test’@1
│  │  │  ╰─ _1: (INIT_VAL(n_2(D))*(size_t)4)
│  │  ╰─ frame: ‘calls_malloc’@2
│  │ ├─ result_4: &HEAP_ALLOCATED_REGION(27)
│  │ ╰─ _5: &HEAP_ALLOCATED_REGION(27)
│  ╰─ Dynamic Extents
│ ╰─ HEAP_ALLOCATED_REGION(27): (INIT_VAL(n_2(D))*(size_t)4)
╰─ ‘malloc’ state machine
   ╰─ 0x468cb40: &HEAP_ALLOCATED_REGION(27): unchecked ({free}) (‘result_4’)

and the other for showing the detail of the recursive makeup of svalues
and regions, e.g. the (INIT_VAL(n_2(D))*(size_t)4) from above:

(gdb) call size_in_bytes->dump()
(17): ‘long unsigned int’: binop_svalue(mult_expr: ‘*’)
├─ (15): ‘size_t’: initial_svalue
│  ╰─ m_reg: (12): ‘size_t’: decl_region(‘n_2(D)’)
│ ╰─ parent: (9): frame_region(‘test’, index: 0, depth: 1)
│╰─ parent: (1): stack region
│   ╰─ parent: (0): root region
╰─ (16): ‘size_t’: constant_svalue (‘4’)

I've already found both of these useful when debugging analyzer issues.

The patch uses the former to update the output of
-fdump-analyzer-exploded-nodes-2 and
-fdump-analyzer-exploded-nodes-3.

The older dumping functions within the analyzer are retained in case
they turn out to still be useful for debugging.

gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add text-art/tree-widget.o.
* doc/analyzer.texi: Rewrite discussion of dumping state to
cover the text_art::tree_widget-based dumps, with a more
interesting example.
* text-art/dump-widget-info.h: New file.
* text-art/dump.h: New file.
* text-art/selftests.cc (selftest::text_art_tests): Call
text_art_tree_widget_cc_tests.
* text-art/selftests.h (selftest::text_art_tree_widget_cc_tests):
New decl.
* text-art/theme.cc (ascii_theme::get_cppchar): Handle the various
cell_kind::TREE_*.
(unicode_theme::get_cppchar): Likewise.
* text-art/theme.h (enum class theme::cell_kind): Add
TREE_CHILD_NON_FINAL, TREE_CHILD_FINAL, TREE_X_CONNECTOR, and
TREE_Y_CONNECTOR.
* text-art/tree-widget.cc: New file.

gcc/analyzer/ChangeLog:
* call-details.cc: Define INCLUDE_VECTOR.
* call-info.cc: Likewise.
* call-summary.cc: Likewise.
* checker-event.cc: Likewise.
* checker-path.cc: Likewise.
* complexity.cc: Likewise.
* constraint-manager.cc: Likewise.
(bounded_range::make_dump_widget): New.
(bounded_ranges::add_to_dump_widget): New.
(equiv_class::make_dump_widget): New.
(constraint::make_dump_widget): New.
(bounded_ranges_constraint::make_dump_widget): New.
(constraint_manager::make_dump_widget): New.
* constraint-manager.h (bounded_range::make_dump_widget): New
decl.
(bounded_ranges::add_to_dump_widget): New decl.
(equiv_class::make_dump_widget): New decl.
(constraint::make_dump_widget): New decl.
(bounded_ranges_constraint::make_dump_widget): New decl.
(constraint_manager::make_dump_widget): New decl.
* diagnostic-manager.cc: Define INCLUDE

[gcc r15-875] diagnostics: consolidate global state in diagnostic-color.cc

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:21fc89bac61983a869c066f7377f8280a6adca49

commit r15-875-g21fc89bac61983a869c066f7377f8280a6adca49
Author: David Malcolm 
Date:   Tue May 28 15:55:28 2024 -0400

diagnostics: consolidate global state in diagnostic-color.cc

Simplify the table of default colors, avoiding the need to manually
add the strlen of each entry.
Consolidate the global state in diagnostic-color.cc into a
g_color_dict, adding selftests for the new class diagnostic_color_dict.

No functional change intended.

gcc/ChangeLog:
* diagnostic-color.cc: Define INCLUDE_VECTOR.
Include "label-text.h" and "selftest.h".
(struct color_cap): Replace with...
(struct color_default): ...this, adding "m_" prefixes to fields
and dropping "name_len" and "free_val" field.
(color_dict): Convert to...
(gcc_color_defaults): ...this, making const, dropping the trailing
strlen and "false" from each entry.
(class diagnostic_color_dict): New.
(g_color_dict): New.
(colorize_start): Reimplement in terms of g_color_dict.
(diagnostic_color_dict::get_entry_by_name): New, based on
colorize_start.
(diagnostic_color_dict::get_start_by_name): Likewise.
(diagnostic_color_dict::diagnostic_color_dict): New.
(parse_gcc_colors): Reimplement, moving body...
(diagnostic_color_dict::parse_envvar_value): ...here.
(colorize_init): Lazily create g_color_dict.
(selftest::test_empty_color_dict): New.
(selftest::test_default_color_dict): New.
(selftest::test_color_dict_envvar_parsing): New.
(selftest::diagnostic_color_cc_tests): New.
* selftest-run-tests.cc (selftest::run_tests): Call
selftest::diagnostic_color_cc_tests.
* selftest.h (selftest::diagnostic_color_cc_tests): New decl.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-color.cc   | 277 +++---
 gcc/selftest-run-tests.cc |   1 +
 gcc/selftest.h|   1 +
 3 files changed, 216 insertions(+), 63 deletions(-)

diff --git a/gcc/diagnostic-color.cc b/gcc/diagnostic-color.cc
index f01a0fc2e37..cbe57ce763f 100644
--- a/gcc/diagnostic-color.cc
+++ b/gcc/diagnostic-color.cc
@@ -17,9 +17,11 @@
02110-1301, USA.  */
 
 #include "config.h"
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "diagnostic-color.h"
 #include "diagnostic-url.h"
+#include "label-text.h"
 
 #ifdef __MINGW32__
 #  define WIN32_LEAN_AND_MEAN
@@ -27,6 +29,7 @@
 #endif
 
 #include "color-macros.h"
+#include "selftest.h"
 
 /* The context and logic for choosing default --color screen attributes
(foreground and background colors, etc.) are the following.
@@ -72,56 +75,124 @@
 counterparts) and possibly bold blue.  */
 /* Default colors. The user can overwrite them using environment
variable GCC_COLORS.  */
-struct color_cap
+struct color_default
 {
-  const char *name;
-  const char *val;
-  unsigned char name_len;
-  bool free_val;
+  const char *m_name;
+  const char *m_val;
 };
 
 /* For GCC_COLORS.  */
-static struct color_cap color_dict[] =
+static const color_default gcc_color_defaults[] =
 {
-  { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED), 5, false },
-  { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA),
-  7, false },
-  { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
-  { "range1", SGR_SEQ (COLOR_FG_GREEN), 6, false },
-  { "range2", SGR_SEQ (COLOR_FG_BLUE), 6, false },
-  { "locus", SGR_SEQ (COLOR_BOLD), 5, false },
-  { "quote", SGR_SEQ (COLOR_BOLD), 5, false },
-  { "path", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
-  { "fnname", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 6, false },
-  { "targs", SGR_SEQ (COLOR_FG_MAGENTA), 5, false },
-  { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN), 12, false },
-  { "fixit-delete", SGR_SEQ (COLOR_FG_RED), 12, false },
-  { "diff-filename", SGR_SEQ (COLOR_BOLD), 13, false },
-  { "diff-hunk", SGR_SEQ (COLOR_FG_CYAN), 9, false },
-  { "diff-delete", SGR_SEQ (COLOR_FG_RED), 11, false },
-  { "diff-insert", SGR_SEQ (COLOR_FG_GREEN), 11, false },
-  { "type-diff", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 9, false 
},
-  { "valid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 5, false },
-  { "invalid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED), 7, false },
-  { NULL, NULL, 0, false }
+  { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED) },
+  { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA) },
+  { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN) },
+  { "range1", SGR_SEQ (COLOR_FG_GREEN) },
+  { "range2", SGR_SEQ (COLOR_FG_BLUE) },
+  { "locus", SGR_SEQ (COLOR_BOLD) },
+  { "quote", SGR_SEQ (COLOR_BOLD) },
+  { "path

[gcc r15-874] libcpp: move label_text to its own header

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:9bda2c4c81b668b1d9abbb58cc4e805ac955a639

commit r15-874-g9bda2c4c81b668b1d9abbb58cc4e805ac955a639
Author: David Malcolm 
Date:   Tue May 28 15:55:24 2024 -0400

libcpp: move label_text to its own header

No functional change intended.

libcpp/ChangeLog:
* Makefile.in (TAGS_SOURCES): Add include/label-text.h.
* include/label-text.h: New file.
* include/rich-location.h: Include "label-text.h".
(class label_text): Move to label-text.h.

Signed-off-by: David Malcolm 

Diff:
---
 libcpp/Makefile.in |   2 +-
 libcpp/include/label-text.h| 102 +
 libcpp/include/rich-location.h |  79 +--
 3 files changed, 105 insertions(+), 78 deletions(-)

diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in
index ebbca3f..7e47153264c 100644
--- a/libcpp/Makefile.in
+++ b/libcpp/Makefile.in
@@ -271,7 +271,7 @@ ETAGS = @ETAGS@
 
 TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h system.h ucnid.h \
 include/cpplib.h include/line-map.h include/mkdeps.h include/symtab.h \
-include/rich-location.h
+include/rich-location.h include/label-text.h
 
 
 TAGS: $(TAGS_SOURCES)
diff --git a/libcpp/include/label-text.h b/libcpp/include/label-text.h
new file mode 100644
index 000..13562cda41f
--- /dev/null
+++ b/libcpp/include/label-text.h
@@ -0,0 +1,102 @@
+/* A very simple string class.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING3.  If not see
+.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them.   Help stamp out software-hoarding!  */
+
+#ifndef LIBCPP_LABEL_TEXT_H
+#define LIBCPP_LABEL_TEXT_H
+
+/* A struct for the result of range_label::get_text: a NUL-terminated buffer
+   of localized text, and a flag to determine if the caller should "free" the
+   buffer.  */
+
+class label_text
+{
+public:
+  label_text ()
+  : m_buffer (NULL), m_owned (false)
+  {}
+
+  ~label_text ()
+  {
+if (m_owned)
+  free (m_buffer);
+  }
+
+  /* Move ctor.  */
+  label_text (label_text &&other)
+  : m_buffer (other.m_buffer), m_owned (other.m_owned)
+  {
+other.release ();
+  }
+
+  /* Move assignment.  */
+  label_text & operator= (label_text &&other)
+  {
+if (m_owned)
+  free (m_buffer);
+m_buffer = other.m_buffer;
+m_owned = other.m_owned;
+other.release ();
+return *this;
+  }
+
+  /* Delete the copy ctor and copy-assignment operator.  */
+  label_text (const label_text &) = delete;
+  label_text & operator= (const label_text &) = delete;
+
+  /* Create a label_text instance that borrows BUFFER from a
+ longer-lived owner.  */
+  static label_text borrow (const char *buffer)
+  {
+return label_text (const_cast  (buffer), false);
+  }
+
+  /* Create a label_text instance that takes ownership of BUFFER.  */
+  static label_text take (char *buffer)
+  {
+return label_text (buffer, true);
+  }
+
+  void release ()
+  {
+m_buffer = NULL;
+m_owned = false;
+  }
+
+  const char *get () const
+  {
+return m_buffer;
+  }
+
+  bool is_owner () const
+  {
+return m_owned;
+  }
+
+private:
+  char *m_buffer;
+  bool m_owned;
+
+  label_text (char *buffer, bool owned)
+  : m_buffer (buffer), m_owned (owned)
+  {}
+};
+
+#endif /* !LIBCPP_LABEL_TEXT_H  */
diff --git a/libcpp/include/rich-location.h b/libcpp/include/rich-location.h
index a2ece8b033c..be424cb4b65 100644
--- a/libcpp/include/rich-location.h
+++ b/libcpp/include/rich-location.h
@@ -22,6 +22,8 @@ along with this program; see the file COPYING3.  If not see
 #ifndef LIBCPP_RICH_LOCATION_H
 #define LIBCPP_RICH_LOCATION_H
 
+#include "label-text.h"
+
 class range_label;
 class label_effects;
 
@@ -541,83 +543,6 @@ protected:
   const diagnostic_path *m_path;
 };
 
-/* A struct for the result of range_label::get_text: a NUL-terminated buffer
-   of localized text, and a flag to determine if the caller should "free" the
-   buffer.  */
-
-class label_text
-{
-public:
-  label_text ()
-  : m_buffer (NULL), m_owned (false)
-  {}
-
-  ~label_text ()
-  {
-if (m_owned)
-  free (m_buffer);
-  }
-
-  /* Move ctor.  */
-  label_text (label_text &&other)
-  : m_buffer (other.m_buffer), m_owned (other.m_owned)
-  {
-o

[gcc r15-873] selftests: split out make_fndecl from selftest.h to its own header

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:fb7a943ead689e80e1ffdf6fa4e129dc155312d3

commit r15-873-gfb7a943ead689e80e1ffdf6fa4e129dc155312d3
Author: David Malcolm 
Date:   Tue May 28 15:55:17 2024 -0400

selftests: split out make_fndecl from selftest.h to its own header

Avoid selftest.h requiring the "tree" type.
No functional change intended.

gcc/analyzer/ChangeLog:
* region-model.cc: Include "selftest-tree.h".

gcc/ChangeLog:
* function-tests.cc: Include "selftest-tree.h".
* selftest-tree.h: New file.
* selftest.h (make_fndecl): Move to selftest-tree.h.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/region-model.cc |  1 +
 gcc/function-tests.cc|  1 +
 gcc/selftest-tree.h  | 41 +
 gcc/selftest.h   |  7 ---
 4 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index bebe2ed3cd6..0dd5671db1b 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-color.h"
 #include "bitmap.h"
 #include "selftest.h"
+#include "selftest-tree.h"
 #include "analyzer/analyzer.h"
 #include "analyzer/analyzer-logging.h"
 #include "ordered-hash-map.h"
diff --git a/gcc/function-tests.cc b/gcc/function-tests.cc
index 827734422d8..ea3d722d4b6 100644
--- a/gcc/function-tests.cc
+++ b/gcc/function-tests.cc
@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-ref.h"
 #include "cgraph.h"
 #include "selftest.h"
+#include "selftest-tree.h"
 #include "print-rtl.h"
 
 #if CHECKING_P
diff --git a/gcc/selftest-tree.h b/gcc/selftest-tree.h
new file mode 100644
index 000..9922af3340f
--- /dev/null
+++ b/gcc/selftest-tree.h
@@ -0,0 +1,41 @@
+/* A self-testing framework, for use by -fself-test.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_SELFTEST_TREE_H
+#define GCC_SELFTEST_TREE_H
+
+/* The selftest code should entirely disappear in a production
+   configuration, hence we guard all of it with #if CHECKING_P.  */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Helper function for selftests that need a function decl.  */
+
+extern tree make_fndecl (tree return_type,
+const char *name,
+vec  ¶m_types,
+bool is_variadic = false);
+
+} /* end of namespace selftest.  */
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_TREE_H */
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 3bddaf1c322..808d432ec48 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -178,13 +178,6 @@ class line_table_test
   ~line_table_test ();
 };
 
-/* Helper function for selftests that need a function decl.  */
-
-extern tree make_fndecl (tree return_type,
-const char *name,
-vec  ¶m_types,
-bool is_variadic = false);
-
 /* Run TESTCASE multiple times, once for each case in our test matrix.  */
 
 extern void


[gcc r15-872] regenerate-opt-urls.py: fix transposed values for "vax" and "v850"

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:7cc529fe514cc64e88208a6a7acfc6fe6419a453

commit r15-872-g7cc529fe514cc64e88208a6a7acfc6fe6419a453
Author: David Malcolm 
Date:   Tue May 28 15:47:38 2024 -0400

regenerate-opt-urls.py: fix transposed values for "vax" and "v850"

gcc/ChangeLog:
* config/v850/v850.opt.urls: Regenerate, with fix.
* config/vax/vax.opt.urls: Likewise.
* regenerate-opt-urls.py (TARGET_SPECIFIC_PAGES): Fix transposed
values for "vax" and "v850".

Signed-off-by: David Malcolm 

Diff:
---
 gcc/config/v850/v850.opt.urls | 81 ---
 gcc/config/vax/vax.opt.urls   | 21 ---
 gcc/regenerate-opt-urls.py|  4 +--
 3 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/gcc/config/v850/v850.opt.urls b/gcc/config/v850/v850.opt.urls
index dc5a83107b3..a06f4833f47 100644
--- a/gcc/config/v850/v850.opt.urls
+++ b/gcc/config/v850/v850.opt.urls
@@ -1,60 +1,87 @@
 ; Autogenerated by regenerate-opt-urls.py from gcc/config/v850/v850.opt and 
generated HTML
 
-; skipping UrlSuffix for 'mapp-regs' due to finding no URLs
+mapp-regs
+UrlSuffix(gcc/V850-Options.html#index-mapp-regs-1)
 
-; skipping UrlSuffix for 'mbig-switch' due to finding no URLs
+mbig-switch
+UrlSuffix(gcc/V850-Options.html#index-mbig-switch-1)
 
 ; skipping UrlSuffix for 'mdebug' due to finding no URLs
 
-; skipping UrlSuffix for 'mdisable-callt' due to finding no URLs
+mdisable-callt
+UrlSuffix(gcc/V850-Options.html#index-mdisable-callt)
 
-; skipping UrlSuffix for 'mep' due to finding no URLs
+mep
+UrlSuffix(gcc/V850-Options.html#index-mep)
 
-; skipping UrlSuffix for 'mghs' due to finding no URLs
+mghs
+UrlSuffix(gcc/V850-Options.html#index-mghs)
 
-; skipping UrlSuffix for 'mlong-calls' due to finding no URLs
+mlong-calls
+UrlSuffix(gcc/V850-Options.html#index-mlong-calls-7)
 
-; skipping UrlSuffix for 'mprolog-function' due to finding no URLs
+mprolog-function
+UrlSuffix(gcc/V850-Options.html#index-mprolog-function)
 
-; skipping UrlSuffix for 'msda=' due to finding no URLs
+msda=
+UrlSuffix(gcc/V850-Options.html#index-msda)
 
-; skipping UrlSuffix for 'mspace' due to finding no URLs
+mspace
+UrlSuffix(gcc/V850-Options.html#index-mspace)
 
-; skipping UrlSuffix for 'mtda=' due to finding no URLs
+mtda=
+UrlSuffix(gcc/V850-Options.html#index-mtda)
 
 ; skipping UrlSuffix for 'mno-strict-align' due to finding no URLs
 
-; skipping UrlSuffix for 'mv850' due to finding no URLs
+mv850
+UrlSuffix(gcc/V850-Options.html#index-mv850)
 
-; skipping UrlSuffix for 'mv850e' due to finding no URLs
+mv850e
+UrlSuffix(gcc/V850-Options.html#index-mv850e)
 
-; skipping UrlSuffix for 'mv850e1' due to finding no URLs
+mv850e1
+UrlSuffix(gcc/V850-Options.html#index-mv850e1)
 
-; skipping UrlSuffix for 'mv850es' due to finding no URLs
+mv850es
+UrlSuffix(gcc/V850-Options.html#index-mv850es)
 
-; skipping UrlSuffix for 'mv850e2' due to finding no URLs
+mv850e2
+UrlSuffix(gcc/V850-Options.html#index-mv850e2)
 
-; skipping UrlSuffix for 'mv850e2v3' due to finding no URLs
+mv850e2v3
+UrlSuffix(gcc/V850-Options.html#index-mv850e2v3)
 
-; skipping UrlSuffix for 'mv850e3v5' due to finding no URLs
+mv850e3v5
+UrlSuffix(gcc/V850-Options.html#index-mv850e3v5)
 
-; skipping UrlSuffix for 'mv850e2v4' due to finding no URLs
+mv850e2v4
+UrlSuffix(gcc/V850-Options.html#index-mv850e2v4)
 
-; skipping UrlSuffix for 'mloop' due to finding no URLs
+mloop
+UrlSuffix(gcc/V850-Options.html#index-mloop-1)
 
-; skipping UrlSuffix for 'mzda=' due to finding no URLs
+mzda=
+UrlSuffix(gcc/V850-Options.html#index-mzda)
 
-; skipping UrlSuffix for 'mrelax' due to finding no URLs
+mrelax
+UrlSuffix(gcc/V850-Options.html#index-mrelax-9)
 
-; skipping UrlSuffix for 'mlong-jumps' due to finding no URLs
+mlong-jumps
+UrlSuffix(gcc/V850-Options.html#index-mlong-jumps)
 
-; skipping UrlSuffix for 'msoft-float' due to finding no URLs
+msoft-float
+UrlSuffix(gcc/V850-Options.html#index-msoft-float-14)
 
-; skipping UrlSuffix for 'mhard-float' due to finding no URLs
+mhard-float
+UrlSuffix(gcc/V850-Options.html#index-mhard-float-9)
 
-; skipping UrlSuffix for 'mrh850-abi' due to finding no URLs
+mrh850-abi
+UrlSuffix(gcc/V850-Options.html#index-mrh850-abi)
 
-; skipping UrlSuffix for 'mgcc-abi' due to finding no URLs
+mgcc-abi
+UrlSuffix(gcc/V850-Options.html#index-mgcc-abi)
 
-; skipping UrlSuffix for 'm8byte-align' due to finding no URLs
+m8byte-align
+UrlSuffix(gcc/V850-Options.html#index-m8byte-align)
 
diff --git a/gcc/config/vax/vax.opt.urls b/gcc/config/vax/vax.opt.urls
index c6b1c418b61..10bee25d833 100644
--- a/gcc/config/vax/vax.opt.urls
+++ b/gcc/config/vax/vax.opt.urls
@@ -1,10 +1,23 @@
 ; Autogenerated by regenerate-opt-urls.py from gcc/config/vax/vax.opt and 
generated HTML
 
-; skipping UrlSuffix for 'mg' due to finding no URLs
+md
+UrlSuffix(gcc/VAX-Options.html#index-md)
 
-; skipping UrlSuffix for 'mgnu' due to finding no URLs
+md-float
+UrlSuffix(gcc/VAX-Options.html#index-

[gcc r15-866] diagnostics: disable localization of events in selftest paths [PR115203]

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:2dbb1c124c1e585dc413132d7a8d4be62c6b7baa

commit r15-866-g2dbb1c124c1e585dc413132d7a8d4be62c6b7baa
Author: David Malcolm 
Date:   Tue May 28 13:04:26 2024 -0400

diagnostics: disable localization of events in selftest paths [PR115203]

gcc/ChangeLog:
PR analyzer/115203
* diagnostic-path.h
(simple_diagnostic_path::disable_event_localization): New.
(simple_diagnostic_path::m_localize_events): New field.
* diagnostic.cc
(simple_diagnostic_path::simple_diagnostic_path): Initialize
m_localize_events.
(simple_diagnostic_path::add_event): Only localize fmt if
m_localize_events is true.
* tree-diagnostic-path.cc
(test_diagnostic_path::test_diagnostic_path): Call
disable_event_localization.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.h   | 3 +++
 gcc/diagnostic.cc   | 8 +---
 gcc/tree-diagnostic-path.cc | 3 ++-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index 982d68b872e..938bd583a3d 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -293,12 +293,15 @@ class simple_diagnostic_path : public diagnostic_path
 
   void connect_to_next_event ();
 
+  void disable_event_localization () { m_localize_events = false; }
+
  private:
   auto_delete_vec m_threads;
   auto_delete_vec m_events;
 
   /* (for use by add_event).  */
   pretty_printer *m_event_pp;
+  bool m_localize_events;
 };
 
 extern void debug (diagnostic_path *path);
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 1f30d1d7cda..f27b2f1a492 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -2517,7 +2517,8 @@ set_text_art_charset (enum diagnostic_text_art_charset 
charset)
 /* class simple_diagnostic_path : public diagnostic_path.  */
 
 simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
-  : m_event_pp (event_pp)
+: m_event_pp (event_pp),
+  m_localize_events (true)
 {
   add_thread ("main");
 }
@@ -2563,7 +2564,7 @@ simple_diagnostic_path::add_thread (const char *name)
stack depth DEPTH.
 
Use m_context's printer to format FMT, as the text of the new
-   event.
+   event.  Localize FMT iff m_localize_events is set.
 
Return the id of the new event.  */
 
@@ -2580,7 +2581,8 @@ simple_diagnostic_path::add_event (location_t loc, tree 
fndecl, int depth,
 
   va_start (ap, fmt);
 
-  text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
+  text_info ti (m_localize_events ? _(fmt) : fmt,
+   &ap, 0, nullptr, &rich_loc);
   pp_format (pp, &ti);
   pp_output_formatted_text (pp);
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 743a8c2a1d2..0ad6c5beb81 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -1016,7 +1016,7 @@ path_events_have_column_data_p (const diagnostic_path 
&path)
 }
 
 /* A subclass of simple_diagnostic_path that adds member functions
-   for adding test events.  */
+   for adding test events and suppresses translation of these events.  */
 
 class test_diagnostic_path : public simple_diagnostic_path
 {
@@ -1024,6 +1024,7 @@ class test_diagnostic_path : public simple_diagnostic_path
   test_diagnostic_path (pretty_printer *event_pp)
   : simple_diagnostic_path (event_pp)
   {
+disable_event_localization ();
   }
 
   void add_entry (tree fndecl, int stack_depth)


[gcc r15-865] Fix bootstrap on AIX by adding c-family/c-type-mismatch.cc [PR115167]

2024-05-28 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:b544ff88560e100e53ed8966d38f172c5bafce8d

commit r15-865-gb544ff88560e100e53ed8966d38f172c5bafce8d
Author: David Malcolm 
Date:   Tue May 28 13:04:25 2024 -0400

Fix bootstrap on AIX by adding c-family/c-type-mismatch.cc [PR115167]

PR bootstrap/115167 reports a bootstrap failure on AIX triggered by
r15-636-g770657d02c986c whilst building f951 in stage 2, due to
the linker not being able to find symbols for:

  vtable for range_label_for_type_mismatch
  range_label_for_type_mismatch::get_text(unsigned int) const

The only users of the class range_label_for_type_mismatch are in the
C/C++ frontends, each of which supply their own implementation of:

  range_label_for_type_mismatch::get_text(unsigned int) const

i.e. we had a cluster of symbols that was disconnnected from any
users on f951.

The above patch added a new range_label::get_effects vfunc to the
base class.  My hunch is that we were getting away with not defining
the symbol for Fortran with AIX's linker before (since none of the
users are used), but adding the get_effects vfunc has somehow broken
things (possibly because there's an empty implementation in the base
class in the *header*).

The following patch moves all of the code in
gcc/gcc-rich-location.[cc,h,o} defining and using
range_label_for_type_mismatch to a new
gcc/c-family/c-type-mismatch.{cc,h,o}, to help the linker ignore this
cluster of symbols when it's disconnected from users.

I was able to reproduce the failure without the patch, and then
successfully bootstrap with this patch on powerpc-ibm-aix7.3.1.0
(cfarm119).

gcc/ChangeLog:
PR bootstrap/115167
* Makefile.in (C_COMMON_OBJS): Add c-family/c-type-mismatch.o.
* gcc-rich-location.cc
(maybe_range_label_for_tree_type_mismatch::get_text): Move to
c-family/c-type-mismatch.cc.
(binary_op_rich_location::binary_op_rich_location): Likewise.
(binary_op_rich_location::use_operator_loc_p): Likewise.
* gcc-rich-location.h (class range_label_for_type_mismatch):
Likewise.
(class maybe_range_label_for_tree_type_mismatch): Likewise.
(class op_location_t): Likewise for forward decl.
(class binary_op_rich_location): Likewise.

gcc/c-family/ChangeLog:
PR bootstrap/115167
* c-format.cc: Replace include of "gcc-rich-location.h" with
"c-family/c-type-mismatch.h".
* c-type-mismatch.cc: New file, taking material from
gcc-rich-location.cc.
* c-type-mismatch.h: New file, taking material from
gcc-rich-location.h.
* c-warn.cc: Replace include of "gcc-rich-location.h" with
"c-family/c-type-mismatch.h".

gcc/c/ChangeLog:
PR bootstrap/115167
* c-objc-common.cc: Replace include of "gcc-rich-location.h" with
"c-family/c-type-mismatch.h".
* c-typeck.cc: Likewise.

gcc/cp/ChangeLog:
PR bootstrap/115167
PR bootstrap/115167
* call.cc: Replace include of "gcc-rich-location.h" with
"c-family/c-type-mismatch.h".
* error.cc: Likewise.
* typeck.cc: Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/Makefile.in |   3 +-
 gcc/c-family/c-format.cc|   2 +-
 gcc/c-family/c-type-mismatch.cc | 127 
 gcc/c-family/c-type-mismatch.h  | 126 +++
 gcc/c-family/c-warn.cc  |   2 +-
 gcc/c/c-objc-common.cc  |   2 +-
 gcc/c/c-typeck.cc   |   2 +-
 gcc/cp/call.cc  |   2 +-
 gcc/cp/error.cc |   2 +-
 gcc/cp/typeck.cc|   2 +-
 gcc/gcc-rich-location.cc|  89 
 gcc/gcc-rich-location.h | 101 
 12 files changed, 262 insertions(+), 198 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a7f15694c34..66d42cc41f8 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1301,7 +1301,8 @@ C_COMMON_OBJS = c-family/c-common.o 
c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
   c-family/c-semantics.o c-family/c-ada-spec.o \
   c-family/c-ubsan.o c-family/known-headers.o \
-  c-family/c-attribs.o c-family/c-warn.o c-family/c-spellcheck.o
+  c-family/c-attribs.o c-family/c-warn.o c-family/c-spellcheck.o \
+  c-family/c-type-mismatch.o
 
 # Analyzer object files
 ANALYZER_OBJS = \
diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index 9c4deabc109..7a5ffc25602 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #includ

[gcc r15-640] Regenerate common.opt.urls

2024-05-17 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:4e3bb431bbf2802bcf8e5d983dd1450f719d6ac7

commit r15-640-g4e3bb431bbf2802bcf8e5d983dd1450f719d6ac7
Author: David Malcolm 
Date:   Fri May 17 17:56:56 2024 -0400

Regenerate common.opt.urls

I forgot to do this for r15-636-g770657d02c986c.

gcc/ChangeLog:
* common.opt.urls: Regenerate to add
fdiagnostics-show-event-links.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/common.opt.urls | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/common.opt.urls b/gcc/common.opt.urls
index f71ed80a34b4..10462e408744 100644
--- a/gcc/common.opt.urls
+++ b/gcc/common.opt.urls
@@ -534,6 +534,9 @@ 
UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show
 fdiagnostics-show-caret
 
UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-caret)
 
+fdiagnostics-show-event-links
+UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-event-links)
+
 fdiagnostics-show-labels
 
UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-labels)


[gcc r15-636] diagnostics, analyzer: add CFG edge visualization to path-printing

2024-05-17 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:770657d02c986c8724214dba51f21bb3c299ebae

commit r15-636-g770657d02c986c8724214dba51f21bb3c299ebae
Author: David Malcolm 
Date:   Fri May 17 14:51:47 2024 -0400

diagnostics, analyzer: add CFG edge visualization to path-printing

This patch adds some ability for links between labelled ranges when
quoting the user's source code, and uses this to add links between
events when printing diagnostic_paths, chopping them up further into
event ranges that can be printed together.
It adds links to the various "from..." - "...to" events in the
analyzer.

For example, previously we emitted this for
c-c++-common/analyzer/infinite-loop-linked-list.c's
while_loop_missing_next':

infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] 
[-Wanalyzer-infinite-loop]
   30 |   while (n)
  |  ^
  'while_loop_missing_next': events 1-5
   30 |   while (n)
  |  ^
  |  |
  |  (1) infinite loop here
  |  (2) when 'n' is non-NULL: always following 'true' branch...
  |  (5) ...to here
   31 | {
   32 |   sum += n->val;
  |   ~
  |   |   |
  |   |   (3) ...to here
  |   (4) looping back...

whereas with the patch we now emit:

infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] 
[-Wanalyzer-infinite-loop]
   30 |   while (n)
  |  ^
  'while_loop_missing_next': events 1-3
   30 |   while (n)
  |  ^
  |  |
  |  (1) infinite loop here
  |  (2) when 'n' is non-NULL: always following 'true' 
branch... ->-+
  | 
|
  | 
|
  
|++
   31 ||{
   32 ||  sum += n->val;
  || ~~
  ||  |
  |+->(3) ...to here
  'while_loop_missing_next': event 4
   32 |   sum += n->val;
  |   ^
  |   |
  |   (4) looping back... ->-+
  |  |
  'while_loop_missing_next': event 5
  |  |
  |+-+
   30 ||  while (n)
  || ^
  || |
  |+>(5) ...to here

which I believe is easier to understand.

The patch also implements the use of unicode characters and colorization
for the lines (not shown in the above example).

There is a new option -fno-diagnostics-show-event-links for getting
back the old behavior (added to -fdiagnostics-plain-output).

gcc/analyzer/ChangeLog:
* checker-event.h (checker_event::connect_to_next_event_p):
Implement new diagnostic_event::connect_to_next_event_p vfunc.
(start_cfg_edge_event::connect_to_next_event_p): Likewise.
(start_consolidated_cfg_edges_event::connect_to_next_event_p):
Likewise.
* infinite-loop.cc (class looping_back_event): New subclass.
(infinite_loop_diagnostic::add_final_event): Use it.

gcc/ChangeLog:
* common.opt (fdiagnostics-show-event-links): New option.
* diagnostic-label-effects.h: New file.
* diagnostic-path.h (diagnostic_event::connect_to_next_event_p):
New pure virtual function.
(simple_diagnostic_event::connect_to_next_event_p): Implement it.
(simple_diagnostic_event::connect_to_next_event): New.
(simple_diagnostic_event::m_connected_to_next_event): New field.
(simple_diagnostic_path::connect_to_next_event): New decl.
* diagnostic-show-locus.cc: Include "text-art/theme.h" and
"diagnostic-label-effects.h".
(colorizer::set_cfg_edge): New.
(layout::m_fallback_theme): New field.
(layout::m_theme): New field.
(layout::m_effect_info): New field.
(layout::m_link_lhs_state): New enum and field.
(layout::m_link_rhs_column): New field.
(layout_range::has_in_edge): New.
(layout_range::has_out_edge): New.
(layout::layout): Add "effect_info" optional param.  Initialize
m_theme, m_link_lhs_state, and m_link_rhs_column.
(layout::maybe_add_location_range): Remove stray "FIXME" from
leading comment.
(layout::print_source_line): Replace space after margin with a
call to print_leftmost_column.
(layout::print_leftmost_column): New.
(layout::start_annotatio

[gcc r15-535] diagnostics: use unicode art for interprocedural depth

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:e656656e711949ef42a7e284f7cf81ca56f37374

commit r15-535-ge656656e711949ef42a7e284f7cf81ca56f37374
Author: David Malcolm 
Date:   Wed May 15 21:22:52 2024 -0400

diagnostics: use unicode art for interprocedural depth

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
output to use unicode for depth indication.
* gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c: Likewise.

gcc/ChangeLog:
* text-art/theme.cc (ascii_theme::get_cppchar): Add
cell_kind::INTERPROCEDURAL_*.
(unicode_theme::get_cppchar): Likewise.
* text-art/theme.h (theme::cell_kind): Likewise.
* tree-diagnostic-path.cc:
(thread_event_printer::print_swimlane_for_event_range): Use the
above to get characters for indicating interprocedural stack
depth activity, falling back to ascii.
(selftest::test_interprocedural_path_1): Test with both ascii
and unicode themes.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c   |  26 +-
 .../analyzer/out-of-bounds-diagram-1-unicode.c |  26 +-
 gcc/text-art/theme.cc  |  30 ++
 gcc/text-art/theme.h   |  10 +
 gcc/tree-diagnostic-path.cc| 381 ++---
 5 files changed, 331 insertions(+), 142 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
index 7b4ecf0d6b0c..8d22e4109628 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
arr[10] = x;
^~~
   event 1 (depth 0)
-|
-| int32_t arr[10];
-| ^~~
-| |
-| (1) capacity: 40 bytes
-|
-+--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-   |
-   |   arr[10] = x;
-   |   ^~~
-   |   |
-   |   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
-   |
+│
+│ int32_t arr[10];
+│ ^~~
+│ |
+│ (1) capacity: 40 bytes
+│
+└──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+   │
+   │   arr[10] = x;
+   │   ^~~
+   │   |
+   │   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
+   │
{ dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
index 71f66ff87c9e..58c4a7bedf34 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
arr[10] = x;
^~~
   event 1 (depth 0)
-|
-| int32_t arr[10];
-| ^~~
-| |
-| (1) capacity: 40 bytes
-|
-+--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-   |
-   |   arr[10] = x;
-   |   ^~~
-   |   |
-   |   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
-   |
+│
+│ int32_t arr[10];
+│ ^~~
+│ |
+│ (1) capacity: 40 bytes
+│
+└──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+   │
+   │   arr[10] = x;
+   │   ^~~
+   │   |
+   │   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
+   │
{ dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/text-art/theme.cc b/gcc/text-art/theme.cc
index 4ac0cae92e26..cba4c585c469 100644
--- a/gcc/text-art/theme.cc
+++ b/gcc/text-art/theme.cc
@@ -125,6 +125,21 @@ ascii_theme::get_cppchar (enum cell_kind kind) const
 case cell_kind::Y_ARROW_UP_TAIL:
 case cell_kind::Y_ARROW_DOWN_TAIL:
   return '|';
+
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT:
+  return '+';
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE:
+  return '-';
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT:
+  return '>';
+case cell_kind::INTERPROCEDURAL_DEPTH_MARKER:
+  return '|';
+case cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT:
+  return '<';
+case cell_kind::INTERPROC

[gcc r15-534] diagnostics: add warning emoji to events with VERB_danger

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:0b7ebe5427a4af0956e0aed5e7432b98559ca7b5

commit r15-534-g0b7ebe5427a4af0956e0aed5e7432b98559ca7b5
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: add warning emoji to events with VERB_danger

Tweak the printing of -fdiagnostics-path-format=inline-events so that
any event with diagnostic_event::VERB_danger gains a warning emoji,
provided that the text art theme enables emoji support.

VERB_danger is set by the analyzer on the last event in a path, and so
this emoji appears at the end of all analyzer execution paths
highlighting the location of the problem.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
output to include warning emoji.
* gcc.dg/analyzer/warning-emoji.c: New test.

gcc/ChangeLog:
* tree-diagnostic-path.cc: Include "text-art/theme.h".
(path_label::get_text): If the event has
diagnostic_event::VERB_danger, and the theme enables emojis, then
add a warning emoji between the event number and the event text.

Signed-off-by: David Malcolm 

Diff:
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c   |  2 +-
 gcc/testsuite/gcc.dg/analyzer/warning-emoji.c  | 29 +
 gcc/tree-diagnostic-path.cc| 30 +++---
 3 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
index 1c6125225ff2..7b4ecf0d6b0c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -29,7 +29,7 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
|   arr[10] = x;
|   ^~~
|   |
-   |   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
+   |   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
|
{ dg-end-multiline-output "" } */
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
new file mode 100644
index ..47e5fb0acf90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
@@ -0,0 +1,29 @@
+/* Verify that the final event in an analyzer path gets a "warning" emoji 
+   when -fdiagnostics-text-art-charset=emoji (and
+   -fdiagnostics-path-format=inline-events).  */
+
+/* { dg-additional-options "-fdiagnostics-show-line-numbers" } */
+/* { dg-additional-options "-fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=emoji" } */
+/* { dg-enable-nn-line-numbers "" } */
+
+void test (void *p)
+{
+  __builtin_free (p);
+  __builtin_free (p); /* { dg-warning "double-'free'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+   NN |   __builtin_free (p);
+  |   ^~
+  'test': events 1-2
+   NN |   __builtin_free (p);
+  |   ^~
+  |   |
+  |   (1) first 'free' here
+   NN |   __builtin_free (p);
+  |   ~~
+  |   |
+  |   (2) ⚠️  second 'free' here; first 'free' was at (1)
+   { dg-end-multiline-output "" } */
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 33389ef5d33e..bc90aaf321cc 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-event-id.h"
 #include "selftest.h"
 #include "selftest-diagnostic.h"
+#include "text-art/theme.h"
 
 /* Anonymous namespace for path-printing code.  */
 
@@ -60,13 +61,36 @@ class path_label : public range_label
 /* Get the description of the event, perhaps with colorization:
normally, we don't colorize within a range_label, but this
is special-cased for diagnostic paths.  */
-bool colorize = pp_show_color (global_dc->printer);
+const bool colorize = pp_show_color (global_dc->printer);
 label_text event_text (event.get_desc (colorize));
 gcc_assert (event_text.get ());
+
+const diagnostic_event::meaning meaning (event.get_meaning ());
+
 pretty_printer pp;
-pp_show_color (&pp) = pp_show_color (global_dc->printer);
+pp_show_color (&pp) = colorize;
 diagnostic_event_id_t event_id (event_idx);
-pp_printf (&pp, "%@ %s", &event_id, event_text.get ());
+
+pp_printf (&pp, "%@", &event_id);
+pp_space (&pp);
+
+if (meaning.m_verb == diagnostic_event::VERB_danger)
+  if (text_art::theme *theme = global_dc->get_diagram_theme ())
+   if (theme->emojis_p ())
+ {
+   pp_unicode_character (&pp, 0x26A0); /* U+26A0 WARNING SIGN.  */
+   /* Append U+F

[gcc r15-533] diagnostics: simplify output of purely intraprocedural execution paths

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3cd267446755ab6b2c59936a718d34c8bc474ca5

commit r15-533-g3cd267446755ab6b2c59936a718d34c8bc474ca5
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: simplify output of purely intraprocedural execution paths

Diagnostic path printing was added in r10-5901-g4bc1899b2e883f.  As of
that commit, with -fdiagnostics-path-format=inline-events (the default),
we print a vertical line to the left of the source line numbering,
visualizing the stack depth and interprocedural calls and returns as
indentation changes.

For cases where the events on a thread are purely interprocedural, this
line does nothing except take up space and complicate the output.

This patch adds logic to omit it for such cases, simpifying the output,
and, I believe, improving readability.

gcc/ChangeLog:
* diagnostic-path.h: Update leading comment to reflect
intraprocedural cases.  Fix typo in comment.
* doc/invoke.texi: Update intraprocedural example.

gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/allocation-size-multiline-1.c: Update
expected results for purely intraprocedural path.
* c-c++-common/analyzer/allocation-size-multiline-2.c: Likewise.
* c-c++-common/analyzer/allocation-size-multiline-3.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-0.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-1.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-2.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-3.c: Likewise.
* c-c++-common/analyzer/malloc-macro-inline-events.c: Likewise.
Doing so for this file requires a rewrite since the paths
prefixing the "in expansion of macro" lines become the only thing
on their line and so are no longer pruned by multiline.exp logic
for pruning extra content on non-blank lines.
* c-c++-common/analyzer/malloc-paths-9-noexcept.c: Likewise.
* c-c++-common/analyzer/setjmp-2.c: Likewise.
* gcc.dg/analyzer/malloc-paths-9.c: Likewise.
* gcc.dg/analyzer/out-of-bounds-multiline-2.c: Likewise.
* gcc.dg/plugin/diagnostic-test-paths-2.c: Likewise.

gcc/ChangeLog:
* tree-diagnostic-path.cc (per_thread_summary::interprocedural_p):
New.
(thread_event_printer::print_swimlane_for_event_range): Don't
indent and print the stack depth line if this thread's events are
purely intraprocedural.
(selftest::test_intraprocedural_path): Update expected output.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.h  |  32 +-
 gcc/doc/invoke.texi|  30 +-
 .../analyzer/allocation-size-multiline-1.c |  68 +--
 .../analyzer/allocation-size-multiline-2.c |  72 +--
 .../analyzer/allocation-size-multiline-3.c |  48 +-
 .../c-c++-common/analyzer/analyzer-verbosity-0.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-1.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-2.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-3.c   |  40 +-
 .../analyzer/malloc-macro-inline-events.c  |  83 +--
 .../analyzer/malloc-paths-9-noexcept.c | 604 ++---
 gcc/testsuite/c-c++-common/analyzer/setjmp-2.c | 140 +++--
 gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c | 302 +--
 .../gcc.dg/analyzer/out-of-bounds-multiline-2.c|  21 +-
 .../gcc.dg/plugin/diagnostic-test-paths-2.c|  30 +-
 gcc/tree-diagnostic-path.cc|  86 ++-
 16 files changed, 799 insertions(+), 877 deletions(-)

diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index fb7abe88ed32..696991c6d736 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -41,22 +41,20 @@ class sarif_object;
 29 | PyList_Append(list, item);
| ^
'demo': events 1-3
-  |
-  |   25 |   list = PyList_New(0);
-  |  |  ^
-  |  |  |
-  |  |  (1) when 'PyList_New' fails, returning NULL
-  |   26 |
-  |   27 |   for (i = 0; i < count; i++) {
-  |  |   ~~~
-  |  |   |
-  |  |   (2) when 'i < count'
-  |   28 | item = PyLong_FromLong(random());
-  |   29 | PyList_Append(list, item);
-  |  | ~
-  |  | |
-  |  | (3) when calling 'PyList_Append', passing NULL from (1) 
as argument 1
-  |
+25 |   list = PyList_New(0);
+   |  ^
+   |  |
+   |  (1) when 'PyList_New' fails, returning NULL
+ 

[gcc r15-532] diagnostics: handle SGR codes in line_label::m_display_width

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a7be993806a90a58397e9d5bc9b54160ac9f35db

commit r15-532-ga7be993806a90a58397e9d5bc9b54160ac9f35db
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: handle SGR codes in line_label::m_display_width

gcc/ChangeLog:
* diagnostic-show-locus.cc: Define INCLUDE_VECTOR and include
"text-art/types.h".
(line_label::line_label): Drop "policy" argument.  Use
styled_string::calc_canvas_width when computing m_display_width,
as this skips SGR codes.
(layout::print_any_labels): Update for line_label ctor change.
(selftest::test_one_liner_labels_utf8): Update expected text to
reflect that the labels can fit on one line if we don't get
confused by SGR colorization codes.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-show-locus.cc | 28 +---
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index ceccc0b793d1..f42006cfe2a1 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
 #include "version.h"
@@ -31,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest.h"
 #include "selftest-diagnostic.h"
 #include "cpplib.h"
+#include "text-art/types.h"
 
 #ifdef HAVE_TERMIOS_H
 # include 
@@ -1923,14 +1925,18 @@ struct pod_label_text
 class line_label
 {
 public:
-  line_label (const cpp_char_column_policy &policy,
- int state_idx, int column,
+  line_label (int state_idx, int column,
  label_text text)
   : m_state_idx (state_idx), m_column (column),
 m_text (std::move (text)), m_label_line (0), m_has_vbar (true)
   {
-const int bytes = strlen (m_text.m_buffer);
-m_display_width = cpp_display_width (m_text.m_buffer, bytes, policy);
+/* Using styled_string rather than cpp_display_width here
+   lets us skip SGR formatting characters for color and URLs.
+   It doesn't handle tabs and unicode escaping, but we don't
+   expect to see either of those in labels.  */
+text_art::style_manager sm;
+text_art::styled_string str (sm, m_text.m_buffer);
+m_display_width = str.calc_canvas_width ();
   }
 
   /* Sorting is primarily by column, then by state index.  */
@@ -1990,7 +1996,7 @@ layout::print_any_labels (linenum_type row)
if (text.get () == NULL)
  continue;
 
-   labels.safe_push (line_label (m_policy, i, disp_col, std::move (text)));
+   labels.safe_push (line_label (i, disp_col, std::move (text)));
   }
   }
 
@@ -4382,9 +4388,9 @@ test_one_liner_labels_utf8 ()
   ASSERT_STREQ (" _foo = _bar._field;\n"
" ^    ~~~\n"
" |   ||\n"
-   " |   |label 2\xcf\x80\n"
-   " |   label 1\xcf\x80\n"
-   " label 0\xf0\x9f\x98\x82\n",
+   " label 0\xf0\x9f\x98\x82"
+   /* ... */ "   label 1\xcf\x80"
+   /* ...*/ " label 2\xcf\x80\n",
pp_formatted_text (dc.printer));
 }
 {
@@ -4395,9 +4401,9 @@ test_one_liner_labels_utf8 ()
(" <9f><98><82>_foo = 
<80>_bar.<9f><98><82>_field<80>;\n"
 " ^~~~    ~~\n"
 " |  ||\n"
-" |  |label 2\xcf\x80\n"
-" |  label 1\xcf\x80\n"
-" label 0\xf0\x9f\x98\x82\n",
+" label 0\xf0\x9f\x98\x82"
+/* ... */ "  label 1\xcf\x80"
+/* ..*/ " label 2\xcf\x80\n",
 pp_formatted_text (dc.printer));
 }
   }


[gcc r15-526] analyzer: fix ICE seen with -fsanitize=undefined [PR114899]

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:1779e22150b917e28e959623c819ef943fab02df

commit r15-526-g1779e22150b917e28e959623c819ef943fab02df
Author: David Malcolm 
Date:   Wed May 15 18:40:56 2024 -0400

analyzer: fix ICE seen with -fsanitize=undefined [PR114899]

gcc/analyzer/ChangeLog:
PR analyzer/114899
* access-diagram.cc
(written_svalue_spatial_item::get_label_string): Bulletproof
against SSA_NAME_VAR being null.

gcc/testsuite/ChangeLog:
PR analyzer/114899
* c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/access-diagram.cc|  3 ++-
 .../analyzer/out-of-bounds-diagram-pr114899.c | 15 +++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 500480b68328..8d7461fe381d 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -1632,7 +1632,8 @@ protected:
 if (rep_tree)
   {
if (TREE_CODE (rep_tree) == SSA_NAME)
- rep_tree = SSA_NAME_VAR (rep_tree);
+ if (tree var = SSA_NAME_VAR (rep_tree))
+   rep_tree = var;
switch (TREE_CODE (rep_tree))
  {
  default:
diff --git 
a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c 
b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c
new file mode 100644
index ..14ba540d4ec2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c
@@ -0,0 +1,15 @@
+/* Verify we don't ICE generating out-of-bounds diagram.  */
+
+/* { dg-additional-options " -fsanitize=undefined 
-fdiagnostics-text-art-charset=unicode" } */
+
+int * a() {
+  int *b = (int *)__builtin_malloc(sizeof(int));
+  int *c = b - 1;
+  ++*c;
+  return b;
+}
+
+/* We don't care about the exact diagram, just that we don't ICE.  */
+
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */


[gcc r13-8761] diagnostics: fix corrupt json/SARIF on stderr [PR114348]

2024-05-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:b7a2697733d19a093cbdd0e200ffce069a4bc812

commit r13-8761-gb7a2697733d19a093cbdd0e200ffce069a4bc812
Author: David Malcolm 
Date:   Thu May 9 13:09:33 2024 -0400

diagnostics: fix corrupt json/SARIF on stderr [PR114348]

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 

Diff:
---
 gcc/diagnostic.cc | 24 
 1 file changed, 24 insertions(+)

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 0f093081161a..a3d84cf0bfae 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:


[gcc r13-8760] Fix ICE in -fdiagnostics-generate-patch [PR112684]

2024-05-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:2a6f99aef7c8522471967b171180d9ba4136da90

commit r13-8760-g2a6f99aef7c8522471967b171180d9ba4136da90
Author: David Malcolm 
Date:   Thu May 9 13:09:32 2024 -0400

Fix ICE in -fdiagnostics-generate-patch [PR112684]

Backported from r14-8255-ge254d1224df306.

gcc/ChangeLog:
PR middle-end/112684
* toplev.cc (toplev::main): Don't ICE in
-fdiagnostics-generate-patch when exiting after options,
since no edit context will have been created.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/toplev.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 109c9d58cbd1..19391208eac2 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2292,10 +2292,8 @@ toplev::main (int argc, char **argv)
  emit some diagnostics here.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
-  if (flag_diagnostics_generate_patch)
+  if (global_dc->edit_context_ptr)
 {
-  gcc_assert (global_dc->edit_context_ptr);
-
   pretty_printer pp;
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   global_dc->edit_context_ptr->print_diff (&pp, true);


  1   2   >