[pushed] pretty_printer: unbreak build on aarch64 [PR115465]

2024-06-12 Thread David Malcolm
I missed this target-specific usage of pretty_printer::buffer when
making the fields private in r15-1209-gc5e3be456888aa; sorry.

Verified that this fixes the build breakage with
--target=aarch64-unknown-linux-gnu.

Pushed as r15-1220-ge35f4eab68773b.

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 
---
 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 (_slim_pp, insn, 1);
  pp_flush (_slim_pp);
  fprintf (dump_file, "\n");
-- 
2.26.3



[pushed 2/3] pretty_printer: make all fields private

2024-06-12 Thread David Malcolm
vas_urls): Likewise.
* text-art/dump.h (dump_to_file): Likewise.
* text-art/selftests.cc (selftest::assert_canvas_streq): Likewise.
* text-art/style.cc (style::print_changes): Likewise.
* text-art/styled-string.cc (styled_string::from_fmt_va):
Likewise.
* tree-diagnostic-path.cc (control_flow_tests): Update for
pp_show_color becoming an inline function.
* tree-loop-distribution.cc (dot_rdg_1): Update for fields of
pretty_printer becoming private.
* tree-pretty-print.cc (maybe_init_pretty_print): Likewise.
* value-range.cc (vrange::dump): Likewise.
(irange_bitmask::dump): Likewise.

gcc/fortran/ChangeLog:
* error.cc (gfc_clear_pp_buffer): Likewise.
(gfc_warning): Likewise.
(gfc_warning_check): Likewise.
(gfc_error_opt): Likewise.
(gfc_error_check): Likewise.

gcc/jit/ChangeLog:
* jit-recording.cc (recording::function::dump_to_dot): Update for
fields of pretty_printer becoming private.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_cpython_plugin.c (dump_refcnt_info):
Update for fields of pretty_printer becoming private.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/access-diagram.cc|   2 +-
 gcc/analyzer/call-details.cc  |   2 +-
 gcc/analyzer/call-summary.cc  |   4 +-
 gcc/analyzer/checker-event.cc |   2 +-
 gcc/analyzer/constraint-manager.cc|   8 +-
 gcc/analyzer/engine.cc|   6 +-
 gcc/analyzer/feasible-graph.cc|   2 +-
 gcc/analyzer/program-point.cc |   2 +-
 gcc/analyzer/program-state.cc |   6 +-
 gcc/analyzer/ranges.cc|   4 +-
 gcc/analyzer/record-layout.cc |   2 +-
 gcc/analyzer/region-model-reachability.cc |   2 +-
 gcc/analyzer/region-model.cc  |   6 +-
 gcc/analyzer/region-model.h   |   2 +-
 gcc/analyzer/region.cc|   4 +-
 gcc/analyzer/sm-malloc.cc |   2 +-
 gcc/analyzer/store.cc |  14 +-
 gcc/analyzer/supergraph.cc|   4 +-
 gcc/analyzer/svalue.cc|   2 +-
 gcc/c-family/c-ada-spec.cc|   2 +-
 gcc/c-family/c-pretty-print.cc|  36 +-
 gcc/c/c-objc-common.cc|   4 +-
 gcc/cp/cxx-pretty-print.cc|  12 +-
 gcc/cp/error.cc   |  37 +-
 gcc/diagnostic.cc |  14 +-
 gcc/diagnostic.h  |   6 +-
 gcc/digraph.cc|   2 +-
 gcc/digraph.h |   2 +-
 gcc/dumpfile.cc   |   1 +
 gcc/fortran/error.cc  |  30 +-
 gcc/gimple-pretty-print.cc|  10 +-
 gcc/graph.cc  |   4 +-
 gcc/jit/jit-recording.cc  |   2 +-
 gcc/langhooks.cc  |   3 +-
 gcc/lto-wrapper.cc|   4 +-
 gcc/pretty-print.cc   | 339 +-
 gcc/pretty-print.h| 263 +++---
 gcc/print-rtl.cc  |   6 +-
 gcc/print-tree.cc |   2 +-
 gcc/sched-rgn.cc  |   2 +-
 .../gcc.dg/plugin/analyzer_cpython_plugin.c   |   2 +-
 gcc/text-art/canvas.cc|  10 +-
 gcc/text-art/dump.h   |   2 +-
 gcc/text-art/selftests.cc |   2 +-
 gcc/text-art/style.cc |   4 +-
 gcc/text-art/styled-string.cc |   2 +-
 gcc/tree-diagnostic-path.cc   |   2 +-
 gcc/tree-loop-distribution.cc |   2 +-
 gcc/tree-pretty-print.cc  |   2 +-
 gcc/value-range.cc|   4 +-
 50 files changed, 516 insertions(+), 373 deletions(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 8d7461fe381d..cb5b656c164a 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -547,7 +547,7 @@ access_range::dump (bool simple) const
   pretty_printer pp;
   pp_format_decoder () = default_tree_printer;
   pp_show_color () = pp_show_color (global_dc->printer);
-  pp.buffer->stream = stderr;
+  pp.set_output_stream (stderr);
   dump_to_pp (, simple);
   pp_newline ();
   pp_flush ();
diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc
index fda925edb968..116ab40afaf5 100644
--- a/gcc/analyzer/call-details.cc
+++ b/gcc/analyzer/call-details.cc
@@ -366,7 +366,7 @@ call_details::dump (bool simple) const
   pretty_printer pp;
   pp_format_decoder () = default_tree_printer;
   pp_show_color () = pp_show_color (global_dc->

[pushed 3/3] pretty_printer: convert chunk_info into a class

2024-06-12 Thread David Malcolm
No functional change intended.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-1210-g1cae1a5ce088c1.

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 
---
 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 == >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 (>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 ,
-   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_idx] = nullptr;
+}
+
+/* Deallocate the current chunk structure and everything after it (i.e. the
+   associated series of formatted strings).  */
+
+void
+chunk_info::pop_from_output_buffer (o

[pushed] analyzer: add logging to get_representative_path_var

2024-06-07 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-1109-gd039eef925878e.

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 
---
 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 8b3706cdfa87..30c0913c861d 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 ,
   svalue_set visited;
   path_var leaked_pv
 = m_old_state->m_region_model->get_representative_path_var (sval,
-   );
+   ,
+   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 9f24011c17bf..a25181f2a3ec 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, );
+  m_store.get_representative_path_vars (this, visited, sval, logger, );
 
   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, logger))
if (const field_region *field_reg = subreg->dyn_cast_field_region ())
  return path_var (build3 (COMPONENT_REF,

[pushed] analyzer: eliminate cast_region::m_original_region

2024-06-07 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-1108-g70f26314b62e2d.

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 
---
 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 60ca78a334da..46b4e2a3bbd7 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 b094b2f7e434..8154d914e81c 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 d6bcb8630cd6..9f24011c17bf 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,
   /* Special-case: read the initial char of a STRING_CST.  */
   if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
 if (const string_region *str_reg
-   = cast_reg->ge

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

2024-06-07 Thread David Malcolm
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  - 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  - 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  - arr;
   │  |^
   │  ||
   │  |(3) ⚠️  subtraction of pointers has 
undefined behavior if they do not point into the same array object
   │

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-1107-g13dcaf1bb6d4f1.

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 
---
 gcc/analyzer/analyzer.opt |   4 +
 gcc/analyzer/analyzer.opt.urls|   3 +
 gcc/analyzer/region-model.cc  | 141 ++
 gcc/doc/invoke.texi   |  16 ++
 .../analyzer/out-of-bounds-pr110387.c |   4 +-
 .../c-c++-common/analyzer/ptr-subtraction-1.c |  46 ++
 .../ptr-subtraction-CWE-469-example.c |  81 ++
 7 files changed, 293 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-1.c
 create mode 100644 
gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-CWE-469-example.c

diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index bbf2ba670d8a..5335f7e1999e 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 5fcab7205823..18a0d6926de7 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 d142d851a26f..d6bcb8630cd6 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_event : public region_creation_event
+  {
+  public:
+ptrdiff_region_creation_event (const event_loc_info _info,
+  bool is_lhs)
+: region_creation_event (loc_info),
+  m_is_lhs 

Re: [analyzer PATCH] Restore bootstrap with g++ 4.8.

2024-06-07 Thread David Malcolm
On Fri, 2024-06-07 at 19:40 +0100, Roger Sayle wrote:
> 
> This patch restores bootstrap when using g++ 4.8 as a host compiler.
> Returning a std::unique_ptr requires a std::move on C++ compilers
> (pre-C++17) that don't guarantee copy elision/return value
> optimization.
> 
> Bootstrapped on x86_64-pc-linux-gnu using both gcc 4.8.5 (system) and
> gcc 10.2.1 (using "scl enable devetoolset-10") as host compilers.
> Ok for mainline?

Yes, thanks.  Sorry for the breakage.

Dave

> 
> 
> 2024-06-07  Roger Sayle  
> 
> gcc/analyzer/ChangeLog
>     * constraint-manager.cc (equiv_class::make_dump_widget): Use
>     std::move to return a std::unique_ptr.
>     (bounded_ranges_constraint::make_dump_widget): Likewise.
>     (constraint_manager::make_dump_widget): Likewise.
>     * program_state.cc (sm_state_map::make_dump_widget):
> Likewise.
>     (program_state::make_dump_widget): Likewise.
>     * region-model.cc (region_to_value_map::make_dump_widget):
> Likewise.
>     (region_model::make_dump_widget): Likewise.
>     * region.cc (region::make_dump_widget): Likewise.
>     * store.cc (binding_cluster::make_dump_widget): Likewise.
>     (store::make_dump_widget): Likewise.
>     * svalue.cc (svalue::make_dump_widget): Likewise.
> 
> Thanks in advance,
> Roger
> --
> 



Re: [pushed 2/3] libcpp: move label_text to its own header

2024-06-06 Thread David Malcolm
On Thu, 2024-06-06 at 08:40 -0700, Andrew Pinski wrote:
> On Thu, Jun 6, 2024 at 6:02 AM Bert Wesarg
>  wrote:
> > 
> > Dear David,
> > 
> > On Tue, May 28, 2024 at 10:07 PM David Malcolm
> >  wrote:
> > > 
> > > No functional change intended.
> > > 
> > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> > > Pushed to trunk as r15-874-g9bda2c4c81b668.
> > > 
> > > 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 
> > > ---
> > >  libcpp/Makefile.in |   2 +-
> > >  libcpp/include/label-text.h    | 102
> > > +
> > >  libcpp/include/rich-location.h |  79 +
> > >  3 files changed, 105 insertions(+), 78 deletions(-)
> > >  create mode 100644 libcpp/include/label-text.h
> > > 
> > > diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in
> > > index ebbca3fb..7e47153264c0 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
> > 
> > this does not seem to be enough that the new header will be
> > installed.
> > I get compile errors when compiling an plug-in with this patch:
> > 
> > In file included from
> > /home/bitten/opt/gcc-15-20240602/lib/gcc/x86_64-pc-linux-
> > gnu/15.0.0/plugin/include/diagnostic.h:24,
> > from
> > /home/bitten/builds/oCyPvWN6/1/perftools/cicd/scorep/src/build-gcc-
> > plugin/../src/adapters/compiler/gcc-
> > plugin/scorep_plugin_inst_descriptor.cpp:43:
> > /home/bitten/opt/gcc-15-20240602/lib/gcc/x86_64-pc-linux-
> > gnu/15.0.0/plugin/include/rich-location.h:25:10:
> > fatal error: label-text.h: No such file or directory
> > 25 | #include "label-text.h"
> > > ^~
> > compilation terminated.
> 
> I have a fix which I am testing.

Likewise (and sorry about the breakage)

Dave



Re: "counted_by" and -fanalyzer

2024-06-05 Thread David Malcolm
On Tue, 2024-06-04 at 22:09 +, Qing Zhao wrote:
> 
> 
> > On Jun 4, 2024, at 17:55, David Malcolm 
> > wrote:
> > 
> > On Fri, 2024-05-31 at 13:11 +, Qing Zhao wrote:
> > > 
> > > 

[...]

> > > 
> > > 
> > > Thanks a lot for the review.
> > > Will commit the patch set soon.
> > 
> > [...snip...]
> > 
> > Congratulations on getting this merged.
> > 
> > FWIW I've started investigating adding support for the new
> > attribute to
> > -fanalyzer (and am tracked this as PR analyzer/111567
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111567 ).
> 
> Thank you for starting looking at this.
> > 
> > The docs for the attribute speak of the implied relationship
> > between
> > the count field and size of the flex array, and say that: "It's the
> > user's responsibility to make sure the above requirements to be
> > kept
> > all the time.  Otherwise the compiler *reports warnings*, at the
> > same
> > time, the results of the array bound sanitizer and the
> > '__builtin_dynamic_object_size' is undefined." (my emphasis).
> > 
> > What are these warnings that are reported?  I looked through 
> > r15-944-gf824acd0e80754 through r15-948-g4c5bea7def1361 and I
> > didn't
> > see any new warnings or test coverage for warnings (beyond misuing
> > the
> > attribute).  Sorry if I'm missing something obvious here.
> 
> These warnings will be in the remaining work (I listed the remaining
> work in all versions except the last one):
> 
> > > > > **Remaining works: 
> > > > > 
> > > > > 6  Improve __bdos to use the counted_by info in whole-object
> > > > > size for the structure with FAM.
> > > > > 7  Emit warnings when the user breaks the requirments for the
> > > > > new counted_by attribute
> > > > > compilation time: -Wcounted-by
> > > > > run time: -fsanitizer=counted-by
> > > > >    * The initialization to the size field should be done
> > > > > before the first reference to the FAM field.
> > > > >    * the array has at least # of elements specified by the
> > > > > size field all the time during the program.

Aha - thanks.  Sorry for missing this, I confess I haven't been paying
close attention to this thread.

> 
> With the current patches that have been committed, the warnings are
> not emitted. 
> I believe that more analysis and more information are needed for
> these warnings to be effective, it might not
> be a trivial patch.  More discussion is needed for emitting such
> warnings.
> 
> > 
> > Does anyone have examples of cases that -fanalyzer ought to warn
> > for?
> 
> At this moment, I don’t have concrete testing cases for this yet, but
> I can come up with several small examples and share with you in a
> later email.

FWIW I did some brainstorming and put together the following .c file,
am posting it inline here for the sake of discussion; does this look
like the kind of thing to test for (in terms of how users are expected
to use the attribute, and the kinds of mistake they'd want warnings
about) ?

/* TODO:
   Some ideas for dimensions of test matrix:
   (a) concrete value vs symbolic value for "count"
   (b) concrete value vs symbolic value for size of array
   (c) dynamic vs static allocation of buffer (and malloc vs alloca)
   (d) relative size of array and of count
   - same size (not an issue)
   - array is too small compared to "count"
 - off by one
 - off by more than one
 - size is zero (but not negative)
 - negative size (which the docs say is OK)
   - array is too large compared to "count" (not an issue)
   (e) type of flex array:
   - char
   - non-char
   - type requiring padding
   (f) type/size/signedness of count field; what about overflow
   in (count * sizeof (type of array element)) ?
   ... etc: ideas?

Other ideas for test coverage:
- realloc
  - growing object
  - shrinking object
  - symbolic sizes where could be growth or shrinkage
  - failing realloc
- ...etc: ideas?  */

#include 
#include 
#include 

/* Example from the docs.  */

struct P {
  size_t count;
  char other;
  char array[] __attribute__ ((counted_by (count)));
} *p;

struct P *
test_malloc_with_correct_symbolic (size_t n)
{
  struct P *p = malloc (sizeof (struct P) + n);
  if (!p)
return NULL;
  p->count = n; // don't warn here
  return p;  
}

struct P *
test_malloc_with_correct_count_concrete (void)
{
  struct P *p = malloc (sizeof (struct P) + 42);
  if (!p)
return NULL;
  p->

"counted_by" and -fanalyzer (was Re: [PATCH v10 2/5] Convert references with "counted_by" attributes to/from .ACCESS_WITH_SIZE.)

2024-06-04 Thread David Malcolm
On Fri, 2024-05-31 at 13:11 +, Qing Zhao wrote:
> 
> 
> > On May 31, 2024, at 08:58, Richard Biener 
> > wrote:
> > 
> > On Thu, 30 May 2024, Qing Zhao wrote:
> > 
> > > Including the following changes:
> > > * The definition of the new internal function .ACCESS_WITH_SIZE
> > >  in internal-fn.def.
> > > * C FE converts every reference to a FAM with a "counted_by"
> > > attribute
> > >  to a call to the internal function .ACCESS_WITH_SIZE.
> > >  (build_component_ref in c_typeck.cc)
> > > 
> > >  This includes the case when the object is statically allocated
> > > and
> > >  initialized.
> > >  In order to make this working, the routine digest_init in c-
> > > typeck.cc
> > >  is updated to fold calls to .ACCESS_WITH_SIZE to its first
> > > argument
> > >  when require_constant is TRUE.
> > > 
> > >  However, for the reference inside "offsetof", the "counted_by"
> > > attribute is
> > >  ignored since it's not useful at all.
> > >  (c_parser_postfix_expression in c/c-parser.cc)
> > > 
> > >  In addtion to "offsetof", for the reference inside operator
> > > "typeof" and
> > >  "alignof", we ignore counted_by attribute too.
> > > 
> > >  When building ADDR_EXPR for the .ACCESS_WITH_SIZE in C FE,
> > >  replace the call with its first argument.
> > > 
> > > * Convert every call to .ACCESS_WITH_SIZE to its first argument.
> > >  (expand_ACCESS_WITH_SIZE in internal-fn.cc)
> > > * Provide the utility routines to check the call is
> > > .ACCESS_WITH_SIZE and
> > >  get the reference from the call to .ACCESS_WITH_SIZE.
> > >  (is_access_with_size_p and get_ref_from_access_with_size in
> > > tree.cc)
> > 
> > The middle-end parts of this revised patch are OK.
> 
> Thanks a lot for the review.
> Will commit the patch set soon.

[...snip...]

Congratulations on getting this merged.

FWIW I've started investigating adding support for the new attribute to
-fanalyzer (and am tracked this as PR analyzer/111567
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111567 ).

The docs for the attribute speak of the implied relationship between
the count field and size of the flex array, and say that: "It's the
user's responsibility to make sure the above requirements to be kept
all the time.  Otherwise the compiler *reports warnings*, at the same
time, the results of the array bound sanitizer and the
'__builtin_dynamic_object_size' is undefined." (my emphasis).

What are these warnings that are reported?  I looked through 
r15-944-gf824acd0e80754 through r15-948-g4c5bea7def1361 and I didn't
see any new warnings or test coverage for warnings (beyond misuing the
attribute).  Sorry if I'm missing something obvious here.

Does anyone have examples of cases that -fanalyzer ought to warn for?
Presumably it would be helpful for the analyzer to report about code
paths in which the requirements are violated (but it may be that the
analyzer runs too late to do this...)

Thanks
Dave



Re: [PATCH] testsuite: analyzer: Skip tests with non-numeric macros on Solaris [PR107750]

2024-06-03 Thread David Malcolm
On Mon, 2024-06-03 at 22:57 +0200, Rainer Orth wrote:
> A couple of gcc.dg/analyzer/fd-*.c tests still FAIL on Solaris.  The
> reason is always the same: they use macros that don't expand to
> simple
> numbers, something which c/c-parser.cc
> (ana::c_translation_unit::consider_macro) cannot handle:
> 
> * :
> 
> #define SOCK_STREAM NC_TPI_COTS /* stream socket */
> #define SOCK_DGRAM  NC_TPI_CLTS /* datagram socket */
> 
> * :
> 
> #define O_ACCMODE   (O_SEARCH | O_EXEC | 0x3)
> 
> To avoid the resulting noise, this patch skips the affected tests.
> 
> Tested on i386-pc-solaris2.11, sparc-sun-solaris2.11, and
> x86_64-pc-linux-gnu.
> 
> Ok for trunk?

Thanks, LGTM.

Dave




[pushed] diagnostics: add SARIF property artifact.roles (3.24.6)

2024-06-03 Thread David Malcolm
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

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-999-ga67595d5c5d4bd.

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 
---
 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 +
 .../diagnostic-format-sarif-file-1.c  |   5 +
 ...diagnostic-format-sarif-file-header-role.c |  12 +
 ...diagnostic-format-sarif-file-header-role.h |   1 +
 .../diagnostic-format-sarif-file-no-results.c |  44 +++
 11 files changed, 344 insertions(+), 51 deletions(-)
 create mode 100644 gcc/te

Re: [PATCH] regenerate-opt-urls.py: fix transposed values for "vax" and "v850"

2024-06-03 Thread David Malcolm
On Mon, 2024-06-03 at 11:30 +0100, Maciej W. Rozycki wrote:
> On Tue, 28 May 2024, David Malcolm wrote:
> 
> > I've pushed this to gcc trunk as r15-872-g7cc529fe514cc6 (having
> > bootstrapped and lightly tested it on x86_64-pc-linux-gnu)
> 
>  Thank you for fixing this up.  Is this a new requirement now for
> .opt 
> file changes?  

Yes, as of GCC 14.

I posted the objectives here:
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636060.html

> Why does it have to be called by hand then rather than
> being a make dependency?

IIRC, the idea is:
(a) to avoid requiring Python 3 as a build dependency, and 
(b) to avoid requiring the HTML docs to be built before gcc's code can
be built

since missing a few URLs is a relatively minor issue that we don't want
to complicate the build for.

Hence we decided to check for it in CI instead.

Hope the trade-off sounds reasonable
Dave



Re: [RFC][PATCH] PR tree-optimization/109071 - -Warray-bounds false positive warnings due to code duplication from jump threading

2024-06-03 Thread David Malcolm
On Mon, 2024-06-03 at 08:29 +0200, Richard Biener wrote:
> On Fri, May 31, 2024 at 11:23 PM Qing Zhao 
> wrote:
> > 
> > 
> > 
> > > On May 23, 2024, at 07:46, Richard Biener
> > >  wrote:
> > > 
> > > On Wed, May 22, 2024 at 8:53 PM Qing Zhao 
> > > wrote:
> > > > 
> > > > 
> > > > 
> > > > > On May 22, 2024, at 03:38, Richard Biener
> > > > >  wrote:
> > > > > 
> > > > > On Tue, May 21, 2024 at 11:36 PM David Malcolm
> > > > >  wrote:
> > > > > > 
> > > > > > On Tue, 2024-05-21 at 15:13 +, Qing Zhao wrote:
> > > > > > > Thanks for the comments and suggestions.
> > > > > > > 
> > > > > > > > On May 15, 2024, at 10:00, David Malcolm
> > > > > > > > 
> > > > > > > > wrote:
> > > > > > > > 
> > > > > > > > On Tue, 2024-05-14 at 15:08 +0200, Richard Biener
> > > > > > > > wrote:
> > > > > > > > > On Mon, 13 May 2024, Qing Zhao wrote:
> > > > > > > > > 
> > > > > > > > > > -Warray-bounds is an important option to enable
> > > > > > > > > > linux kernal to
> > > > > > > > > > keep
> > > > > > > > > > the array out-of-bound errors out of the source
> > > > > > > > > > tree.
> > > > > > > > > > 
> > > > > > > > > > However, due to the false positive warnings
> > > > > > > > > > reported in
> > > > > > > > > > PR109071
> > > > > > > > > > (-Warray-bounds false positive warnings due to code
> > > > > > > > > > duplication
> > > > > > > > > > from
> > > > > > > > > > jump threading), -Warray-bounds=1 cannot be added
> > > > > > > > > > on by
> > > > > > > > > > default.
> > > > > > > > > > 
> > > > > > > > > > Although it's impossible to elinimate all the false
> > > > > > > > > > positive
> > > > > > > > > > warnings
> > > > > > > > > > from -Warray-bounds=1 (See PR104355 Misleading -
> > > > > > > > > > Warray-bounds
> > > > > > > > > > documentation says "always out of bounds"), we
> > > > > > > > > > should minimize
> > > > > > > > > > the
> > > > > > > > > > false positive warnings in -Warray-bounds=1.
> > > > > > > > > > 
> > > > > > > > > > The root reason for the false positive warnings
> > > > > > > > > > reported in
> > > > > > > > > > PR109071 is:
> > > > > > > > > > 
> > > > > > > > > > When the thread jump optimization tries to reduce
> > > > > > > > > > the # of
> > > > > > > > > > branches
> > > > > > > > > > inside the routine, sometimes it needs to duplicate
> > > > > > > > > > the code
> > > > > > > > > > and
> > > > > > > > > > split into two conditional pathes. for example:
> > > > > > > > > > 
> > > > > > > > > > The original code:
> > > > > > > > > > 
> > > > > > > > > > void sparx5_set (int * ptr, struct nums * sg, int
> > > > > > > > > > index)
> > > > > > > > > > {
> > > > > > > > > > if (index >= 4)
> > > > > > > > > >   warn ();
> > > > > > > > > > *ptr = 0;
> > > > > > > > > > *val = sg->vals[index];
> > > > > > > > > > if (index >= 4)
> > > > > > > > > >   warn ();
> > > > > > > > > > *ptr = *val;
> > > > > > > > > > 
> > > > > > > > > > return;
&g

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

2024-06-01 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-969-g2b0a7fe3abfbd4.

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 
---
 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 +-
 .../analyzer/allocation-size-multiline-4.c| 64 ++
 .../gcc.dg/plugin/analyzer_cpython_plugin.c   |  5 ++
 15 files changed, 216 insertions(+), 42 deletions(-)
 create mode 100644 gcc/analyzer/event-loc-info.h
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/allocation-size-multiline-4.c

diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 7a4510ee81d0..d0935aca9853 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 da98b9679cbb..20e793d72c19 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 ,
  We use the final enode from the epath, which might be different from
  the sd.m_enode, as the dedupe code doesn't care about enodes, just
  snodes.  */
-  sd.m_d->add_final_event (sd.m_sm, epath-

[pushed] Add new text_art::tree_widget and use it in analyzer

2024-05-30 Thread David Malcolm
_svalue::add_dump_widget_children): New decl.
(conjured_svalue::print_dump_widget_label): New decl.
(conjured_svalue::add_dump_widget_children): New decl.
(asm_output_svalue::print_dump_widget_label): New decl.
(asm_output_svalue::add_dump_widget_children): New decl.
(const_fn_result_svalue::print_dump_widget_label): New decl.
(const_fn_result_svalue::add_dump_widget_children): New decl.
* trimmed-graph.cc: Define INCLUDE_VECTOR.
* varargs.cc: Likewise.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_cpython_plugin.c: Define INCLUDE_VECTOR.
* gcc.dg/plugin/analyzer_gil_plugin.c: Likewise.
* gcc.dg/plugin/analyzer_kernel_plugin.c: Likewise.
* gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise.

Signed-off-by: David Malcolm 
---
 gcc/Makefile.in   |   1 +
 gcc/analyzer/call-details.cc  |   1 +
 gcc/analyzer/call-info.cc |   1 +
 gcc/analyzer/call-summary.cc  |   1 +
 gcc/analyzer/checker-event.cc |   1 +
 gcc/analyzer/checker-path.cc  |   1 +
 gcc/analyzer/complexity.cc|   1 +
 gcc/analyzer/constraint-manager.cc| 100 +
 gcc/analyzer/constraint-manager.h |  20 +
 gcc/analyzer/diagnostic-manager.cc|   1 +
 gcc/analyzer/engine.cc|  29 +-
 gcc/analyzer/feasible-graph.cc|   1 +
 gcc/analyzer/infinite-recursion.cc|   1 +
 gcc/analyzer/kf-analyzer.cc   |   1 +
 gcc/analyzer/kf-lang-cp.cc|   1 +
 gcc/analyzer/kf.cc|   1 +
 gcc/analyzer/known-function-manager.cc|   1 +
 gcc/analyzer/pending-diagnostic.cc|   1 +
 gcc/analyzer/program-point.cc |   1 +
 gcc/analyzer/program-state.cc | 112 +
 gcc/analyzer/program-state.h  |  10 +
 gcc/analyzer/ranges.cc|   1 +
 gcc/analyzer/record-layout.cc |   1 +
 gcc/analyzer/region-model-asm.cc  |   1 +
 gcc/analyzer/region-model-manager.cc  |   1 +
 gcc/analyzer/region-model-reachability.cc |   1 +
 gcc/analyzer/region-model.cc  |  78 
 gcc/analyzer/region-model.h   |   9 +
 gcc/analyzer/region.cc| 251 +++
 gcc/analyzer/region.h |  68 +++
 gcc/analyzer/sm-fd.cc |   1 +
 gcc/analyzer/sm-file.cc   |   1 +
 gcc/analyzer/sm-malloc.cc |   1 +
 gcc/analyzer/sm-pattern-test.cc   |   1 +
 gcc/analyzer/sm-signal.cc |   1 +
 gcc/analyzer/sm-taint.cc  |   1 +
 gcc/analyzer/sm.cc|   1 +
 gcc/analyzer/state-purge.cc   |   1 +
 gcc/analyzer/store.cc | 156 +++
 gcc/analyzer/store.h  |  13 +
 gcc/analyzer/svalue.cc| 421 ++
 gcc/analyzer/svalue.h | 143 +-
 gcc/analyzer/trimmed-graph.cc |   1 +
 gcc/analyzer/varargs.cc   |   1 +
 gcc/doc/analyzer.texi | 175 ++--
 .../gcc.dg/plugin/analyzer_cpython_plugin.c   |   1 +
 .../gcc.dg/plugin/analyzer_gil_plugin.c   |   1 +
 .../gcc.dg/plugin/analyzer_kernel_plugin.c|   1 +
 .../gcc.dg/plugin/analyzer_known_fns_plugin.c |   1 +
 gcc/text-art/dump-widget-info.h   |  53 +++
 gcc/text-art/dump.h   |  83 
 gcc/text-art/selftests.cc |   1 +
 gcc/text-art/selftests.h  |   1 +
 gcc/text-art/theme.cc |  18 +
 gcc/text-art/theme.h  |   8 +-
 gcc/text-art/tree-widget.cc   | 237 ++
 gcc/text-art/tree-widget.h|  83 
 57 files changed, 2071 insertions(+), 33 deletions(-)
 create mode 100644 gcc/text-art/dump-widget-info.h
 create mode 100644 gcc/text-art/dump.h
 create mode 100644 gcc/text-art/tree-widget.cc
 create mode 100644 gcc/text-art/tree-widget.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 66d42cc41f84..e200c1310647 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1836,6 +1836,7 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o 
diagnostic-color.o \
text-art/styled-string.o \
text-art/table.o \
text-art/theme.o \
+   text-art/tree-widget.o \
text-art/widget.o
 
 # Objects in libcommon-target.a, used by drivers and by the core
diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc
index ca47953f1461..fda925edb968 100644
--- a/gcc/analyzer/call-details.cc
+++ b/gcc/analyzer/call-details.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include &qu

[pushed] analyzer: fix a -Wunused-parameter

2024-05-30 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-926-g0b3a3a66eb816b.

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 
---
 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 04346cdfdc3c..a83b8130e43c 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...");
   }
-- 
2.26.3



Re: CFG edge visualization to path-printing bootstrap failure

2024-05-29 Thread David Malcolm
On Wed, 2024-05-29 at 15:26 -0400, David Edelsohn wrote:
> On Mon, May 20, 2024 at 1:56 PM David Edelsohn 
> wrote:
> 
> > Hi, David
> > 
> > Unfortunately r15-636-g770657d02c986c causes a bootstrap failure on
> > AIX
> > when building f951 in stage2.  cc1 and cc1plus link successfully.
> > There
> > doesn't seem to be a similar failure for powerpc64-linux BE or LE.
> > 
> > The failure is
> > 
> > ld: 0711-317 ERROR: Undefined symbol:
> > _ZTV29range_label_for_type_mismatch
> > ld: 0711-317 ERROR: Undefined symbol:
> > ._ZNK29range_label_for_type_mismatch8get_textEj
> > 
> > which corresponds to
> > 
> > vtable for range_label_for_type_mismatch
> > range_label_for_type_mismatch::get_text(unsigned int) const
> > 
> > I suspect that something is not being explicitly instantiated,
> > which is
> > running afoul of the AIX linker.
> > 
> > Somehow your patch is causing the f951 compiler to reference these
> > additional, undefined symbols.  I suspect that they also are
> > undefined for
> > Linux targets, but the linker ignores the error and nothing is
> > amiss if the
> > symbols never are called.
> > 
> > Thanks, David
> > 
> 
> Thanks for diagnosing and fixing the problem.

Thanks for your help!

For reference, this was PR bootstrap/115167, fixed by
r15-865-gb544ff88560e10:
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/652918.html

Sorry for messing up the mailing list threading.

Dave



Re: PING: Re: [PATCH] selftest: invoke "diff" when ASSERT_STREQ fails

2024-05-29 Thread David Malcolm
On Wed, 2024-05-29 at 16:35 -0400, Eric Gallager wrote:
> On Tue, May 28, 2024 at 1:21 PM David Malcolm 
> wrote:
> > 
> > Ping.
> > 
> > This patch has actually been *very* helpful to me when debugging
> > selftest failures involving ASSERT_STREQ.
> > 
> > Thanks
> > Dave
> > 
> 
> Currently `diff` is only listed under the "Tools/packages necessary
> for modifying GCC" section of install/prerequisites.html:
> https://gcc.gnu.org/install/prerequisites.html
> If it's going to become a dependency for actually running GCC, too,
> it
> should get moved to be documented elsewhere, IMO.

All this is selftest code, and is turned off in a release configuration
of GCC.  The code path that invokes "diff" is when a selftest is
failing, which is immediately before a hard failure of the *build* of
GCC.  So arguably this is just a build-time thing for people
packaging/hacking on GCC, and thus not a new dependency for end-usage.

BTW I'm a bit hazy on the details of how "pex" is meant to work, so
hopefully someone more knowledgable than me can comment on that aspect
of the patch.  It seems to work though.

Dave

> 
> > On Fri, 2024-05-17 at 15:51 -0400, David Malcolm wrote:
> > > Currently when ASSERT_STREQ or ASSERT_STREQ_AT fail we print
> > > both strings to stderr.  However it can be hard to figure out
> > > the problem (e.g. for 1-character differences in long strings).
> > > 
> > > Extend the output by writing out the strings to tempfiles and
> > > invoking "diff -up" on them when we have such a selftest failure,
> > > to (I hope) simplify debugging.
> > > 
> > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> > > 
> > > OK for trunk?
> > > 
> > > gcc/ChangeLog:
> > >     * selftest.cc (selftest::print_diff): New function.
> > >     (selftest::assert_streq): Call it when we have non-equal
> > >     non-null strings.
> > > 
> > > Signed-off-by: David Malcolm 
> > > ---
> > >  gcc/selftest.cc | 28 ++--
> > >  1 file changed, 26 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/gcc/selftest.cc b/gcc/selftest.cc
> > > index 6438d86a6aa0..f58c0631908e 100644
> > > --- a/gcc/selftest.cc
> > > +++ b/gcc/selftest.cc
> > > @@ -63,6 +63,26 @@ fail_formatted (const location , const
> > > char
> > > *fmt, ...)
> > >    abort ();
> > >  }
> > > 
> > > +/* Invoke "diff" to print the difference between VAL1 and VAL2
> > > +   on stdout.  */
> > > +
> > > +static void
> > > +print_diff (const location , const char *val1, const char
> > > *val2)
> > > +{
> > > +  temp_source_file tmpfile1 (loc, ".txt", val1);
> > > +  temp_source_file tmpfile2 (loc, ".txt", val2);
> > > +  const char *args[] = {"diff",
> > > +   "-up",
> > > +   tmpfile1.get_filename (),
> > > +   tmpfile2.get_filename (),
> > > +   NULL};
> > > +  int exit_status = 0;
> > > +  int err = 0;
> > > +  pex_one (PEX_SEARCH | PEX_LAST,
> > > +  args[0], CONST_CAST (char **, args),
> > > +  NULL, NULL, NULL, _status, );
> > > +}
> > > +
> > >  /* Implementation detail of ASSERT_STREQ.
> > >     Compare val1 and val2 with strcmp.  They ought
> > >     to be non-NULL; fail gracefully if either or both are NULL. 
> > > */
> > > @@ -89,8 +109,12 @@ assert_streq (const location ,
> > >     if (strcmp (val1, val2) == 0)
> > >   pass (loc, "ASSERT_STREQ");
> > >     else
> > > - fail_formatted (loc, "ASSERT_STREQ (%s, %s)\n
> > > val1=\"%s\"\n
> > > val2=\"%s\"\n",
> > > - desc_val1, desc_val2, val1, val2);
> > > + {
> > > +   print_diff (loc, val1, val2);
> > > +   fail_formatted
> > > + (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n
> > > val2=\"%s\"\n",
> > > +  desc_val1, desc_val2, val1, val2);
> > > + }
> > >    }
> > >  }
> > > 
> > 
> 



Re: [RFC/RFA] [PATCH 08/12] Add a new pass for naive CRC loops detection

2024-05-29 Thread David Malcolm
On Fri, 2024-05-24 at 12:42 +0400, Mariam Arutunian wrote:
> This patch adds a new compiler pass aimed at identifying naive CRC
> implementations,
> characterized by the presence of a loop calculating a CRC (polynomial
> long
> division).
> Upon detection of a potential CRC, the pass prints an informational
> message.
> 
> Performs CRC optimization if optimization level is >= 2,
> besides optimizations for size and if fno_gimple_crc_optimization
> given.
> 
> This pass is added for the detection and optimization of naive CRC
> implementations,
> improving the efficiency of CRC-related computations.
> 
> This patch includes only initial fast checks for filtering out non-
> CRCs,
> detected possible CRCs verification and optimization parts will be
> provided
> in subsequent patches.
> 
>   gcc/
> 
>     * Makefile.in (OBJS): Add gimple-crc-optimization.o.
>     * common.opt (fgimple-crc-optimization): New option.
>     * doc/invoke.texi (-fgimple-crc-optimization): Add documentation.

A minor nitpick: patches that add new options (and their documentation)
ought to affect the corresponding .opt.urls, so that we can map from
the new option to the URL of its documentation.

Running "make regenerate-opt-urls" in the build/gcc subdirectory ought
to update common.opt.urls for you (provided you've done a "make html").

[...snip...]

Dave



[pushed 1/3] selftests: split out make_fndecl from selftest.h to its own header

2024-05-28 Thread David Malcolm
Avoid selftest.h requiring the "tree" type.
No functional change intended.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-873-gfb7a943ead689e.

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 
---
 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(-)
 create mode 100644 gcc/selftest-tree.h

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index bebe2ed3cd69..0dd5671db1be 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 827734422d88..ea3d722d4b69 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 ..9922af3340f2
--- /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
+<http://www.gnu.org/licenses/>.  */
+
+#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  _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 3bddaf1c3228..808d432ec480 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  _types,
-bool is_variadic = false);
-
 /* Run TESTCASE multiple times, once for each case in our test matrix.  */
 
 extern void
-- 
2.26.3



[pushed 3/3] diagnostics: consolidate global state in diagnostic-color.cc

2024-05-28 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Tested with "make selftest-valgrind" and manually with various
values for GCC_COLORS.
Pushed to trunk as r15-875-g21fc89bac61983.

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 
---
 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 f01a0fc2e377..cbe57ce763f2 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) },
+  { &

[pushed 2/3] libcpp: move label_text to its own header

2024-05-28 Thread David Malcolm
No functional change intended.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-874-g9bda2c4c81b668.

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 
---
 libcpp/Makefile.in |   2 +-
 libcpp/include/label-text.h| 102 +
 libcpp/include/rich-location.h |  79 +
 3 files changed, 105 insertions(+), 78 deletions(-)
 create mode 100644 libcpp/include/label-text.h

diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in
index ebbca3fb..7e47153264c0 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 ..13562cda41f9
--- /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
+<http://www.gnu.org/licenses/>.
+
+ 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 &)
+  : m_buffer (other.m_buffer), m_owned (other.m_owned)
+  {
+other.release ();
+  }
+
+  /* Move assignment.  */
+  label_text & operator= (label_text &)
+  {
+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 a2ece8b033c0..be424cb4b65f 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 &)
-  : m_buffer (other.m_buffer), m_owned (other.m_owned)
-  {
-other.release ();
-  }
-
-  /* Move assignment.  */
-  labe

Re: [PATCH] regenerate-opt-urls.py: fix transposed values for "vax" and "v850"

2024-05-28 Thread David Malcolm
On Tue, 2024-05-28 at 11:41 -0400, David Malcolm wrote:
> > On Tue, 2024-05-28 at 15:03 +0200, Mark Wielaard wrote:
> > Hi Maciej (Hi David, added to CC),
> 
> > On Mon, 2024-05-27 at 05:19 +0100, Maciej W. Rozycki wrote:
> > >  As reported in PR target/79646 and fixed by a change proposed by
> > > Abe we 
> > > have a couple of issues with the descriptions of the VAX
> > > floating-point 
> > > format options in the option definition file.  Additionally most
> > > of
> > > these 
> > > options are not documented in the manual.
> > > 
> > >  This mini patch series addresses these issues, including Abe's
> > > change, 
> > > slightly updated, and my new change.  See individual change
> > > descriptions 
> > > for details.
> > > 
> > >  Verified by inspecting output produced by `vax-netbsdelf-gcc -v
> > > --help' 
> > > and by eyeballing `gcc.info' and `gcc.pdf' files produced. 
> > > Committed.
> > 
> > This broke the gcc-autoregen checker because the
> > gcc/config/vax/vax.opt.urls file wasn't regenerated:
> > https://builder.sourceware.org/buildbot/#/builders/269/builds/5347
> > 
> > Producing the following diff:
> > 
> > diff --git a/gcc/config/vax/vax.opt.urls
> > b/gcc/config/vax/vax.opt.urls
> > index c6b1c418b61..ca78b31dd4c 100644
> > --- a/gcc/config/vax/vax.opt.urls
> > +++ b/gcc/config/vax/vax.opt.urls
> > @@ -1,7 +1,13 @@
> >  ; Autogenerated by regenerate-opt-urls.py from
> > gcc/config/vax/vax.opt and generated HTML
> >  
> > +; skipping UrlSuffix for 'md' due to finding no URLs
> > +
> > +; skipping UrlSuffix for 'md-float' due to finding no URLs
> > +
> >  ; skipping UrlSuffix for 'mg' due to finding no URLs
> >  
> > +; skipping UrlSuffix for 'mg-float' due to finding no URLs
> > +
> >  ; skipping UrlSuffix for 'mgnu' due to finding no URLs
> >  
> >  ; skipping UrlSuffix for 'munix' due to finding no URLs
> > 
> > I am not completely clear on why though. Since it seems you
> > actually
> > did add documentation for exactly these options.
> > 
> > David, should the above diff just be checked in, or do we need to
> > investigate why the URLs weren't found?
> 
> [adding Nick, re the v850 target]
> 
> I found the problem - I messed up when I was populating
> TARGET_SPECIFIC_PAGES in regenerate-opt-urls.py, accidentally
> transposing the entries for v850 and vax by writing:
> 
>     'gcc/V850-Options.html' : 'gcc/config/vax/',
>     'gcc/VAX-Options.html' : 'gcc/config/v850/',
> 
> leading to both gcc/config/v850/v850.opt.urls and
> gcc/config/vax/vax.opt.urls being full of such comments.
> 
> Sorry.
> 
> Fixing that leads to the files for both targets being populated with
> correct-looking URL entries.
> 
> I'll push this to trunk (and backport to gcc 14) after suitable
> testing.

I've pushed this to gcc trunk as r15-872-g7cc529fe514cc6 (having
bootstrapped and lightly tested it on x86_64-pc-linux-gnu)

Dave



PING: Re: [PATCH] selftest: invoke "diff" when ASSERT_STREQ fails

2024-05-28 Thread David Malcolm
Ping.

This patch has actually been *very* helpful to me when debugging
selftest failures involving ASSERT_STREQ.

Thanks
Dave

On Fri, 2024-05-17 at 15:51 -0400, David Malcolm wrote:
> Currently when ASSERT_STREQ or ASSERT_STREQ_AT fail we print
> both strings to stderr.  However it can be hard to figure out
> the problem (e.g. for 1-character differences in long strings).
> 
> Extend the output by writing out the strings to tempfiles and
> invoking "diff -up" on them when we have such a selftest failure,
> to (I hope) simplify debugging.
> 
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> 
> OK for trunk?
> 
> gcc/ChangeLog:
> * selftest.cc (selftest::print_diff): New function.
> (selftest::assert_streq): Call it when we have non-equal
> non-null strings.
> 
> Signed-off-by: David Malcolm 
> ---
>  gcc/selftest.cc | 28 ++--
>  1 file changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/selftest.cc b/gcc/selftest.cc
> index 6438d86a6aa0..f58c0631908e 100644
> --- a/gcc/selftest.cc
> +++ b/gcc/selftest.cc
> @@ -63,6 +63,26 @@ fail_formatted (const location , const char
> *fmt, ...)
>    abort ();
>  }
>  
> +/* Invoke "diff" to print the difference between VAL1 and VAL2
> +   on stdout.  */
> +
> +static void
> +print_diff (const location , const char *val1, const char *val2)
> +{
> +  temp_source_file tmpfile1 (loc, ".txt", val1);
> +  temp_source_file tmpfile2 (loc, ".txt", val2);
> +  const char *args[] = {"diff",
> +   "-up",
> +   tmpfile1.get_filename (),
> +   tmpfile2.get_filename (),
> +   NULL};
> +  int exit_status = 0;
> +  int err = 0;
> +  pex_one (PEX_SEARCH | PEX_LAST,
> +  args[0], CONST_CAST (char **, args),
> +  NULL, NULL, NULL, _status, );
> +}
> +
>  /* Implementation detail of ASSERT_STREQ.
>     Compare val1 and val2 with strcmp.  They ought
>     to be non-NULL; fail gracefully if either or both are NULL.  */
> @@ -89,8 +109,12 @@ assert_streq (const location ,
> if (strcmp (val1, val2) == 0)
>   pass (loc, "ASSERT_STREQ");
> else
> - fail_formatted (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n
> val2=\"%s\"\n",
> - desc_val1, desc_val2, val1, val2);
> + {
> +   print_diff (loc, val1, val2);
> +   fail_formatted
> + (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n
> val2=\"%s\"\n",
> +  desc_val1, desc_val2, val1, val2);
> + }
>    }
>  }
>  



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

2024-05-28 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-866-g2dbb1c124c1e58.

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 
---
 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 982d68b872ea..938bd583a3da 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 1f30d1d7cdac..f27b2f1a492c 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), , 0, nullptr, _loc);
+  text_info ti (m_localize_events ? _(fmt) : fmt,
+   , 0, nullptr, _loc);
   pp_format (pp, );
   pp_output_formatted_text (pp);
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 743a8c2a1d29..0ad6c5beb81c 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 
)
 }
 
 /* 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)
-- 
2.26.3



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

2024-05-28 Thread David Malcolm
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).

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-865-gb544ff88560e10.

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 
---
 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(-)
 create mode 100644 gcc/c-family/c-type-mismatch.cc
 create mode 100644 gcc/c-family/c-type-mismatch.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a7f15694c34b..66d42cc41f84 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 9c4deabc1095..7a5ffc25602c 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
 #include "selftest-diagnostic.h"
 #include "builtins.h"
 #include "attribs.h"
-#include "gcc-rich-location.h"
+#include "c-family/c-type-mismatch.h"
 
 /* Handle attributes associated with format checking.  */
 
diff --git a/gcc/c-family/c-typ

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

2024-05-28 Thread David Malcolm
> On Tue, 2024-05-28 at 15:03 +0200, Mark Wielaard wrote:
> Hi Maciej (Hi David, added to CC),

>On Mon, 2024-05-27 at 05:19 +0100, Maciej W. Rozycki wrote:
> >  As reported in PR target/79646 and fixed by a change proposed by
> > Abe we 
> > have a couple of issues with the descriptions of the VAX
> > floating-point 
> > format options in the option definition file.  Additionally most of
> > these 
> > options are not documented in the manual.
> > 
> >  This mini patch series addresses these issues, including Abe's
> > change, 
> > slightly updated, and my new change.  See individual change
> > descriptions 
> > for details.
> > 
> >  Verified by inspecting output produced by `vax-netbsdelf-gcc -v
> > --help' 
> > and by eyeballing `gcc.info' and `gcc.pdf' files produced. 
> > Committed.
>
> This broke the gcc-autoregen checker because the
> gcc/config/vax/vax.opt.urls file wasn't regenerated:
> https://builder.sourceware.org/buildbot/#/builders/269/builds/5347
> 
> Producing the following diff:
> 
> diff --git a/gcc/config/vax/vax.opt.urls
> b/gcc/config/vax/vax.opt.urls
> index c6b1c418b61..ca78b31dd4c 100644
> --- a/gcc/config/vax/vax.opt.urls
> +++ b/gcc/config/vax/vax.opt.urls
> @@ -1,7 +1,13 @@
>  ; Autogenerated by regenerate-opt-urls.py from
> gcc/config/vax/vax.opt and generated HTML
>  
> +; skipping UrlSuffix for 'md' due to finding no URLs
> +
> +; skipping UrlSuffix for 'md-float' due to finding no URLs
> +
>  ; skipping UrlSuffix for 'mg' due to finding no URLs
>  
> +; skipping UrlSuffix for 'mg-float' due to finding no URLs
> +
>  ; skipping UrlSuffix for 'mgnu' due to finding no URLs
>  
>  ; skipping UrlSuffix for 'munix' due to finding no URLs
> 
> I am not completely clear on why though. Since it seems you actually
> did add documentation for exactly these options.
> 
> David, should the above diff just be checked in, or do we need to
> investigate why the URLs weren't found?

[adding Nick, re the v850 target]

I found the problem - I messed up when I was populating
TARGET_SPECIFIC_PAGES in regenerate-opt-urls.py, accidentally
transposing the entries for v850 and vax by writing:

'gcc/V850-Options.html' : 'gcc/config/vax/',
'gcc/VAX-Options.html' : 'gcc/config/v850/',

leading to both gcc/config/v850/v850.opt.urls and
gcc/config/vax/vax.opt.urls being full of such comments.

Sorry.

Fixing that leads to the files for both targets being populated with
correct-looking URL entries.

I'll push this to trunk (and backport to gcc 14) after suitable testing.

Dave

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

Re: [RFC][PATCH] PR tree-optimization/109071 - -Warray-bounds false positive warnings due to code duplication from jump threading

2024-05-23 Thread David Malcolm
On Thu, 2024-05-23 at 14:03 +, Qing Zhao wrote:

[...snip...]

> Is “location_adhoc_data” an available data structure in current GCC?
> I just searched GCC source tree, cannot find it. 

It's in libcpp/include/line-table.h; see the big comment at the top of
that file.

Dave



Re: [RFC][PATCH] PR tree-optimization/109071 - -Warray-bounds false positive warnings due to code duplication from jump threading

2024-05-21 Thread David Malcolm
On Tue, 2024-05-21 at 15:13 +, Qing Zhao wrote:
> Thanks for the comments and suggestions.
> 
> > On May 15, 2024, at 10:00, David Malcolm 
> > wrote:
> > 
> > On Tue, 2024-05-14 at 15:08 +0200, Richard Biener wrote:
> > > On Mon, 13 May 2024, Qing Zhao wrote:
> > > 
> > > > -Warray-bounds is an important option to enable linux kernal to
> > > > keep
> > > > the array out-of-bound errors out of the source tree.
> > > > 
> > > > However, due to the false positive warnings reported in
> > > > PR109071
> > > > (-Warray-bounds false positive warnings due to code duplication
> > > > from
> > > > jump threading), -Warray-bounds=1 cannot be added on by
> > > > default.
> > > > 
> > > > Although it's impossible to elinimate all the false positive
> > > > warnings
> > > > from -Warray-bounds=1 (See PR104355 Misleading -Warray-bounds
> > > > documentation says "always out of bounds"), we should minimize
> > > > the
> > > > false positive warnings in -Warray-bounds=1.
> > > > 
> > > > The root reason for the false positive warnings reported in
> > > > PR109071 is:
> > > > 
> > > > When the thread jump optimization tries to reduce the # of
> > > > branches
> > > > inside the routine, sometimes it needs to duplicate the code
> > > > and
> > > > split into two conditional pathes. for example:
> > > > 
> > > > The original code:
> > > > 
> > > > void sparx5_set (int * ptr, struct nums * sg, int index)
> > > > {
> > > >   if (index >= 4)
> > > >     warn ();
> > > >   *ptr = 0;
> > > >   *val = sg->vals[index];
> > > >   if (index >= 4)
> > > >     warn ();
> > > >   *ptr = *val;
> > > > 
> > > >   return;
> > > > }
> > > > 
> > > > With the thread jump, the above becomes:
> > > > 
> > > > void sparx5_set (int * ptr, struct nums * sg, int index)
> > > > {
> > > >   if (index >= 4)
> > > >     {
> > > >   warn ();
> > > >   *ptr = 0; // Code duplications since "warn" does
> > > > return;
> > > >   *val = sg->vals[index];   // same this line.
> > > >     // In this path, since it's
> > > > under
> > > > the condition
> > > >     // "index >= 4", the compiler
> > > > knows
> > > > the value
> > > >     // of "index" is larger then 4,
> > > > therefore the
> > > >     // out-of-bound warning.
> > > >   warn ();
> > > >     }
> > > >   else
> > > >     {
> > > >   *ptr = 0;
> > > >   *val = sg->vals[index];
> > > >     }
> > > >   *ptr = *val;
> > > >   return;
> > > > }
> > > > 
> > > > We can see, after the thread jump optimization, the # of
> > > > branches
> > > > inside
> > > > the routine "sparx5_set" is reduced from 2 to 1, however,  due
> > > > to
> > > > the
> > > > code duplication (which is needed for the correctness of the
> > > > code),
> > > > we
> > > > got a false positive out-of-bound warning.
> > > > 
> > > > In order to eliminate such false positive out-of-bound warning,
> > > > 
> > > > A. Add one more flag for GIMPLE: is_splitted.
> > > > B. During the thread jump optimization, when the basic blocks
> > > > are
> > > >    duplicated, mark all the STMTs inside the original and
> > > > duplicated
> > > >    basic blocks as "is_splitted";
> > > > C. Inside the array bound checker, add the following new
> > > > heuristic:
> > > > 
> > > > If
> > > >    1. the stmt is duplicated and splitted into two conditional
> > > > paths;
> > > > +  2. the warning level < 2;
> > > > +  3. the current block is not dominating the exit block
> > > > Then not report the warning.
> > > > 
> > > > The false positive warnings are moved from -Warray-bounds=1 to
> > > >  -Warray-bounds=2 now.
> > > > 
> > > > Bootstrapped and regression tested on both x86 and aarch64.
> > > > adjusted
> > > >  -Warray-bounds-61.c due to the false positive warnings.
> > > > 
> > > > Let me know if you have any comments and suggestions.
> > > 
> > > At the last Cauldron I talked with David Malcolm about these kind
> > > of
> > > issues and thought of instead of suppressing diagnostics to
> > > record
> > > how a block was duplicated.  For jump threading my idea was to
> > > record
> > > the condition that was proved true when entering the path and do
> > > this
> > > by recording the corresponding locations
> 
> Is only recording the location for the TRUE path  enough?
> We might need to record the corresponding locations for both TRUE and
> FALSE paths since the VRP might be more accurate on both paths. 
> Is only recording the location is enough? 
> Do we need to record the pointer to the original condition stmt?

Just to be clear: I don't plan to work on this myself (I have far too
much already to work on...); I'm assuming Richard Biener is
hoping/planning to implement this himself.

But feel free to ask me any questions about the diagnostic_path
machinery within the diagnostics subsystem.

[...snip...]

Regards
Dave



Re: [COMMITTED] Regenerate riscv.opt.urls and i386.opt.urls

2024-05-20 Thread David Malcolm
On Mon, 2024-05-20 at 16:19 +, Jiang, Haochen wrote:
> Thanks for your help! I haven't noticed this file is newly added to
> GCC.
> I suppose that is why the buildbot is reporting something the whole
> afternoon for me.
> 
> So just for confirm, does that mean we will always need to run
> gcc/regenerate-opt-urls.py after adding or removing options in GCC?
> My current understanding is yes.

Yes please (and make sure you've got a clean build of the HTML docs
with the new options added when you do)

Though if you forget, the only problem will be some missing URLs at the
command line, and complaints from the CI.

Dave

> 
> Thx,
> Haochen
> 
> > -Original Message-
> > From: Mark Wielaard 
> > Sent: Monday, May 20, 2024 7:22 PM
> > To: gcc-patches@gcc.gnu.org
> > Cc: Palmer Dabbelt ; Jeff Law
> > ; Jiang, Haochen ;
> > Hu,
> > Lin1 ; Mark Wielaard 
> > Subject: [COMMITTED] Regenerate riscv.opt.urls and i386.opt.urls
> > 
> > risc-v added an -mfence-tso option. i386 removed Xeon Phi ISA
> > support options.
> > But the opt.urls files weren't regenerated.
> > 
> > Fixes: a6114c2a6911 ("RISC-V: Implement -m{,no}fence-tso")
> > Fixes: e1a7e2c54d52 ("i386: Remove Xeon Phi ISA support")
> > 
> > gcc/ChangeLog:
> > 
> > * config/riscv/riscv.opt.urls: Regenerate.
> > * config/i386/i386.opt.urls: Likewise.
> > ---
> >  gcc/config/i386/i386.opt.urls   | 15 ---
> >  gcc/config/riscv/riscv.opt.urls |  3 +++
> >  2 files changed, 3 insertions(+), 15 deletions(-)
> > 
> > diff --git a/gcc/config/i386/i386.opt.urls
> > b/gcc/config/i386/i386.opt.urls index
> > 81c5bb9a9270..40e8a8449367 100644
> > --- a/gcc/config/i386/i386.opt.urls
> > +++ b/gcc/config/i386/i386.opt.urls
> > @@ -238,12 +238,6 @@ UrlSuffix(gcc/x86-Options.html#index-mavx2)
> >  mavx512f
> >  UrlSuffix(gcc/x86-Options.html#index-mavx512f)
> > 
> > -mavx512pf
> > -UrlSuffix(gcc/x86-Options.html#index-mavx512pf)
> > -
> > -mavx512er
> > -UrlSuffix(gcc/x86-Options.html#index-mavx512er)
> > -
> >  mavx512cd
> >  UrlSuffix(gcc/x86-Options.html#index-mavx512cd)
> > 
> > @@ -262,12 +256,6 @@ UrlSuffix(gcc/x86-Options.html#index-
> > mavx512ifma)
> >  mavx512vbmi
> >  UrlSuffix(gcc/x86-Options.html#index-mavx512vbmi)
> > 
> > -mavx5124fmaps
> > -UrlSuffix(gcc/x86-Options.html#index-mavx5124fmaps)
> > -
> > -mavx5124vnniw
> > -UrlSuffix(gcc/x86-Options.html#index-mavx5124vnniw)
> > -
> >  mavx512vpopcntdq
> >  UrlSuffix(gcc/x86-Options.html#index-mavx512vpopcntdq)
> > 
> > @@ -409,9 +397,6 @@ UrlSuffix(gcc/x86-Options.html#index-mrdrnd)
> >  mf16c
> >  UrlSuffix(gcc/x86-Options.html#index-mf16c)
> > 
> > -mprefetchwt1
> > -UrlSuffix(gcc/x86-Options.html#index-mprefetchwt1)
> > -
> >  mfentry
> >  UrlSuffix(gcc/x86-Options.html#index-mfentry)
> > 
> > diff --git a/gcc/config/riscv/riscv.opt.urls
> > b/gcc/config/riscv/riscv.opt.urls index
> > 2f01ae5d6271..e02ef3ee3dd9 100644
> > --- a/gcc/config/riscv/riscv.opt.urls
> > +++ b/gcc/config/riscv/riscv.opt.urls
> > @@ -91,3 +91,6 @@ UrlSuffix(gcc/RISC-V-Options.html#index-minline-
> > strlen)
> > 
> >  ; skipping UrlSuffix for 'mtls-dialect=' due to finding no URLs
> > 
> > +mfence-tso
> > +UrlSuffix(gcc/RISC-V-Options.html#index-mfence-tso)
> > +
> > --
> > 2.45.1
> 



[pushed] Regenerate common.opt.urls

2024-05-17 Thread David Malcolm
I forgot to do this for r15-636-g770657d02c986c.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-640-g4e3bb431bbf280.

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

Signed-off-by: David Malcolm 
---
 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)
 
-- 
2.26.3



[PATCH] selftest: invoke "diff" when ASSERT_STREQ fails

2024-05-17 Thread David Malcolm
Currently when ASSERT_STREQ or ASSERT_STREQ_AT fail we print
both strings to stderr.  However it can be hard to figure out
the problem (e.g. for 1-character differences in long strings).

Extend the output by writing out the strings to tempfiles and
invoking "diff -up" on them when we have such a selftest failure,
to (I hope) simplify debugging.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

OK for trunk?

gcc/ChangeLog:
* selftest.cc (selftest::print_diff): New function.
(selftest::assert_streq): Call it when we have non-equal
non-null strings.

Signed-off-by: David Malcolm 
---
 gcc/selftest.cc | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/gcc/selftest.cc b/gcc/selftest.cc
index 6438d86a6aa0..f58c0631908e 100644
--- a/gcc/selftest.cc
+++ b/gcc/selftest.cc
@@ -63,6 +63,26 @@ fail_formatted (const location , const char *fmt, ...)
   abort ();
 }
 
+/* Invoke "diff" to print the difference between VAL1 and VAL2
+   on stdout.  */
+
+static void
+print_diff (const location , const char *val1, const char *val2)
+{
+  temp_source_file tmpfile1 (loc, ".txt", val1);
+  temp_source_file tmpfile2 (loc, ".txt", val2);
+  const char *args[] = {"diff",
+   "-up",
+   tmpfile1.get_filename (),
+   tmpfile2.get_filename (),
+   NULL};
+  int exit_status = 0;
+  int err = 0;
+  pex_one (PEX_SEARCH | PEX_LAST,
+  args[0], CONST_CAST (char **, args),
+  NULL, NULL, NULL, _status, );
+}
+
 /* Implementation detail of ASSERT_STREQ.
Compare val1 and val2 with strcmp.  They ought
to be non-NULL; fail gracefully if either or both are NULL.  */
@@ -89,8 +109,12 @@ assert_streq (const location ,
if (strcmp (val1, val2) == 0)
  pass (loc, "ASSERT_STREQ");
else
- fail_formatted (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n 
val2=\"%s\"\n",
- desc_val1, desc_val2, val1, val2);
+ {
+   print_diff (loc, val1, val2);
+   fail_formatted
+ (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n val2=\"%s\"\n",
+  desc_val1, desc_val2, val1, val2);
+ }
   }
 }
 
-- 
2.26.3



[pushed] diagnostics, analyzer: add CFG edge visualization to path-printing

2024-05-17 Thread David Malcolm
ow_test): New.
(selftest::test_control_flow_1): New.
(selftest::test_control_flow_2): New.
(selftest::test_control_flow_3): New.
(selftest::assert_cfg_edge_path_streq): New.
(ASSERT_CFG_EDGE_PATH_STREQ): New macro.
(selftest::test_control_flow_4): New.
(selftest::test_control_flow_5): New.
(selftest::test_control_flow_6): New.
(selftest::control_flow_tests): New.
(selftest::tree_diagnostic_path_cc_tests): Disable colorization on
global_dc's printer.  Convert event_pp to a std::unique_ptr. Call
control_flow_tests via for_each_line_table_case.
(gen_command_line_string): Likewise.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/event-links-ascii.c: New test.
* gcc.dg/analyzer/event-links-color.c: New test.
* gcc.dg/analyzer/event-links-disabled.c: New test.
* gcc.dg/analyzer/event-links-unicode.c: New test.

libcpp/ChangeLog:
* include/rich-location.h (class label_effects): New forward decl.
(range_label::get_effects): New vfunc.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/checker-event.h  |3 +
 gcc/analyzer/infinite-loop.cc |   18 +-
 gcc/common.opt|4 +
 gcc/diagnostic-label-effects.h|   58 +
 gcc/diagnostic-path.h |   16 +
 gcc/diagnostic-show-locus.cc  |  387 +-
 gcc/diagnostic.cc |   12 +
 gcc/diagnostic.h  |   17 +-
 gcc/doc/invoke.texi   |   29 +-
 gcc/lto-wrapper.cc|3 +
 gcc/opts-common.cc|3 +-
 gcc/opts.cc   |5 +
 .../gcc.dg/analyzer/event-links-ascii.c   |   61 +
 .../gcc.dg/analyzer/event-links-color.c   |   66 +
 .../gcc.dg/analyzer/event-links-disabled.c|   55 +
 .../gcc.dg/analyzer/event-links-unicode.c |   62 +
 gcc/text-art/theme.cc |   30 +
 gcc/text-art/theme.h  |   11 +-
 gcc/toplev.cc |2 +
 gcc/tree-diagnostic-path.cc   | 1178 -
 libcpp/include/rich-location.h|7 +
 21 files changed, 1959 insertions(+), 68 deletions(-)
 create mode 100644 gcc/diagnostic-label-effects.h
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/event-links-ascii.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/event-links-color.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/event-links-disabled.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/event-links-unicode.c

diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index d2fb87fb523f..7a4510ee81d0 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -113,6 +113,7 @@ public:
   return NULL;
   }
   meaning get_meaning () const override;
+  bool connect_to_next_event_p () const override { return false; }
   diagnostic_thread_id_t get_thread_id () const final override
   {
 return 0;
@@ -451,6 +452,7 @@ public:
   }
 
   label_text get_desc (bool can_colorize) const override;
+  bool connect_to_next_event_p () const final override { return true; }
 
 protected:
   label_text maybe_describe_condition (bool can_colorize) const;
@@ -534,6 +536,7 @@ public:
 
   label_text get_desc (bool can_colorize) const final override;
   meaning get_meaning () const override;
+  bool connect_to_next_event_p () const final override { return true; }
 
  private:
   bool m_edge_sense;
diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc
index e277a8384a04..04346cdfdc3c 100644
--- a/gcc/analyzer/infinite-loop.cc
+++ b/gcc/analyzer/infinite-loop.cc
@@ -162,6 +162,21 @@ public:
   }
 };
 
+class looping_back_event : public start_cfg_edge_event
+{
+public:
+  looping_back_event (const exploded_edge ,
+ const event_loc_info _info)
+  : start_cfg_edge_event (eedge, loc_info)
+  {
+  }
+
+  label_text get_desc (bool can_colorize) const final override
+  {
+return label_text::borrow ("looping back...");
+  }
+};
+
 /* A subclass of pending_diagnostic for complaining about suspected
infinite loops.  */
 
@@ -300,8 +315,7 @@ public:
else if (cfg_sedge->back_edge_p ())
  {
emission_path->add_event
- (make_unique
-  (loc_info_from, "looping back..."));
+ (make_unique (*eedge, loc_info_from));
emission_path->add_event
  (make_unique
   (*eedge,
diff --git a/gcc/common.opt b/gcc/common.opt
index 40cab3cb36a3..9566122ca50e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1368,6 +1368,10 @@ fdiagnostics-show-caret
 Common Var(flag_diagnostics_show_caret) Init(1)
 Show the source line with a caret indicating the column.
 
+fdiagnostics-show-event-links
+C

[pushed] diagnostics: use unicode art for interprocedural depth

2024-05-15 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-535-ge656656e711949.

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 
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c  |  26 +-
 .../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::INTERPROCEDURAL_POP_FRAMES_MIDDLE:
+  return '-';
+case cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT:
+  return '+';
   

[pushed] diagnostics: add warning emoji to events with VERB_danger

2024-05-15 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-534-g0b7ebe5427a4af.

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 
---
 .../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(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/warning-emoji.c

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_show_color (global_dc->printer);
+pp_show_color () = colorize;
 diagnostic_event_id_t event_id (event_idx);
-pp_printf (, "%@ %s", _id, event_text.get ());
+
+pp_printf (, "%@", _id);
+pp_space ();
+
+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 (, 0x2

[pushed] diagnostics: simplify output of purely intraprocedural execution paths

2024-05-15 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-533-g3cd267446755ab.

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 
---
 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 +-
 .../analyzer/analyzer-verbosity-0.c   |  40 +-
 .../analyzer/analyzer-verbosity-1.c   |  40 +-
 .../analyzer/analyzer-verbosity-2.c   |  40 +-
 .../analyzer/analyzer-verbosity-3.c   |  40 +-
 .../analyzer/malloc-macro-inline-events.c |  83 +--
 .../analyzer/malloc-paths-9-noexcept.c| 604 +-
 .../c-c++-common/analyzer/setjmp-2.c  | 140 ++--
 .../gcc.dg/analyzer/malloc-paths-9.c  | 302 +
 .../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
+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_

[pushed] diagnostics: handle SGR codes in line_label::m_display_width

2024-05-15 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-532-ga7be993806a90a.

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 
---
 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
 <http://www.gnu.org/licenses/>.  */
 
 #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 ,
- 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));
 }
   }
-- 
2.26.3



[pushed] analyzer: fix ICE seen with -fsanitize=undefined [PR114899]

2024-05-15 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-526-g1779e22150b917.

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 
---
 gcc/analyzer/access-diagram.cc|  3 ++-
 .../analyzer/out-of-bounds-diagram-pr114899.c | 15 +++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 
gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c

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 ".*" } */
-- 
2.26.3



Re: [RFC][PATCH] PR tree-optimization/109071 - -Warray-bounds false positive warnings due to code duplication from jump threading

2024-05-15 Thread David Malcolm
On Tue, 2024-05-14 at 15:08 +0200, Richard Biener wrote:
> On Mon, 13 May 2024, Qing Zhao wrote:
> 
> > -Warray-bounds is an important option to enable linux kernal to
> > keep
> > the array out-of-bound errors out of the source tree.
> > 
> > However, due to the false positive warnings reported in PR109071
> > (-Warray-bounds false positive warnings due to code duplication
> > from
> > jump threading), -Warray-bounds=1 cannot be added on by default.
> > 
> > Although it's impossible to elinimate all the false positive
> > warnings
> > from -Warray-bounds=1 (See PR104355 Misleading -Warray-bounds
> > documentation says "always out of bounds"), we should minimize the
> > false positive warnings in -Warray-bounds=1.
> > 
> > The root reason for the false positive warnings reported in
> > PR109071 is:
> > 
> > When the thread jump optimization tries to reduce the # of branches
> > inside the routine, sometimes it needs to duplicate the code and
> > split into two conditional pathes. for example:
> > 
> > The original code:
> > 
> > void sparx5_set (int * ptr, struct nums * sg, int index)
> > {
> >   if (index >= 4)
> >     warn ();
> >   *ptr = 0;
> >   *val = sg->vals[index];
> >   if (index >= 4)
> >     warn ();
> >   *ptr = *val;
> > 
> >   return;
> > }
> > 
> > With the thread jump, the above becomes:
> > 
> > void sparx5_set (int * ptr, struct nums * sg, int index)
> > {
> >   if (index >= 4)
> >     {
> >   warn ();
> >   *ptr = 0; // Code duplications since "warn" does
> > return;
> >   *val = sg->vals[index];   // same this line.
> > // In this path, since it's under
> > the condition
> > // "index >= 4", the compiler knows
> > the value
> > // of "index" is larger then 4,
> > therefore the
> > // out-of-bound warning.
> >   warn ();
> >     }
> >   else
> >     {
> >   *ptr = 0;
> >   *val = sg->vals[index];
> >     }
> >   *ptr = *val;
> >   return;
> > }
> > 
> > We can see, after the thread jump optimization, the # of branches
> > inside
> > the routine "sparx5_set" is reduced from 2 to 1, however,  due to
> > the
> > code duplication (which is needed for the correctness of the code),
> > we
> > got a false positive out-of-bound warning.
> > 
> > In order to eliminate such false positive out-of-bound warning,
> > 
> > A. Add one more flag for GIMPLE: is_splitted.
> > B. During the thread jump optimization, when the basic blocks are
> >    duplicated, mark all the STMTs inside the original and
> > duplicated
> >    basic blocks as "is_splitted";
> > C. Inside the array bound checker, add the following new heuristic:
> > 
> > If
> >    1. the stmt is duplicated and splitted into two conditional
> > paths;
> > +  2. the warning level < 2;
> > +  3. the current block is not dominating the exit block
> > Then not report the warning.
> > 
> > The false positive warnings are moved from -Warray-bounds=1 to
> >  -Warray-bounds=2 now.
> > 
> > Bootstrapped and regression tested on both x86 and aarch64.
> > adjusted
> >  -Warray-bounds-61.c due to the false positive warnings.
> > 
> > Let me know if you have any comments and suggestions.
> 
> At the last Cauldron I talked with David Malcolm about these kind of
> issues and thought of instead of suppressing diagnostics to record
> how a block was duplicated.  For jump threading my idea was to record
> the condition that was proved true when entering the path and do this
> by recording the corresponding locations so that in the end we can
> use the diagnostic-path infrastructure to say
> 
> warning: array index always above array bounds
> events 1:
> 
> > 3 |  if (index >= 4)
>  |
>     (1) when index >= 4
> 
> it would be possible to record the info as part of the ad-hoc
> location data on each duplicated stmt or, possibly simpler,
> as part of a debug stmt of new kind.
> 
> I'm not sure pruning the warnings is a good thing to do.  One
> would argue we should instead isolate such path as unreachable
> since it invokes undefined behavior.  In particular your
> example is clearly a bug and should be diagnosed.
> 
> Note very similar issues happen w

Re: [PATCH] testsuite: analyzer: Fix fd-glibc-byte-stream-connection-server.c on Solaris [PR107750]

2024-05-14 Thread David Malcolm
On Tue, 2024-05-14 at 14:32 +0200, Rainer Orth wrote:
> gcc.dg/analyzer/fd-glibc-byte-stream-connection-server.c currently
> FAILs
> on Solaris:
> 
> FAIL: gcc.dg/analyzer/fd-glibc-byte-stream-connection-server.c (test
> for excess errors)
> 
> Excess errors:
> /vol/gcc/src/hg/master/local/gcc/testsuite/gcc.dg/analyzer/fd-glibc-
> byte-stream-connection-server.c:91:3: error: implicit declaration of
> function 'memset' [-Wimplicit-function-declaration]
> 
> Solaris  has
> 
> #define FD_ZERO(__p)    (void) memset((__p), 0, sizeof (*(__p))) 
> 
> but no declaration of memset.  While one can argue that this should
> be
> fixed, it's easy enough to just include  instead, which is
> what this patch does.
> 
> Tested on i386-pc-solaris2.11 and i686-pc-linux-gnu.
> 
> Ok for trunk?

Yes, thanks.

Dave



Re: [EXTERNAL] [COMMITTED] Regenerate cygming.opt.urls and mingw.opt.urls

2024-05-13 Thread David Malcolm
On Mon, 2024-05-13 at 09:42 -0400, David Malcolm wrote:
> On Mon, 2024-05-13 at 11:14 +0200, Mark Wielaard wrote:
> > Hi Evgeny,
> > 
> > Adding David to the CC, who might know the details.
> > 
> > On Mon, May 13, 2024 at 08:44:12AM +, Evgeny Karpov wrote:
> > > Sunday, May 12, 2024
> > > 
> > > Thank you for reviewing our changes related to the refactoring of
> > > extracting the MinGW implementation from ix64.
> > > 
> > > It was expected to move the MinGW-related files without changes
> > > in
> > > this commit ("Reuse MinGW from i386 for AArch64") and apply the
> > > renaming in a follow-up commit, which has been done in 'Rename
> > > "x86
> > > Windows Options" to "Cygwin and MinGW Options"'.
> > > 
> > > The script to update opt.urls files has been used.
> > > 
> > > > diff --git a/gcc/config/mingw/cygming.opt.urls
> > > > b/gcc/config/mingw/cygming.opt.urls
> > > > index c624e22e4427..af11c4997609 100644
> > > > --- a/gcc/config/mingw/cygming.opt.urls
> > > > +++ b/gcc/config/mingw/cygming.opt.urls
> > > > @@ -1,4 +1,4 @@
> > > 
> > > > -; Autogenerated by regenerate-opt-urls.py from
> > > > gcc/config/i386/cygming.opt
> > > > and generated HTML
> > > > +; Autogenerated by regenerate-opt-urls.py from
> > > > +gcc/config/mingw/cygming.opt and generated HTML
> > > 
> > > I am not sure why this comment has not been updated. Is it
> > > critical
> > > or it could be updated next time when it is needed?
> > 
> > Odd that the script didn't update this comment, it really should
> > have.
> > It might be that running the script through make regenerate-opt-
> > urls
> > inside the gcc build subdir invokes regenerate-opt-urls.py slightly
> > differently so that this line is updated.
> 
> It might be a "make" dependencies issue:
> "make regenerate-opt-urls" has dependencies on OPT_URLS_HTML_DEPS
> which
> is currently defined as:
> OPT_URLS_HTML_DEPS = $(build_htmldir)/gcc/Option-Index.html \
> $(build_htmldir)/gdc/Option-Index.html \
> $(build_htmldir)/gfortran/Option-Index.html
> which might not be enough for the doc changes when moving things
> around
> that affect other generated html files.
> 
> So when the CI runs "make regenerate-opt-urls" in a pristine build it
> will forcibly rerun texinfo to regenerate the docs first, whereas if
> you manually run the script in a build directory, you might not be
> seeing the latest version of the HTML (especially in thre presence of
> file moves).
> 
> So I think the Makefile as currently written handles most cases, but
> can get it slightly wrong for the case you ran into here (sorry);
> fully
> refreshing the built docs ought to fix such cases.

Specifically, if you have some generated .html files in the
$(build_htmldir) from a file that has gone away (due to a move), then I
suspect these .html files stick around until you fully delete the
$(build_htmldir), and in the meantime they get found by regenerate-opt-
urls.py and lead to duplicate enries, leading to differences against a
pristine build dir.

Dave

> 
> That's my theory of what happened here, anyway.
> 
> Dave
> 
> > 
> > > >  mconsole
> > > >  UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mconsole)
> > > > @@ -9,9 +9,8 @@ UrlSuffix(gcc/Cygwin-and-MinGW-
> > > > Options.html#index-
> > > > mdll)
> > > >  mnop-fun-dllimport
> > > >  UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mnop-fun-
> > > > dllimport)
> > > > 
> > > > -; skipping UrlSuffix for 'mthreads' due to multiple URLs:
> > > > -;   duplicate: 'gcc/Cygwin-and-MinGW-Options.html#index-
> > > > mthreads-1'
> > > > -;   duplicate: 'gcc/x86-Options.html#index-mthreads'
> > > > +mthreads
> > > > +UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mthreads-1)
> > > 
> > > mthreads has the same issue before applying changes. Has
> > > something
> > > been changed recently?
> > > This is the change in patch series in 'Rename "x86 Windows
> > > Options"
> > > to "Cygwin and MinGW Options"' commit.
> > > 
> > > ; skipping UrlSuffix for 'mthreads' due to multiple URLs:
> > > +;   duplicate: 'gcc/Cygwin-and-MinGW-Options.html#index-
> > > mthreads-
> > > 1'
> > >  ;   duplicate: 'gcc/x86-Options.html#index-mthreads'
> > > -;   duplicate: 'gcc/x86-Windows-Options.html#index-mthreads-1'
> > 
> > Again, it might be caused by invoking the script by hand vs with
> > make
> > regenerate-opt-urls.py. I believe with the make option it will
> > renumber the suffixes making sure the urls are unique.
> > 
> > BTW. There is a CI buildbot that tries to regenerate all generated
> > files, which is how I spotted this:
> > https://builder.sourceware.org/buildbot/#/builders/gcc-autoregen
> > (It should also sent email to the author of the patch on failure.)
> > 
> > Cheers,
> > 
> > Mark
> > 
> 



Re: [EXTERNAL] [COMMITTED] Regenerate cygming.opt.urls and mingw.opt.urls

2024-05-13 Thread David Malcolm
On Mon, 2024-05-13 at 11:14 +0200, Mark Wielaard wrote:
> Hi Evgeny,
> 
> Adding David to the CC, who might know the details.
> 
> On Mon, May 13, 2024 at 08:44:12AM +, Evgeny Karpov wrote:
> > Sunday, May 12, 2024
> > 
> > Thank you for reviewing our changes related to the refactoring of
> > extracting the MinGW implementation from ix64.
> > 
> > It was expected to move the MinGW-related files without changes in
> > this commit ("Reuse MinGW from i386 for AArch64") and apply the
> > renaming in a follow-up commit, which has been done in 'Rename "x86
> > Windows Options" to "Cygwin and MinGW Options"'.
> > 
> > The script to update opt.urls files has been used.
> > 
> > > diff --git a/gcc/config/mingw/cygming.opt.urls
> > > b/gcc/config/mingw/cygming.opt.urls
> > > index c624e22e4427..af11c4997609 100644
> > > --- a/gcc/config/mingw/cygming.opt.urls
> > > +++ b/gcc/config/mingw/cygming.opt.urls
> > > @@ -1,4 +1,4 @@
> > 
> > > -; Autogenerated by regenerate-opt-urls.py from
> > > gcc/config/i386/cygming.opt
> > > and generated HTML
> > > +; Autogenerated by regenerate-opt-urls.py from
> > > +gcc/config/mingw/cygming.opt and generated HTML
> > 
> > I am not sure why this comment has not been updated. Is it critical
> > or it could be updated next time when it is needed?
> 
> Odd that the script didn't update this comment, it really should
> have.
> It might be that running the script through make regenerate-opt-urls
> inside the gcc build subdir invokes regenerate-opt-urls.py slightly
> differently so that this line is updated.

It might be a "make" dependencies issue:
"make regenerate-opt-urls" has dependencies on OPT_URLS_HTML_DEPS which
is currently defined as:
OPT_URLS_HTML_DEPS = $(build_htmldir)/gcc/Option-Index.html \
$(build_htmldir)/gdc/Option-Index.html \
$(build_htmldir)/gfortran/Option-Index.html
which might not be enough for the doc changes when moving things around
that affect other generated html files.

So when the CI runs "make regenerate-opt-urls" in a pristine build it
will forcibly rerun texinfo to regenerate the docs first, whereas if
you manually run the script in a build directory, you might not be
seeing the latest version of the HTML (especially in thre presence of
file moves).

So I think the Makefile as currently written handles most cases, but
can get it slightly wrong for the case you ran into here (sorry); fully
refreshing the built docs ought to fix such cases.

That's my theory of what happened here, anyway.

Dave

> 
> > >  mconsole
> > >  UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mconsole)
> > > @@ -9,9 +9,8 @@ UrlSuffix(gcc/Cygwin-and-MinGW-
> > > Options.html#index-
> > > mdll)
> > >  mnop-fun-dllimport
> > >  UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mnop-fun-
> > > dllimport)
> > > 
> > > -; skipping UrlSuffix for 'mthreads' due to multiple URLs:
> > > -;   duplicate: 'gcc/Cygwin-and-MinGW-Options.html#index-
> > > mthreads-1'
> > > -;   duplicate: 'gcc/x86-Options.html#index-mthreads'
> > > +mthreads
> > > +UrlSuffix(gcc/Cygwin-and-MinGW-Options.html#index-mthreads-1)
> > 
> > mthreads has the same issue before applying changes. Has something
> > been changed recently?
> > This is the change in patch series in 'Rename "x86 Windows Options"
> > to "Cygwin and MinGW Options"' commit.
> > 
> > ; skipping UrlSuffix for 'mthreads' due to multiple URLs:
> > +;   duplicate: 'gcc/Cygwin-and-MinGW-Options.html#index-mthreads-
> > 1'
> >  ;   duplicate: 'gcc/x86-Options.html#index-mthreads'
> > -;   duplicate: 'gcc/x86-Windows-Options.html#index-mthreads-1'
> 
> Again, it might be caused by invoking the script by hand vs with make
> regenerate-opt-urls.py. I believe with the make option it will
> renumber the suffixes making sure the urls are unique.
> 
> BTW. There is a CI buildbot that tries to regenerate all generated
> files, which is how I spotted this:
> https://builder.sourceware.org/buildbot/#/builders/gcc-autoregen
> (It should also sent email to the author of the patch on failure.)
> 
> Cheers,
> 
> Mark
> 



[PATCH 21/21] diagnostics: fix corrupt json/SARIF on stderr [PR114348]

2024-05-09 Thread David Malcolm
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 
---
 gcc/diagnostic.cc | 24 
 1 file changed, 24 insertions(+)

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 0f093081161..a3d84cf0bfa 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -2175,6 +2175,9 @@ internal_error_no_backtrace (const char *gmsgid, ...)
   gcc_unreachable ();
 }
 
+
+static enum diagnostics_output_format output_format;
+
 /* Special case error functions.  Most are implemented in terms of the
above, or should be.  */
 
@@ -2183,6 +2186,25 @@ internal_error_no_backtrace (const char *gmsgid, ...)
 void
 fnotice (FILE *file, const char *cmsgid, ...)
 {
+  /* If the user requested one of the machine-readable diagnostic output
+ formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then
+ emitting free-form text on stderr will lead to corrupt output.
+ Skip the message for such cases.  */
+  if (file == stderr && global_dc)
+switch (output_format)
+  {
+  default:
+   gcc_unreachable ();
+  case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
+  case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
+  case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
+   break;
+  case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
+  case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
+   /* stderr is meant to machine-readable; skip.  */
+   return;
+  }
+
   va_list ap;
 
   va_start (ap, cmsgid);
@@ -2290,6 +2312,8 @@ diagnostic_output_format_init (diagnostic_context 
*context,
   const char *base_file_name,
   enum diagnostics_output_format format)
 {
+  output_format = format;
+
   switch (format)
 {
 default:
-- 
2.26.3



[PATCH 19/21] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700]

2024-05-09 Thread David Malcolm
Backported from r14-4474-g94caa6a6b4bd73.

gcc/ChangeLog:
PR driver/111700
* input.cc (file_cache::add_file): Update leading comment to
clarify that it can fail.
(file_cache::lookup_or_add_file): Likewise.
(get_source_file_content): Gracefully handle lookup_or_add_file
failing.

gcc/testsuite/ChangeLog:
PR driver/111700
* c-c++-common/diagnostic-format-sarif-file-pr111700.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/input.cc | 12 ++--
 .../diagnostic-format-sarif-file-pr111700.c  | 12 
 2 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c

diff --git a/gcc/input.cc b/gcc/input.cc
index eaf301ec7c1..d1668ef5dcd 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -443,7 +443,10 @@ file_cache::evicted_cache_tab_entry (unsigned 
*highest_use_count)
accessed by caret diagnostic.  This cache is added to an array of
cache and can be retrieved by lookup_file_in_cache_tab.  This
function returns the created cache.  Note that only the last
-   num_file_slots files are cached.  */
+   num_file_slots files are cached.
+
+   This can return nullptr if the FILE_PATH can't be opened for
+   reading, or if the content can't be converted to the input_charset.  */
 
 file_cache_slot*
 file_cache::add_file (const char *file_path)
@@ -547,7 +550,10 @@ file_cache::~file_cache ()
 /* Lookup the cache used for the content of a given file accessed by
caret diagnostic.  If no cached file was found, create a new cache
for this file, add it to the array of cached file and return
-   it.  */
+   it.
+
+   This can return nullptr on a cache miss if FILE_PATH can't be opened for
+   reading, or if the content can't be converted to the input_charset.  */
 
 file_cache_slot*
 file_cache::lookup_or_add_file (const char *file_path)
@@ -1071,6 +1077,8 @@ get_source_file_content (const char *file_path)
   diagnostic_file_cache_init ();
 
   file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
+  if (c == nullptr)
+return char_span (nullptr, 0);
   return c->get_full_file_content ();
 }
 
diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c 
b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
new file mode 100644
index 000..06605accf6e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-format=sarif-file" } */
+
+# 0 "this-file-does-not-exist.c"
+#warning message
+
+/* Verify that some JSON was written to a file with the expected name.  */
+/* { dg-final { verify-sarif-file } } */
+
+/* ...and that it at least includes the warning
+   { dg-final { scan-sarif-file "\"message\": " } }
+ { dg-final { scan-sarif-file "\"text\": \"#warning message" } } */
-- 
2.26.3



[PATCH 13/21] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969]

2024-05-09 Thread David Malcolm
Confusion in binding_cluster::maybe_get_compound_binding about whether
offsets are relative to the start of the region or to the start of the
cluster was leading to incorrect handling of default values, leading
to false positives from -Wanalyzer-use-of-uninitialized-value, from
-Wanalyzer-exposure-through-uninit-copy, and other logic errors.

Fixed thusly.

Backported from commit r14-8428-g6426d466779fa8 (keeping tests
in gcc.dg, rather than c-c++-common).

gcc/analyzer/ChangeLog:
PR analyzer/112969
* store.cc (binding_cluster::maybe_get_compound_binding): When
populating default_map, express the bit-range of the default key
for REG relative to REG, rather than to the base region.

gcc/testsuite/ChangeLog:
PR analyzer/112969
* gcc.dg/analyzer/compound-assignment-5.c (test_3): Remove
xfails, reorder tests.
* gcc.dg/analyzer/compound-assignment-pr112969.c: New test.
* gcc.dg/plugin/infoleak-pr112969.c: New test.
* gcc.dg/plugin/plugin.exp: Add infoleak-pr112969.c to
analyzer_kernel_plugin.c tests.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/store.cc | 11 +++-
 .../gcc.dg/analyzer/compound-assignment-5.c   | 29 ---
 .../analyzer/compound-assignment-pr112969.c   | 35 +
 .../gcc.dg/plugin/infoleak-pr112969.c | 52 +++
 gcc/testsuite/gcc.dg/plugin/plugin.exp|  1 +
 5 files changed, 109 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c

diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e8c927b9fe9..0acb0a2b186 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1718,7 +1718,16 @@ binding_cluster::maybe_get_compound_binding 
(store_manager *mgr,
   else
 default_sval = sval_mgr->get_or_create_initial_value (reg);
   const binding_key *default_key = binding_key::make (mgr, reg);
-  default_map.put (default_key, default_sval);
+
+  /* Express the bit-range of the default key for REG relative to REG,
+ rather than to the base region.  */
+  const concrete_binding *concrete_default_key
+= default_key->dyn_cast_concrete_binding ();
+  if (!concrete_default_key)
+return nullptr;
+  const concrete_binding *default_key_relative_to_reg
+ = mgr->get_concrete_binding (0, concrete_default_key->get_size_in_bits 
());
+  default_map.put (default_key_relative_to_reg, default_sval);
 
   for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter)
 {
diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c 
b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
index ccf8fe392bf..e1f42177b08 100644
--- a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
@@ -23,7 +23,7 @@ void test_1 (void)
 
 /* Copying from an on-stack array to a global array.  */
 
-struct coord glob_arr[16];
+struct coord glob_arr2[16];
 
 void test_2 (void)
 {
@@ -31,32 +31,29 @@ void test_2 (void)
   arr[3].x = 5;
   arr[3].y = 6;
 
-  glob_arr[7] = arr[3];
+  glob_arr2[7] = arr[3];
 
-  __analyzer_eval (glob_arr[7].x == 5); /* { dg-warning "TRUE" } */
-  __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr2[7].x == 5); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr2[7].y == 6); /* { dg-warning "TRUE" } */
 }
 
 /* Copying from a partially initialized on-stack array to a global array.  */
 
-struct coord glob_arr[16];
+struct coord glob_arr3[16];
 
 void test_3 (void)
 {
   struct coord arr[16];
   arr[3].y = 6;
 
-  glob_arr[7] = arr[3]; // or should the uninit warning be here?
+  glob_arr3[7] = arr[3]; // or should the uninit warning be here?
 
-  __analyzer_eval (glob_arr[7].x); /* { dg-warning "uninitialized" "uninit" { 
xfail *-*-* } } */
-  /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */
-  __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr3[7].y == 6); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr3[7].x); /* { dg-warning "uninitialized" "uninit" } 
*/
 }
 
 /* Symbolic bindings: copying from one array to another.  */
 
-struct coord glob_arr[16];
-
 void test_4 (int i)
 {
   struct coord arr_a[16];
@@ -77,8 +74,6 @@ void test_4 (int i)
 
 /* Symbolic bindings: copying within an array: symbolic src and dest  */
 
-struct coord glob_arr[16];
-
 void test_5a (int i, int j)
 {
   struct coord arr[16];
@@ -95,8 +90,6 @@ void test_5a (int i, int j)
 
 /* Symbolic bindings: copying within an array: symbolic src, concrete dest.  */
 
-struct coord glob_arr[16];
-
 void test_5b (int i)
 {
   struct coord arr[16];
@@ -113,8 +106,6 @@ void test_5b (int i)
 
 /* Symbolic bindings: co

[PATCH 10/21] analyzer: fix ICE for 2 bits before the start of base region [PR112889]

2024-05-09 Thread David Malcolm
Cncrete bindings were using -1 and -2 in the offset field to signify
deleted and empty hash slots, but these are valid values, leading to
assertion failures inside hash_map::put on a debug build, and probable
bugs in a release build.

(gdb) call k.dump(true)
start: -2, size: 1, next: -1

(gdb) p k.is_empty()
$6 = true

Fix by using the size field rather than the offset.

Backported from commit r14-6297-g775aeabcb870b7 (moving the testcase
from c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
PR analyzer/112889
* store.h (concrete_binding::concrete_binding): Strengthen
assertion to require size to be be positive, rather than just
non-zero.
(concrete_binding::mark_deleted): Use size rather than start bit
offset.
(concrete_binding::mark_empty): Likewise.
(concrete_binding::is_deleted): Likewise.
(concrete_binding::is_empty): Likewise.

gcc/testsuite/ChangeLog:
PR analyzer/112889
* gcc.dg/analyzer/ice-pr112889.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/store.h | 10 +-
 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c | 17 +
 2 files changed, 22 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c

diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 7ded650b608..6b06be29d8f 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -368,7 +368,7 @@ public:
   concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
   : m_bit_range (start_bit_offset, size_in_bits)
   {
-gcc_assert (!m_bit_range.empty_p ());
+gcc_assert (m_bit_range.m_size_in_bits > 0);
   }
   bool concrete_p () const final override { return true; }
 
@@ -409,10 +409,10 @@ public:
 
   static int cmp_ptr_ptr (const void *, const void *);
 
-  void mark_deleted () { m_bit_range.m_start_bit_offset = -1; }
-  void mark_empty () { m_bit_range.m_start_bit_offset = -2; }
-  bool is_deleted () const { return m_bit_range.m_start_bit_offset == -1; }
-  bool is_empty () const { return m_bit_range.m_start_bit_offset == -2; }
+  void mark_deleted () { m_bit_range.m_size_in_bits = -1; }
+  void mark_empty () { m_bit_range.m_size_in_bits = -2; }
+  bool is_deleted () const { return m_bit_range.m_size_in_bits == -1; }
+  bool is_empty () const { return m_bit_range.m_size_in_bits == -2; }
 
 private:
   bit_range m_bit_range;
diff --git a/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c 
b/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c
new file mode 100644
index 000..e90a53e79ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c
@@ -0,0 +1,17 @@
+typedef unsigned char __u8;
+struct sk_buff
+{
+  unsigned char *data;
+};
+struct cpl_pass_accept_req
+{
+  __u8 : 6;
+  __u8 sack : 1;
+};
+void build_cpl_pass_accept_req(struct sk_buff* skb)
+{
+  struct cpl_pass_accept_req* req;
+  skb->data -= sizeof(*req);
+  req = (struct cpl_pass_accept_req *)skb->data;
+  req->sack = 1;
+}
-- 
2.26.3



[PATCH 15/21] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289]

2024-05-09 Thread David Malcolm
Backported from commit r14-9076-g5651ad62b08096 (moving new tests from
c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
PR analyzer/111289
* varargs.cc (representable_in_integral_type_p): New.
(va_arg_compatible_types_p): Add "arg_sval" param.  Handle integer
types.
(kf_va_arg::impl_call_pre): Pass arg_sval to
va_arg_compatible_types_p.

gcc/testsuite/ChangeLog:
PR analyzer/111289
* gcc.dg/analyzer/stdarg-pr111289-int.c: New test.
* gcc.dg/analyzer/stdarg-pr111289-ptr.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/varargs.cc   | 38 --
 .../gcc.dg/analyzer/stdarg-pr111289-int.c | 69 +++
 .../gcc.dg/analyzer/stdarg-pr111289-ptr.c | 39 +++
 3 files changed, 142 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c

diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index aeea73a3899..6e13271969a 100644
--- a/gcc/analyzer/varargs.cc
+++ b/gcc/analyzer/varargs.cc
@@ -961,13 +961,43 @@ public:
   }
 };
 
-/* Return true if it's OK to copy a value from ARG_TYPE to LHS_TYPE via
+static bool
+representable_in_integral_type_p (const svalue , const_tree type)
+{
+  gcc_assert (INTEGRAL_TYPE_P (type));
+
+  if (tree cst = sval.maybe_get_constant ())
+return wi::fits_to_tree_p (wi::to_wide (cst), type);
+
+  return true;
+}
+
+/* Return true if it's OK to copy ARG_SVAL from ARG_TYPE to LHS_TYPE via
va_arg (where argument promotion has already happened).  */
 
 static bool
-va_arg_compatible_types_p (tree lhs_type, tree arg_type)
+va_arg_compatible_types_p (tree lhs_type, tree arg_type, const svalue 
_sval)
 {
-  return compat_types_p (arg_type, lhs_type);
+  if (compat_types_p (arg_type, lhs_type))
+return true;
+
+  /* It's OK if both types are integer types, where one is signed and the
+ other type the corresponding unsigned type, when the value is
+ representable in both types.  */
+  if (INTEGRAL_TYPE_P (lhs_type)
+  && INTEGRAL_TYPE_P (arg_type)
+  && TYPE_UNSIGNED (lhs_type) != TYPE_UNSIGNED (arg_type)
+  && TYPE_PRECISION (lhs_type) == TYPE_PRECISION (arg_type)
+  && representable_in_integral_type_p (arg_sval, lhs_type)
+  && representable_in_integral_type_p (arg_sval, arg_type))
+return true;
+
+  /* It's OK if one type is a pointer to void and the other is a
+ pointer to a character type.
+ This is handled by compat_types_p.  */
+
+  /* Otherwise the types are not compatible.  */
+  return false;
 }
 
 /* If AP_SVAL is a pointer to a var_arg_region, return that var_arg_region.
@@ -1031,7 +1061,7 @@ kf_va_arg::impl_call_pre (const call_details ) const
{
  tree lhs_type = cd.get_lhs_type ();
  tree arg_type = arg_sval->get_type ();
- if (va_arg_compatible_types_p (lhs_type, arg_type))
+ if (va_arg_compatible_types_p (lhs_type, arg_type, *arg_sval))
cd.maybe_set_lhs (arg_sval);
  else
{
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c 
b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
new file mode 100644
index 000..33d83169c3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
@@ -0,0 +1,69 @@
+#include 
+#include 
+#include 
+
+typedef unsigned int mode_t;
+
+extern void openat (int, const char *, int, mode_t);
+
+/* Signed vs unsigned of same integral type.  */
+
+static void
+test_1 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  mode_t mode = va_arg (arg, mode_t); /* { dg-bogus 
"-Wanalyzer-va-arg-type-mismatch" } */
+
+  va_end (arg);
+  openat (-42, name, 0, mode);
+}
+
+void
+call_test_1 ()
+{
+  test_1 ("nonexist.ent/", 0600);
+}
+
+/* Not the same size: small enough for int promotion.  */
+
+int16_t global_2;
+
+static void
+test_2 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  global_2 = va_arg (arg, int16_t); /* { dg-warning "promoted to 'int'" } */
+
+  va_end (arg);
+}
+
+void
+call_test_2 ()
+{
+  test_2 ("nonexist.ent/", 42);
+}
+
+/* Not the same size: too big for int promotion.  */
+
+long long global_3;
+
+static void
+test_3 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  global_3 = va_arg (arg, long long); /* { dg-warning "'va_arg' expected 'long 
long int' but received 'int' for variadic argument 1 of 'arg'" } */
+
+  va_end (arg);
+}
+
+void
+call_test_3 ()
+{
+  test_3 ("nonexist.ent/", 42);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c 
b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c
new file mode 100644
index 000..7bdbf256d59
--- /dev/null
+++ b/gcc/test

[PATCH 18/21] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408]

2024-05-09 Thread David Malcolm
Backported from commit r14-9646-g80a0cb37456c49 (moving testcase to gcc.dg
and handling conflict in kf.cc)

gcc/analyzer/ChangeLog:
PR analyzer/114408
* engine.cc (impl_run_checkers): Free up any dominance info that
we may have created.
* kf.cc (class kf_ubsan_handler): New.
(register_sanitizer_builtins): New.
(register_known_functions): Call register_sanitizer_builtins.

gcc/testsuite/ChangeLog:
PR analyzer/114408
* gcc.dg/analyzer/deref-before-check-pr114408.c: New test.
* c-c++-common/ubsan/analyzer-ice-pr114408.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/engine.cc|  7 ++
 gcc/analyzer/kf.cc| 22 +++
 .../ubsan/analyzer-ice-pr114408.c |  9 
 .../analyzer/deref-before-check-pr114408.c| 22 +++
 4 files changed, 60 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index a5965c2b8ff..c5aadc41d11 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -6163,6 +6163,13 @@ impl_run_checkers (logger *logger)
 eng.get_model_manager ()->dump_untracked_regions ();
 
   delete purge_map;
+
+  /* Free up any dominance info that we may have created.  */
+  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+{
+  function *fun = node->get_fun ();
+  free_dominance_info (fun, CDI_DOMINATORS);
+}
 }
 
 /* Handle -fdump-analyzer and -fdump-analyzer-stderr.  */
diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index 93c46630f36..4389ff917b8 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -987,6 +987,27 @@ region_model::impl_deallocation_call (const call_details 
)
   kf.impl_call_post (cd);
 }
 
+/* Handle calls to the various __builtin___ubsan_handle_*.
+   These can return, but continuing after such a return
+   isn't likely to be interesting to the user of the analyzer.
+   Hence we terminate the analysis path at one of these calls.  */
+
+class kf_ubsan_handler : public internal_known_function
+{
+  void impl_call_post (const call_details ) const final override
+  {
+if (cd.get_ctxt ())
+  cd.get_ctxt ()->terminate_path ();
+  }
+};
+
+static void
+register_sanitizer_builtins (known_function_manager )
+{
+  kfm.add (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG,
+  make_unique ());
+}
+
 /* Populate KFM with instances of known functions supported by the core of the
analyzer (as opposed to plugins).  */
 
@@ -1028,6 +1049,7 @@ register_known_functions (known_function_manager )
 kfm.add (BUILT_IN_STRNDUP, make_unique ());
 kfm.add (BUILT_IN_STRLEN, make_unique ());
 
+register_sanitizer_builtins (kfm);
 register_varargs_builtins (kfm);
   }
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c 
b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
new file mode 100644
index 000..55f918726ee
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-require-effective-target analyzer } */
+/* { dg-options "-fanalyzer -fsanitize=undefined" } */
+
+int main(){}
+
+int HMAP_unset_copy(const char *key) {
+return __builtin_strcmp("a", key) + __builtin_strcmp("a", key);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c 
b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c
new file mode 100644
index 000..d55720271d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c
@@ -0,0 +1,22 @@
+extern void unknown_returns (const char *p);
+extern void unknown_noreturn (const char *p) __attribute__((__noreturn__));
+
+void test_1 (const char *p)
+{
+  if (p)
+unknown_returns (p);
+  __builtin_strcmp ("a", p); /* { dg-message "pointer 'p' is dereferenced 
here" "" { target c } } */
+  if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing 
it" "" { target c } } */
+unknown_returns (p);
+  __builtin_strcmp ("a", p);  
+}
+
+void test_2 (const char *p)
+{
+  if (p)
+unknown_noreturn (p);
+  __builtin_strcmp ("a", p);
+  if (p) /* { dg-bogus "check of 'p' for NULL after already dereferencing it" 
} */
+unknown_noreturn (p);
+  __builtin_strcmp ("a", p);  
+}
-- 
2.26.3



[PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014]

2024-05-09 Thread David Malcolm
From: Tim Lange 

This patch adds the reproducers reported in PR 110014 as test cases. The
false positives in those cases are already fixed with PR 109577.

2023-06-09  Tim Lange  

PR analyzer/110014

gcc/testsuite/ChangeLog:

* gcc.dg/analyzer/realloc-pr110014.c: New tests.

(cherry picked from commit r14-1685-g39adc5eebd61fd276f3f1ef9d7228756a35bd0cb)

Signed-off-by: David Malcolm 
---
 .../gcc.dg/analyzer/realloc-pr110014.c| 25 +++
 1 file changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c 
b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
new file mode 100644
index 000..d76b8781413
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
@@ -0,0 +1,25 @@
+void *realloc (void *, unsigned long)
+  __attribute__((__nothrow__, __leaf__))
+  __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__ (2)));
+
+long *
+slurp (long *buffer, unsigned long file_size)
+{
+  unsigned long cc;
+  if (!__builtin_add_overflow (file_size - file_size % sizeof (long),
+  2 * sizeof (long), ))
+buffer = realloc (buffer, cc);
+  return buffer;
+}
+
+long *
+slurp1 (long *buffer, unsigned long file_size)
+{
+  return realloc (buffer, file_size - file_size % sizeof (long));
+}
+
+long *
+slurp2 (long *buffer, unsigned long file_size)
+{
+  return realloc (buffer, (file_size / sizeof (long)) * sizeof (long));
+}
-- 
2.26.3



[PATCH 11/21] analyzer: fix deref-before-check false positives due to inlining [PR112790]

2024-05-09 Thread David Malcolm
Backported from commit r14-6918-g5743e1899d5964 (moving testcase from
c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
PR analyzer/112790
* checker-event.cc (class inlining_info): Move to...
* inlining-iterator.h (class inlining_info): ...here.
* sm-malloc.cc: Include "analyzer/inlining-iterator.h".
(maybe_complain_about_deref_before_check): Reject stmts that were
inlined from another function.

gcc/testsuite/ChangeLog:
PR analyzer/112790
* gcc.dg/analyzer/deref-before-check-pr112790.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/checker-event.cc | 40 ---
 gcc/analyzer/inlining-iterator.h  | 40 +++
 gcc/analyzer/sm-malloc.cc | 10 +
 .../analyzer/deref-before-check-pr112790.c| 27 +
 4 files changed, 77 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c

diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 3612df7bd1d..3cb2fb9175c 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -106,46 +106,6 @@ event_kind_to_string (enum event_kind ek)
 }
 }
 
-/* A class for fixing up fndecls and stack depths in checker_event, based
-   on inlining records.
-
-   The early inliner runs before the analyzer, which can lead to confusing
-   output.
-
-   Tne base fndecl and depth within a checker_event are from call strings
-   in program_points, which reflect the call strings after inlining.
-   This class lets us offset the depth and fix up the reported fndecl and
-   stack depth to better reflect the user's original code.  */
-
-class inlining_info
-{
-public:
-  inlining_info (location_t loc)
-  {
-inlining_iterator iter (loc);
-m_inner_fndecl = iter.get_fndecl ();
-int num_frames = 0;
-while (!iter.done_p ())
-  {
-   m_outer_fndecl = iter.get_fndecl ();
-   num_frames++;
-   iter.next ();
-  }
-if (num_frames > 1)
-  m_extra_frames = num_frames - 1;
-else
-  m_extra_frames = 0;
-  }
-
-  tree get_inner_fndecl () const { return m_inner_fndecl; }
-  int get_extra_frames () const { return m_extra_frames; }
-
-private:
-  tree m_outer_fndecl;
-  tree m_inner_fndecl;
-  int m_extra_frames;
-};
-
 /* class checker_event : public diagnostic_event.  */
 
 /* checker_event's ctor.  */
diff --git a/gcc/analyzer/inlining-iterator.h b/gcc/analyzer/inlining-iterator.h
index 7d4798ce6ea..76ba1dc3cf4 100644
--- a/gcc/analyzer/inlining-iterator.h
+++ b/gcc/analyzer/inlining-iterator.h
@@ -106,4 +106,44 @@ private:
   tree m_next_abstract_origin;
 };
 
+/* A class for fixing up fndecls and stack depths in checker_event, based
+   on inlining records.
+
+   The early inliner runs before the analyzer, which can lead to confusing
+   output.
+
+   Tne base fndecl and depth within a checker_event are from call strings
+   in program_points, which reflect the call strings after inlining.
+   This class lets us offset the depth and fix up the reported fndecl and
+   stack depth to better reflect the user's original code.  */
+
+class inlining_info
+{
+public:
+  inlining_info (location_t loc)
+  {
+inlining_iterator iter (loc);
+m_inner_fndecl = iter.get_fndecl ();
+int num_frames = 0;
+while (!iter.done_p ())
+  {
+   m_outer_fndecl = iter.get_fndecl ();
+   num_frames++;
+   iter.next ();
+  }
+if (num_frames > 1)
+  m_extra_frames = num_frames - 1;
+else
+  m_extra_frames = 0;
+  }
+
+  tree get_inner_fndecl () const { return m_inner_fndecl; }
+  int get_extra_frames () const { return m_extra_frames; }
+
+private:
+  tree m_outer_fndecl;
+  tree m_inner_fndecl;
+  int m_extra_frames;
+};
+
 #endif /* GCC_ANALYZER_INLINING_ITERATOR_H */
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 74701375409..64295cfb66e 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/program-state.h"
 #include "analyzer/checker-event.h"
 #include "analyzer/exploded-graph.h"
+#include "analyzer/inlining-iterator.h"
 
 #if ENABLE_ANALYZER
 
@@ -2147,6 +2148,15 @@ maybe_complain_about_deref_before_check (sm_context 
*sm_ctxt,
   if (checked_in_frame->get_index () > assumed_nonnull_in_frame->get_index ())
 return;
 
+  /* Don't complain if STMT was inlined from another function, to avoid
+ similar false positives involving shared helper functions.  */
+  if (stmt->location)
+{
+  inlining_info info (stmt->location);
+  if (info.get_extra_frames () > 0)
+   return;
+}
+
   tree diag_ptr = sm_ctxt->get_diagnostic_tree (ptr);
   if (diag_ptr)
 sm_ctxt->warn
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr11279

[PATCH 20/21] Fix ICE in -fdiagnostics-generate-patch [PR112684]

2024-05-09 Thread David Malcolm
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 
---
 gcc/toplev.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 109c9d58cbd..19391208eac 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_show_color (global_dc->printer);
   global_dc->edit_context_ptr->print_diff (, true);
-- 
2.26.3



[PATCH 16/21] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251]

2024-05-09 Thread David Malcolm
Backported from commit r14-9586-g9093f275e0a343 (moving tests from
c-c++-common to gcc.dg)

gcc/analyzer/ChangeLog:
PR analyzer/109251
* sm-malloc.cc (deref_before_check::emit): Reject cases where the
check is in a loop header within a macro expansion.
(deref_before_check::loop_header_p): New.

gcc/testsuite/ChangeLog:
PR analyzer/109251
* gcc.dg/analyzer/deref-before-check-pr109251-1.c: New test.
* gcc.dg/analyzer/deref-before-check-pr109251-2.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-malloc.cc | 30 ++
 .../analyzer/deref-before-check-pr109251-1.c  | 60 +++
 .../analyzer/deref-before-check-pr109251-2.c  | 37 
 3 files changed, 127 insertions(+)
 create mode 100644 
gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
 create mode 100644 
gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 64295cfb66e..e9384a14dea 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -1565,6 +1565,21 @@ public:
 if (linemap_location_from_macro_definition_p (line_table, check_loc))
   return false;
 
+/* Reject warning if the check is in a loop header within a
+   macro expansion.  This rejects cases like:
+   |  deref of x;
+   |  [...snip...]
+   |  FOR_EACH(x) {
+   |[...snip...]
+   |  }
+   where the FOR_EACH macro tests for non-nullness of x, since
+   the user is hoping to encapsulate the details of iteration
+   in the macro, and the extra check on the first iteration
+   would just be noise if we reported it.  */
+if (loop_header_p (m_check_enode->get_point ())
+   && linemap_location_from_macro_expansion_p (line_table, check_loc))
+  return false;
+
 /* Reject if m_deref_expr is sufficiently different from m_arg
for cases where the dereference is spelled differently from
the check, which is probably two different ways to get the
@@ -1621,6 +1636,21 @@ public:
   }
 
 private:
+  static bool loop_header_p (const program_point )
+  {
+const supernode *snode = point.get_supernode ();
+if (!snode)
+  return false;
+for (auto _edge : snode->m_preds)
+  {
+   if (const cfg_superedge *cfg_in_edge
+ = in_edge->dyn_cast_cfg_superedge ())
+ if (cfg_in_edge->back_edge_p ())
+   return true;
+  }
+return false;
+  }
+
   static bool sufficiently_similar_p (tree expr_a, tree expr_b)
   {
 pretty_printer *pp_a = global_dc->printer->clone ();
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c 
b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
new file mode 100644
index 000..769cffae6d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
@@ -0,0 +1,60 @@
+/* Reduced from linux-5.10.162's kernel/sched/fair.c,
+   with !CONFIG_FAIR_GROUP_SCHED.  */
+
+#define NULL ((void*)0)
+
+struct load_weight
+{
+  unsigned long weight;
+  /* [...snip...] */
+};
+
+struct sched_entity
+{
+  struct load_weight load;
+  /* [...snip...] */
+  unsigned int on_rq;
+  /* [...snip...] */
+};
+
+struct cfs_rq
+{
+  /* [...snip...] */
+  unsigned int nr_running;
+  /* [...snip...] */
+};
+
+extern int
+__calc_delta(int delta_exec, unsigned long weight /* [...snip...] */);
+
+/* !CONFIG_FAIR_GROUP_SCHED */
+#define for_each_sched_entity(se) \
+  for (; se; se = (struct sched_entity *)NULL)
+
+extern struct cfs_rq*
+cfs_rq_of(struct sched_entity* se);
+
+extern int
+__sched_period(unsigned long nr_running);
+
+int
+sched_slice(struct cfs_rq* cfs_rq, struct sched_entity* se)
+{
+  unsigned int nr_running = cfs_rq->nr_running;
+  int slice;
+
+  /* [...snip...] */
+
+  slice = __sched_period(nr_running + !se->on_rq);
+
+  for_each_sched_entity(se) {
+/* [...snip...] */
+cfs_rq = cfs_rq_of(se);
+/* [...snip...] */
+slice = __calc_delta(slice, se->load.weight);
+  }
+
+  /* [...snip...] */
+
+  return slice;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c 
b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c
new file mode 100644
index 000..8e85a47d315
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c
@@ -0,0 +1,37 @@
+struct node
+{
+  struct node *next;
+  int val;
+};
+
+int test_loop_1 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+return -1;
+  for (struct node *iter = n; iter; iter=iter->next)
+total += iter->val;
+  return total;
+}
+
+int test_loop_2 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+return -1;
+  for (; n; n=n->next)
+total += n->val;
+  return total;
+}
+
+#define FOR_EACH_NODE(ITER) for (; (ITER); (ITER)=(ITER)->next)
+
+int test_loop_3 (struct node *n)
+{
+  int total = 0;

[PATCH 09/21] jit: dump string literal initializers correctly

2024-05-09 Thread David Malcolm
From: Vibhav Pant 

Signed-off-by: David Malcolm 

gcc/jit/ChangeLog:
* jit-recording.cc (recording::global::write_to_dump): Fix
dump of string literal initializers.

(cherry picked from commit r14-4923-gac66744d94226a)

Signed-off-by: David Malcolm 
---
 gcc/jit/jit-recording.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index df0368ff8f7..cf734cf7ef5 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -4919,7 +4919,7 @@ recording::global::write_to_dump (dump )
   else if (m_rvalue_init)
 {
   d.write (" = ");
-  d.write (m_rvalue_init->get_debug_string ());
+  d.write ("%s", m_rvalue_init->get_debug_string ());
   d.write (";\n");
 }
 
-- 
2.26.3



[PATCH 08/21] testsuite, analyzer: add test case [PR108171]

2024-05-09 Thread David Malcolm
The ICE in PR analyzer/108171 appears to be a dup of the recently fixed
PR analyzer/110882 and is likewise fixed by it; adding this test case.

gcc/testsuite/ChangeLog:
PR analyzer/108171
* gcc.dg/analyzer/pr108171.c: New test.

(cherry picked from commit r14-2957-gf80efa49b7a163)

Signed-off-by: David Malcolm 
---
 gcc/testsuite/gcc.dg/analyzer/pr108171.c | 31 
 1 file changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr108171.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/pr108171.c 
b/gcc/testsuite/gcc.dg/analyzer/pr108171.c
new file mode 100644
index 000..5f7b9fd7875
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr108171.c
@@ -0,0 +1,31 @@
+struct nl_context {
+  void *cmd_private;
+};
+
+struct sfeatures_context {
+  int a;
+  int req_mask[0];
+};
+
+int set_sf_req_mask_idx;
+
+extern void fill_legacy_flag();
+
+void
+fill_sfeatures_bitmap(struct nl_context *nlctx) {
+  while (nlctx) {
+fill_legacy_flag();
+struct nl_context __trans_tmp_1 = *nlctx;
+struct sfeatures_context *sfctx = __trans_tmp_1.cmd_private;
+sfctx->req_mask[set_sf_req_mask_idx] |= 1;
+  }
+}
+
+void
+nl_sfeatures() {
+  struct nl_context nlctx;
+  struct sfeatures_context *sfctx;
+  nlctx.cmd_private = 
+  sfctx = 0;
+  fill_sfeatures_bitmap();
+}
-- 
2.26.3



[PATCH 17/21] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]

2024-05-09 Thread David Malcolm
gcc/analyzer/ChangeLog:
PR analyzer/114473
* call-summary.cc
(call_summary_replay::convert_svalue_from_summary): Assert that
the types match.
(call_summary_replay::convert_region_from_summary): Likewise.
(call_summary_replay::convert_region_from_summary_1): Add missing
cast for the deref of RK_SYMBOLIC case.

gcc/testsuite/ChangeLog:
PR analyzer/114473
* gcc.dg/analyzer/call-summaries-pr114473.c: New test.

(cherry picked from commit r14-9697-gfdd59818e2abf6)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/call-summary.cc  | 12 +++
 .../gcc.dg/analyzer/call-summaries-pr114473.c | 31 +++
 2 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a18a1b1b40a..836dcd4318d 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -234,6 +234,11 @@ call_summary_replay::convert_svalue_from_summary (const 
svalue *summary_sval)
 
   const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
 
+  if (caller_sval)
+if (summary_sval->get_type () && caller_sval->get_type ())
+  gcc_assert (types_compatible_p (summary_sval->get_type (),
+ caller_sval->get_type ()));
+
   /* Add to cache.  */
   add_svalue_mapping (summary_sval, caller_sval);
 
@@ -551,6 +556,11 @@ call_summary_replay::convert_region_from_summary (const 
region *summary_reg)
 
   const region *caller_reg = convert_region_from_summary_1 (summary_reg);
 
+  if (caller_reg)
+if (summary_reg->get_type () && caller_reg->get_type ())
+  gcc_assert (types_compatible_p (summary_reg->get_type (),
+ caller_reg->get_type ()));
+
   /* Add to cache.  */
   add_region_mapping (summary_reg, caller_reg);
 
@@ -601,6 +611,8 @@ call_summary_replay::convert_region_from_summary_1 (const 
region *summary_reg)
  = get_caller_model ()->deref_rvalue (caller_ptr_sval,
   NULL_TREE,
   get_ctxt ());
+   caller_reg = mgr->get_cast_region (caller_reg,
+  summary_reg->get_type ());
return caller_reg;
   }
   break;
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c 
b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
new file mode 100644
index 000..4598840f0df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
@@ -0,0 +1,31 @@
+/* { dg-additional-options "-fanalyzer-call-summaries" } */
+
+int a;
+extern int *q[];
+
+int *
+baz (int *src)
+{
+  while (a)
+{
+  src && a;
+  return src;
+}
+}
+
+void
+bar (int **src)
+{
+  for (unsigned j = 0; j;)
+a = 0;
+  while (a)
+baz (src[0]);
+}
+
+void
+foo (void)
+{
+  bar (q);
+  baz ();
+  bar (q);
+}
-- 
2.26.3



[PATCH 14/21] analyzer: fix skipping of debug stmts [PR113253]

2024-05-09 Thread David Malcolm
PR analyzer/113253 reports a case where the analyzer output varied
with and without -g enabled.

The root cause was that debug stmts were in the
FOR_EACH_IMM_USE_FAST list for SSA names, leading to the analyzer's
state purging logic differing between the -g and non-debugging cases,
and thus leading to differences in the exploration of the user's code.

Fix by skipping such stmts in the state-purging logic, and removing
debug stmts when constructing the supergraph.

gcc/analyzer/ChangeLog:
PR analyzer/113253
* region-model.cc (region_model::on_stmt_pre): Add gcc_unreachable
for debug statements.
* state-purge.cc
(state_purge_per_ssa_name::state_purge_per_ssa_name): Skip any
debug stmts in the FOR_EACH_IMM_USE_FAST list.
* supergraph.cc (supergraph::supergraph): Don't add debug stmts
to the supernodes.

gcc/testsuite/ChangeLog:
PR analyzer/113253
* gcc.dg/analyzer/deref-before-check-pr113253.c: New test.

(cherry picked from commit r14-8670-gcc7aebff74d896)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model.cc  |   5 +
 gcc/analyzer/state-purge.cc   |   9 +
 gcc/analyzer/supergraph.cc|   4 +
 .../analyzer/deref-before-check-pr113253.c| 154 ++
 4 files changed, 172 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c98b09d5322..7e42fcdfd55 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1237,6 +1237,11 @@ region_model::on_stmt_pre (const gimple *stmt,
   /* No-op for now.  */
   break;
 
+case GIMPLE_DEBUG:
+  /* We should have stripped these out when building the supergraph.  */
+  gcc_unreachable ();
+  break;
+
 case GIMPLE_ASSIGN:
   {
const gassign *assign = as_a  (stmt);
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index 3a73146d928..31a207436f0 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -329,6 +329,15 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const 
state_purge_map ,
  map.log ("used by stmt: %s", pp_formatted_text ());
}
 
+ if (is_gimple_debug (use_stmt))
+   {
+ /* We skipped debug stmts when building the supergraph,
+so ignore them now.  */
+ if (map.get_logger ())
+   map.log ("skipping debug stmt");
+ continue;
+   }
+
  const supernode *snode
= map.get_sg ().get_supernode_for_stmt (use_stmt);
 
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index a23ff15ece4..f07d68c60b8 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -182,6 +182,10 @@ supergraph::supergraph (logger *logger)
  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next ())
{
  gimple *stmt = gsi_stmt (gsi);
+ /* Discard debug stmts here, so we don't have to check for
+them anywhere within the analyzer.  */
+ if (is_gimple_debug (stmt))
+   continue;
  node_for_stmts->m_stmts.safe_push (stmt);
  m_stmt_to_node_t.put (stmt, node_for_stmts);
  m_stmt_uids.make_uid_unique (stmt);
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c 
b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c
new file mode 100644
index 000..d9015accd6a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c
@@ -0,0 +1,154 @@
+/* Regression test for PR analyzer/113253 which was showing analyzer
+   differences with and without -g.
+
+   C only: reduced reproducer doesn't easily work with C++.  */
+
+/* { dg-additional-options "-O2 -g" } */
+
+typedef long int ptrdiff_t;
+typedef unsigned long int uintptr_t;
+typedef long int EMACS_INT;
+enum
+{
+  EMACS_INT_WIDTH = 64,
+  VALBITS = EMACS_INT_WIDTH - 3,
+};
+typedef struct Lisp_X* Lisp_Word;
+enum Lisp_Type
+{
+  Lisp_Symbol = 0,
+  Lisp_Vectorlike = 5,
+};
+typedef Lisp_Word Lisp_Object;
+static inline EMACS_INT(XLI)(Lisp_Object o)
+{
+  return ((EMACS_INT)(o));
+}
+static inline void*(XLP)(Lisp_Object o)
+{
+  return ((void*)(o));
+}
+struct Lisp_Symbol
+{};
+typedef uintptr_t Lisp_Word_tag;
+extern struct Lisp_Symbol lispsym[1608];
+union vectorlike_header
+{
+  ptrdiff_t size;
+};
+enum pvec_type
+{
+  PVEC_MARKER,
+};
+enum More_Lisp_Bits
+{
+  PSEUDOVECTOR_SIZE_BITS = 12,
+  PSEUDOVECTOR_REST_BITS = 12,
+  PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
+  PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS
+};
+static inline _Bool
+PSEUDOVECTORP(Lisp_Object a, int code)
+{
+  return (
+union vectorlike_header*)((uintptr_t)XLP((a)) -
+ 

[PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577]

2024-05-09 Thread David Malcolm
From: Tim Lange 

Currently, the analyzer tries to prove that the allocation size is a
multiple of the pointee's type size.  This patch reverses the behavior
to try to prove that the expression is not a multiple of the pointee's
type size.  With this change, each unhandled case should be gracefully
considered as correct.  This fixes the bug reported in PR 109577 by
Paul Eggert.

Regression-tested on Linux x86-64 with -m32 and -m64.

2023-06-09  Tim Lange  

PR analyzer/109577

gcc/analyzer/ChangeLog:

* constraint-manager.cc (class sval_finder): Visitor to find
childs in svalue trees.
(constraint_manager::sval_constrained_p): Add new function to
check whether a sval might be part of an constraint.
* constraint-manager.h: Add sval_constrained_p function.
* region-model.cc (class size_visitor): Reverse behavior to not
emit a warning on not explicitly considered cases.
(region_model::check_region_size):
Adapt to size_visitor changes.

gcc/testsuite/ChangeLog:

* gcc.dg/analyzer/allocation-size-2.c: Change expected output
and add new test case.
* gcc.dg/analyzer/pr109577.c: New test.

(cherry picked from commit r14-1684-g1d57a2232575913ad1085bac0ba5e22b58185179)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/constraint-manager.cc| 131 ++
 gcc/analyzer/constraint-manager.h |   1 +
 gcc/analyzer/region-model.cc  |  80 ---
 .../gcc.dg/analyzer/allocation-size-2.c   |  24 ++--
 gcc/testsuite/gcc.dg/analyzer/pr109577.c  |  16 +++
 5 files changed, 194 insertions(+), 58 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr109577.c

diff --git a/gcc/analyzer/constraint-manager.cc 
b/gcc/analyzer/constraint-manager.cc
index 2c9c435527e..9211366fb7c 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -2218,6 +2218,137 @@ constraint_manager::get_equiv_class_by_svalue (const 
svalue *sval,
   return false;
 }
 
+/* Tries to find a svalue inside another svalue.  */
+
+class sval_finder : public visitor
+{
+public:
+  sval_finder (const svalue *query) : m_query (query), m_found (false)
+  {
+  }
+
+  bool found_query_p ()
+  {
+return m_found;
+  }
+
+  void visit_region_svalue (const region_svalue *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_constant_svalue (const constant_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_unknown_svalue (const unknown_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_poisoned_svalue (const poisoned_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_setjmp_svalue (const setjmp_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_initial_svalue (const initial_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_unaryop_svalue (const unaryop_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_binop_svalue (const binop_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_sub_svalue (const sub_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_repeated_svalue (const repeated_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_bits_within_svalue (const bits_within_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_unmergeable_svalue (const unmergeable_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_placeholder_svalue (const placeholder_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_widening_svalue (const widening_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_compound_svalue (const compound_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_conjured_svalue (const conjured_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_asm_output_svalue (const asm_output_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+  void visit_const_fn_result_svalue (const const_fn_result_svalue  *sval)
+  {
+m_found |= m_query == sval;
+  }
+
+private:
+  const svalue *m_query;
+  bool m_found;
+};
+
+/* Returns true if SVAL is constrained.  */
+
+bool
+constraint_manager::sval_constrained_p (const svalue *sval) const
+{
+  int i;
+  equiv_class *ec;
+  sval_finder finder (sval);
+  FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
+{
+  int j;
+  const svalue *iv;
+  FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
+   {
+ iv->accept ();
+ if (finder.found_query_p ())
+   return true;
+   }
+}
+  return false;
+}
+
 /* Ensure that SVAL has an equivalence class within this constraint_manager;
return the ID of the class.  */
 
diff --git a/gcc/analyzer/constraint-manager.h 
b/gcc/analyzer/constraint-manager.h
index 3afbc7f848e..72753e43c96 100644
--- a/gcc/an

[PATCH 07/21] analyzer: fix ICE on zero-sized arrays [PR110882]

2024-05-09 Thread David Malcolm
gcc/analyzer/ChangeLog:
PR analyzer/110882
* region.cc (int_size_in_bits): Fail on zero-sized types.

gcc/testsuite/ChangeLog:
PR analyzer/110882
* gcc.dg/analyzer/pr110882.c: New test.

(cherry picked from commit r14-2955-gc62f93d1e0383d)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region.cc   |  6 +-
 gcc/testsuite/gcc.dg/analyzer/pr110882.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr110882.c

diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index f982ce67509..c1bfecabd15 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -395,7 +395,11 @@ int_size_in_bits (const_tree type, bit_size_t *out)
 }
 
   tree sz = TYPE_SIZE (type);
-  if (sz && tree_fits_uhwi_p (sz))
+  if (sz
+  && tree_fits_uhwi_p (sz)
+  /* If the size is zero, then we may have a zero-sized
+array; handle such cases by returning false.  */
+  && !integer_zerop (sz))
 {
   *out = TREE_INT_CST_LOW (sz);
   return true;
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr110882.c 
b/gcc/testsuite/gcc.dg/analyzer/pr110882.c
new file mode 100644
index 000..80027184053
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr110882.c
@@ -0,0 +1,18 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
+struct csv_row {
+  char *columns[0];
+};
+
+void
+parse_csv_line (int n_columns, const char *columns[])
+{
+  for (int n = 0; n < n_columns; n++) {
+  columns[n] = ((void *)0);
+  }
+}
+
+void parse_csv_data (int n_columns, struct csv_row *entry)
+{
+  parse_csv_line(n_columns, (const char **)entry->columns);
+}
-- 
2.26.3



[PATCH 05/21] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466]

2024-05-09 Thread David Malcolm
gcc/testsuite/ChangeLog:
PR jit/110466
* jit.dg/jit.exp (jit-check-debug-info): Gracefully handle too
early versions of gdb that don't support our dwarf version, via
"unsupported".

(cherry picked from commit r14-2223-gc3c0ba5436170e)

Signed-off-by: David Malcolm 
---
 gcc/testsuite/jit.dg/jit.exp | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 35d38cec5bc..83fb6371fd2 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -440,6 +440,10 @@ proc jit-check-debug-info { obj_file cmds match } {
 send $cmd
 }
 expect {
+   -re "Dwarf Error: wrong version in compilation unit header" {
+   set testcase [testname-for-summary]
+   unsupported "$testcase: gdb does not support dwarf version"
+   }
 -re $match { pass OK }
 default { fail FAIL }
 }
-- 
2.26.3



[PATCH 12/21] analyzer: casting all zeroes should give all zeroes [PR113333]

2024-05-09 Thread David Malcolm
In particular, accessing the result of *calloc (1, SZ) (if non-NULL)
should be known to be all zeroes.

(backported from commit r14-7265-gd235bf2e807c5f)

gcc/analyzer/ChangeLog:
PR analyzer/11
* region-model-manager.cc
(region_model_manager::maybe_fold_unaryop): Casting all zeroes
should give all zeroes.

gcc/testsuite/ChangeLog:
PR analyzer/11
* gcc.dg/analyzer/calloc-1.c: Add tests.
* gcc.dg/analyzer/data-model-9.c: Update expected results.
* gcc.dg/analyzer/pr96639.c: Update expected results.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model-manager.cc |  6 
 gcc/testsuite/gcc.dg/analyzer/calloc-1.c | 34 
 gcc/testsuite/gcc.dg/analyzer/data-model-9.c |  6 ++--
 gcc/testsuite/gcc.dg/analyzer/pr96639.c  |  2 +-
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index 1a9886fd83c..51a2d8b029f 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -422,6 +422,12 @@ region_model_manager::maybe_fold_unaryop (tree type, enum 
tree_code op,
  && region_sval->get_type ()
  && POINTER_TYPE_P (region_sval->get_type ()))
return get_ptr_svalue (type, region_sval->get_pointee ());
+
+   /* Casting all zeroes should give all zeroes.  */
+   if (type
+   && arg->all_zeroes_p ()
+   && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+ return get_or_create_int_cst (type, 0);
   }
   break;
 case TRUTH_NOT_EXPR:
diff --git a/gcc/testsuite/gcc.dg/analyzer/calloc-1.c 
b/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
index bc28128671f..efb1a24c96a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
@@ -25,3 +25,37 @@ char *test_1 (size_t sz)
 
   return p;
 }
+
+char **
+test_pr11_1 (void)
+{
+  char **p = (char **)calloc (1, sizeof(char *));
+  if (p)
+{
+  __analyzer_eval (*p == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (p[0] == 0); /* { dg-warning "TRUE" } */
+}
+  return p;
+}
+
+char **
+test_pr11_2 (void)
+{
+  char **p = (char **)calloc (2, sizeof(char *));
+  if (p)
+{
+  __analyzer_eval (*p == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (p[0] == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (p[1] == 0); /* { dg-warning "TRUE" } */
+}
+  return p;
+}
+
+char **
+test_pr11_3 (void)
+{
+  char **vec = (char **)calloc (1, sizeof(char *));
+  if (vec)
+for (char **p=vec ; *p ; p++); /* { dg-bogus "heap-based buffer over-read" 
} */
+  return vec;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-9.c 
b/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
index 159bc612576..2121f20c4f0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
@@ -14,8 +14,7 @@ void test_1 (void)
   struct foo *f = calloc (1, sizeof (struct foo));
   if (f == NULL)
 return;
-  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* 
} } */
-  /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
+  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" } */
   free (f);
 }
 
@@ -27,7 +26,6 @@ void test_2 (void)
   if (f == NULL)
 return;
   memset (f, 0, sizeof (struct foo));
-  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* 
} } */
-  /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
+  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" } */
   free (f);
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96639.c 
b/gcc/testsuite/gcc.dg/analyzer/pr96639.c
index aedf0464dc9..c06a5c02f79 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr96639.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96639.c
@@ -6,5 +6,5 @@ x7 (void)
   int **md = calloc (1, sizeof (void *));
 
   return md[0][0]; /* { dg-warning "possibly-NULL" "unchecked deref" } */
-  /* { dg-warning "leak of 'md'" "leak" { target *-*-* } .-1 } */
+  /* { dg-warning "Wanalyzer-null-dereference" "deref of NULL" { target *-*-* 
} .-1 } */
 }
-- 
2.26.3



[PATCH 06/21] analyzer: fix ICE on division of tainted floating-point values [PR110700]

2024-05-09 Thread David Malcolm
gcc/analyzer/ChangeLog:
PR analyzer/110700
* region-model-manager.cc
(region_model_manager::get_or_create_int_cst): Assert that we have
an integral or pointer type.
* sm-taint.cc (taint_state_machine::check_for_tainted_divisor):
Don't check non-integral types.

gcc/testsuite/ChangeLog:
PR analyzer/110700
* gcc.dg/analyzer/taint-divisor-2.c: New test.

(cherry picked from commit r14-2658-gb86c0fe327a519)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model-manager.cc|  3 ++-
 gcc/analyzer/sm-taint.cc|  6 ++
 gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c | 13 +
 3 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c

diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index fab5bba15d5..1a9886fd83c 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -233,7 +233,8 @@ const svalue *
 region_model_manager::get_or_create_int_cst (tree type, poly_int64 val)
 {
   gcc_assert (type);
-  tree tree_cst = build_int_cst (type, val);
+  gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
+  tree tree_cst = wide_int_to_tree (type, val);
   return get_or_create_constant_svalue (tree_cst);
 }
 
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index f72f194460c..7bce3ef79b2 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1344,6 +1344,12 @@ taint_state_machine::check_for_tainted_divisor 
(sm_context *sm_ctxt,
 return;
 
   tree divisor_expr = gimple_assign_rhs2 (assign);;
+
+  /* Until we track conditions on floating point values, we can't check to
+ see if they've been checked against zero.  */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (divisor_expr)))
+return;
+
   const svalue *divisor_sval = old_model->get_rvalue (divisor_expr, NULL);
 
   state_t state = sm_ctxt->get_state (assign, divisor_sval);
diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c 
b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c
new file mode 100644
index 000..de9a1cb3a46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c
@@ -0,0 +1,13 @@
+// TODO: remove need for this option:
+/* { dg-additional-options "-fanalyzer-checker=taint" } */
+
+#include "analyzer-decls.h"
+
+__attribute__ ((tainted_args))
+double pr110700 (double x, double y)
+{
+  /* Ideally we'd complain here with -Wanalyzer-tainted-divisor, but
+ until we track conditions on floating point values, we can't check to
+ see if they've been checked against zero.  */
+  return x / y;
+}
-- 
2.26.3



[PATCH 04/21] jit: avoid using __vector in testcase [PR110466]

2024-05-09 Thread David Malcolm
r13-4531-gd2e782cb99c311 added test coverage to libgccjit's vector
support, but used __vector, which doesn't work on Power.  Additionally
the size param to gcc_jit_type_get_vector was wrong.

Fixed thusly.

gcc/testsuite/ChangeLog:
PR jit/110466
* jit.dg/test-expressions.c (run_test_of_comparison): Fix size
param to gcc_jit_type_get_vector.
(verify_comparisons): Use a typedef rather than __vector.

(cherry picked from commit r14--g6735d660839533)

Co-authored-by: Marek Polacek 
Signed-off-by: David Malcolm 
---
 gcc/testsuite/jit.dg/test-expressions.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/testsuite/jit.dg/test-expressions.c 
b/gcc/testsuite/jit.dg/test-expressions.c
index 13b3baf79ea..2337b01907e 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -417,7 +417,7 @@ static void run_test_of_comparison(gcc_jit_context *ctxt,
 const char *expected)
 {
   gcc_jit_type *vec_type =
-gcc_jit_type_get_vector (type, 4);
+gcc_jit_type_get_vector (type, 2);
 
   CHECK_STRING_VALUE (
 make_test_of_comparison (ctxt,
@@ -560,17 +560,17 @@ verify_comparisons (gcc_jit_result *result)
   CHECK_VALUE (test_COMPARISON_GE_on_int (1, 2), 0);
   CHECK_VALUE (test_COMPARISON_GE_on_int (2, 1), 1);
 
-  typedef int __vector __attribute__ ((__vector_size__ (sizeof(int) * 2)));
-  typedef __vector (*test_vec_fn) (__vector, __vector);
+  typedef int v2si __attribute__ ((__vector_size__ (sizeof(int) * 2)));
+  typedef v2si (*test_vec_fn) (v2si, v2si);
 
-  __vector zero_zero = {0, 0};
-  __vector zero_one = {0, 1};
-  __vector one_zero = {1, 0};
+  v2si zero_zero = {0, 0};
+  v2si zero_one = {0, 1};
+  v2si one_zero = {1, 0};
 
-  __vector true_true = {-1, -1};
-  __vector false_true = {0, -1};
-  __vector true_false = {-1, 0};
-  __vector false_false = {0, 0};
+  v2si true_true = {-1, -1};
+  v2si false_true = {0, -1};
+  v2si true_false = {-1, 0};
+  v2si false_false = {0, 0};
 
   test_vec_fn test_COMPARISON_EQ_on_vec_int =
 (test_vec_fn)gcc_jit_result_get_code (result,
@@ -615,7 +615,7 @@ verify_comparisons (gcc_jit_result *result)
   CHECK_VECTOR_VALUE (2, test_COMPARISON_GE_on_vec_int (zero_one, one_zero), 
false_true);
 
   typedef float __vector_f __attribute__ ((__vector_size__ (sizeof(float) * 
2)));
-  typedef __vector (*test_vec_f_fn) (__vector_f, __vector_f);
+  typedef v2si (*test_vec_f_fn) (__vector_f, __vector_f);
 
   __vector_f zero_zero_f = {0, 0};
   __vector_f zero_one_f = {0, 1};
-- 
2.26.3



[pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics)

2024-05-09 Thread David Malcolm
/gcc-patches/2024-January/643386.html
* (cherry picked from commit r14-8255-ge254d1224df306)
  gcc 13: r13-8760-g2a6f99aef7c852

* [pushed] diagnostics: fix corrupt json/SARIF on stderr [PR114348]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648048.html
* (backported from commit r14-9554-g0bf99b1b7eda2f)
  gcc 13: r13-8761-gb7a2697733d19a


David Malcolm (18):
  analyzer: add caching to globals with initializers [PR110112]
  jit: avoid using __vector in testcase [PR110466]
  jit.exp: handle dwarf version mismatch in jit-check-debug-info
[PR110466]
  analyzer: fix ICE on division of tainted floating-point values
[PR110700]
  analyzer: fix ICE on zero-sized arrays [PR110882]
  testsuite, analyzer: add test case [PR108171]
  analyzer: fix ICE for 2 bits before the start of base region
[PR112889]
  analyzer: fix deref-before-check false positives due to inlining
[PR112790]
  analyzer: casting all zeroes should give all zeroes [PR11]
  analyzer: fix defaults in compound assignments from non-zero offsets
[PR112969]
  analyzer: fix skipping of debug stmts [PR113253]
  analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types
[PR111289]
  analyzer: fix -Wanalyzer-deref-before-check false positive seen in
loop header macro [PR109251]
  analyzer: fix ICE due to type mismatch when replaying call summary
[PR114473]
  analyzer: fix ICE and false positive with
-Wanalyzer-deref-before-check [PR114408]
  diagnostics: fix ICE on sarif output when source file is unreadable
[PR111700]
  Fix ICE in -fdiagnostics-generate-patch [PR112684]
  diagnostics: fix corrupt json/SARIF on stderr [PR114348]

Tim Lange (2):
  analyzer: Fix allocation size false positive on conjured svalue
[PR109577]
  testsuite: Add more allocation size tests for conjured svalues
[PR110014]

Vibhav Pant (1):
  jit: dump string literal initializers correctly

 gcc/analyzer/call-summary.cc  |  12 ++
 gcc/analyzer/checker-event.cc |  40 -
 gcc/analyzer/constraint-manager.cc| 131 +++
 gcc/analyzer/constraint-manager.h |   1 +
 gcc/analyzer/engine.cc|   7 +
 gcc/analyzer/inlining-iterator.h  |  40 +
 gcc/analyzer/kf.cc|  22 +++
 gcc/analyzer/region-model-manager.cc  |   9 +-
 gcc/analyzer/region-model.cc  | 110 -
 gcc/analyzer/region.cc|  77 -
 gcc/analyzer/region.h |  14 +-
 gcc/analyzer/sm-malloc.cc |  40 +
 gcc/analyzer/sm-taint.cc  |   6 +
 gcc/analyzer/state-purge.cc   |   9 +
 gcc/analyzer/store.cc |  11 +-
 gcc/analyzer/store.h  |  10 +-
 gcc/analyzer/supergraph.cc|   4 +
 gcc/analyzer/varargs.cc   |  38 -
 gcc/diagnostic.cc |  24 +++
 gcc/input.cc  |  12 +-
 gcc/jit/jit-recording.cc  |   2 +-
 .../diagnostic-format-sarif-file-pr111700.c   |  12 ++
 .../ubsan/analyzer-ice-pr114408.c |   9 +
 .../gcc.dg/analyzer/allocation-size-2.c   |  24 ++-
 .../gcc.dg/analyzer/call-summaries-pr114473.c |  31 
 gcc/testsuite/gcc.dg/analyzer/calloc-1.c  |  34 
 .../gcc.dg/analyzer/compound-assignment-5.c   |  29 ++--
 .../analyzer/compound-assignment-pr112969.c   |  35 
 gcc/testsuite/gcc.dg/analyzer/data-model-9.c  |   6 +-
 .../analyzer/deref-before-check-pr109251-1.c  |  60 +++
 .../analyzer/deref-before-check-pr109251-2.c  |  37 +
 .../analyzer/deref-before-check-pr112790.c|  27 +++
 .../analyzer/deref-before-check-pr113253.c| 154 ++
 .../analyzer/deref-before-check-pr114408.c|  22 +++
 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c  |  17 ++
 gcc/testsuite/gcc.dg/analyzer/pr108171.c  |  31 
 gcc/testsuite/gcc.dg/analyzer/pr109577.c  |  16 ++
 gcc/testsuite/gcc.dg/analyzer/pr110882.c  |  18 ++
 gcc/testsuite/gcc.dg/analyzer/pr96639.c   |   2 +-
 .../gcc.dg/analyzer/realloc-pr110014.c|  25 +++
 .../gcc.dg/analyzer/stdarg-pr111289-int.c |  69 
 .../gcc.dg/analyzer/stdarg-pr111289-ptr.c |  39 +
 .../gcc.dg/analyzer/taint-divisor-2.c |  13 ++
 .../gcc.dg/plugin/infoleak-pr112969.c |  52 ++
 gcc/testsuite/gcc.dg/plugin/plugin.exp|   1 +
 gcc/testsuite/jit.dg/jit.exp  |   4 +
 gcc/testsuite/jit.dg/test-expressions.c   |  22 +--
 gcc/toplev.cc |   4 +-
 48 files changed, 1231 insertions(+), 181 deletions(-)
 create mode 100644 
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
 cr

[PATCH 01/21] analyzer: add caching to globals with initializers [PR110112]

2024-05-09 Thread David Malcolm
PR analyzer/110112 notes that -fanalyzer is extremely slow on a source
file with large read-only static arrays, repeatedly building the
same compound_svalue representing the full initializer, and repeatedly
building svalues representing parts of the the full initialiazer.

This patch adds caches for both of these; together they reduce the time
taken by -fanalyzer -O2 on the testcase in the bug for an optimized
build:
  91.2s : no caches (status quo)
  32.4s : cache in decl_region::get_svalue_for_constructor
   3.7s : cache in region::get_initial_value_at_main
   3.1s : both caches (this patch)

gcc/analyzer/ChangeLog:
PR analyzer/110112
* region-model.cc (region_model::get_initial_value_for_global):
Move code to region::calc_initial_value_at_main.
* region.cc (region::get_initial_value_at_main): New function.
(region::calc_initial_value_at_main): New function, based on code
in region_model::get_initial_value_for_global.
(region::region): Initialize m_cached_init_sval_at_main.
(decl_region::get_svalue_for_constructor): Add a cache, splitting
out body to...
(decl_region::calc_svalue_for_constructor): ...this new function.
* region.h (region::get_initial_value_at_main): New decl.
(region::calc_initial_value_at_main): New decl.
(region::m_cached_init_sval_at_main): New field.
(decl_region::decl_region): Initialize m_ctor_svalue.
(decl_region::calc_svalue_for_constructor): New decl.
(decl_region::m_ctor_svalue): New field.

(cherry picked from commit r14-1664-gfe9771b59f576f)

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model.cc | 25 +
 gcc/analyzer/region.cc   | 71 +---
 gcc/analyzer/region.h| 14 ++-
 3 files changed, 79 insertions(+), 31 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index fb81d43f91b..18996c5e5e8 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2355,30 +2355,7 @@ region_model::get_initial_value_for_global (const region 
*reg) const
  the initial value of REG can be taken from the initialization value
  of the decl.  */
   if (called_from_main_p () || TREE_READONLY (decl))
-{
-  /* Attempt to get the initializer value for base_reg.  */
-  if (const svalue *base_reg_init
-   = base_reg->get_svalue_for_initializer (m_mgr))
-   {
- if (reg == base_reg)
-   return base_reg_init;
- else
-   {
- /* Get the value for REG within base_reg_init.  */
- binding_cluster c (base_reg);
- c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init);
- const svalue *sval
-   = c.get_any_binding (m_mgr->get_store_manager (), reg);
- if (sval)
-   {
- if (reg->get_type ())
-   sval = m_mgr->get_or_create_cast (reg->get_type (),
- sval);
- return sval;
-   }
-   }
-   }
-}
+return reg->get_initial_value_at_main (m_mgr);
 
   /* Otherwise, return INIT_VAL(REG).  */
   return m_mgr->get_or_create_initial_value (reg);
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index a18bfa50d09..f982ce67509 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -272,6 +272,51 @@ region::can_have_initial_svalue_p () const
 }
 }
 
+/* For regions within a global decl, get the svalue for the initial
+   value of this region when the program starts, caching the result.  */
+
+const svalue *
+region::get_initial_value_at_main (region_model_manager *mgr) const
+{
+  if (!m_cached_init_sval_at_main)
+m_cached_init_sval_at_main = calc_initial_value_at_main (mgr);
+  return m_cached_init_sval_at_main;
+}
+
+/* Implementation of region::get_initial_value_at_main.  */
+
+const svalue *
+region::calc_initial_value_at_main (region_model_manager *mgr) const
+{
+  const decl_region *base_reg = get_base_region ()->dyn_cast_decl_region ();
+  gcc_assert (base_reg);
+
+  /* Attempt to get the initializer value for base_reg.  */
+  if (const svalue *base_reg_init
+  = base_reg->get_svalue_for_initializer (mgr))
+{
+  if (this == base_reg)
+   return base_reg_init;
+  else
+   {
+ /* Get the value for REG within base_reg_init.  */
+ binding_cluster c (base_reg);
+ c.bind (mgr->get_store_manager (), base_reg, base_reg_init);
+ const svalue *sval
+   = c.get_any_binding (mgr->get_store_manager (), this);
+ if (sval)
+   {
+ if (get_type ())
+   sval = mgr->get_or_create_cast (get_type (), sval);
+ return sval;
+   }
+   }
+}
+
+  /* Otherwise, return INIT_VAL(REG).  */
+  return mgr->get_or_create_ini

[PATCH] testsuite: fix analyzer C++ failures on Solaris [PR111475]

2024-05-03 Thread David Malcolm
   * gcc.dg/analyzer/malloc-ipa-8-unchecked.c: ...here, dropping
attempt to generalize output for C vs C++.
* c-c++-common/analyzer/signal-4a.c: Move back to...
* gcc.dg/analyzer/signal-4a.c: ...here, dropping attempt to
generalize output for C vs C++.
* c-c++-common/analyzer/signal-4b.c: Move back to...
* gcc.dg/analyzer/signal-4b.c: ...here, dropping attempt to
generalize output for C vs C++.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/analyzer.cc  | 15 +++--
 gcc/analyzer/analyzer.h   |  4 +-
 gcc/analyzer/engine.cc|  2 +-
 gcc/analyzer/kf.cc| 22 +++
 gcc/analyzer/known-function-manager.cc| 38 ++-
 gcc/analyzer/known-function-manager.h |  5 ++
 gcc/analyzer/sm-file.cc   |  8 +++
 gcc/analyzer/sm-malloc.cc |  1 +
 gcc/analyzer/sm-signal.cc | 11 +++-
 .../analyzer/fd-glibc-byte-stream-socket.c|  4 ++
 .../analyzer/fd-manpage-getaddrinfo-client.c  |  4 ++
 ...rver.c => fd-manpage-getaddrinfo-server.c} |  4 ++
 .../c-c++-common/analyzer/fd-socket-meaning.c |  4 ++
 .../analyzer/fd-symbolic-socket.c |  4 ++
 .../analyzer/flexible-array-member-1.c|  6 +-
 .../c-c++-common/analyzer/pr106539.c  |  2 +-
 .../analyzer/malloc-ipa-8-unchecked.c | 46 ++---
 .../analyzer/signal-4a.c  | 53 ++-
 .../analyzer/signal-4b.c  | 65 ++-
 19 files changed, 134 insertions(+), 164 deletions(-)
 rename gcc/testsuite/c-c++-common/analyzer/{fd-mappage-getaddrinfo-server.c => 
fd-manpage-getaddrinfo-server.c} (96%)
 rename gcc/testsuite/{c-c++-common => 
gcc.dg}/analyzer/malloc-ipa-8-unchecked.c (55%)
 rename gcc/testsuite/{c-c++-common => gcc.dg}/analyzer/signal-4a.c (53%)
 rename gcc/testsuite/{c-c++-common => gcc.dg}/analyzer/signal-4b.c (52%)

diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
index 7f5d3d56d338..2a15a3a9ad79 100644
--- a/gcc/analyzer/analyzer.cc
+++ b/gcc/analyzer/analyzer.cc
@@ -293,11 +293,13 @@ get_ssa_default_def (const function , tree var)
is_named_call_p should be used instead, using a fndecl from
get_fndecl_for_call; this function should only be used for special cases
where it's not practical to get at the region model, or for special
-   analyzer functions such as __analyzer_dump.  */
+   analyzer functions such as __analyzer_dump.
+
+   If LOOK_IN_STD is true, then also look for within std:: for the name.  */
 
 bool
 is_special_named_call_p (const gcall *call, const char *funcname,
-unsigned int num_args)
+unsigned int num_args, bool look_in_std)
 {
   gcc_assert (funcname);
 
@@ -305,7 +307,12 @@ is_special_named_call_p (const gcall *call, const char 
*funcname,
   if (!fndecl)
 return false;
 
-  return is_named_call_p (fndecl, funcname, call, num_args);
+  if (is_named_call_p (fndecl, funcname, call, num_args))
+return true;
+  if (look_in_std)
+if (is_std_named_call_p (fndecl, funcname, call, num_args))
+  return true;
+  return false;
 }
 
 /* Helper function for checkers.  Is FNDECL an extern fndecl at file scope
@@ -344,7 +351,7 @@ is_named_call_p (const_tree fndecl, const char *funcname)
Compare with cp/typeck.cc: decl_in_std_namespace_p, but this doesn't
rely on being the C++ FE (or handle inline namespaces inside of std).  */
 
-static inline bool
+bool
 is_std_function_p (const_tree fndecl)
 {
   tree name_decl = DECL_NAME (fndecl);
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index d43812e39635..334b0d32bd05 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -448,10 +448,12 @@ extern tree remove_ssa_names (tree expr);
 } // namespace ana
 
 extern bool is_special_named_call_p (const gcall *call, const char *funcname,
-unsigned int num_args);
+unsigned int num_args,
+bool look_in_std = false);
 extern bool is_named_call_p (const_tree fndecl, const char *funcname);
 extern bool is_named_call_p (const_tree fndecl, const char *funcname,
 const gcall *call, unsigned int num_args);
+extern bool is_std_function_p (const_tree fndecl);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
 const gcall *call, unsigned int num_args);
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index e0dc0e66e88c..556e8a1c8288 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -3768,7 +3768,7 @@ stmt_requires_new_enode_p (const gimple *stmt,
 regular next state, which defeats the &quo

Re: [PATCH] c++: fix source printing for "required from here" message

2024-04-25 Thread David Malcolm
On Wed, 2024-04-24 at 17:05 -0400, Patrick Palka wrote:
> On Wed, 24 Apr 2024, Jason Merrill wrote:
> 
> > On 4/24/24 13:22, Patrick Palka wrote:
> > > Tested on x86_64-pc-linux-gnu, full bootstrap+regtest in
> > > progress,
> > > does this look OK if successful?
> > > 
> > > -- >8 --
> > > 
> > > It seems the diagnostic machinery's source line printing respects
> > > the pretty printer prefix, but this is undesirable for the call
> > > to
> > > diagnostic_show_locus in print_instantiation_partial_context_line
> > > added in r14-4388-g1c45319b66edc9 since the prefix may have been
> > > set when issuing an earlier, unrelated diagnostic and we just
> > > want
> > > to print an unprefixed source line.
> > > 
> > > This patch naively fixes this by clearing the prefix before
> > > calling
> > > diagnostic_show_locus.
> > > 
> > > Before this patch, for error60a.C below we'd print
> > > 
> > > gcc/testsuite/g++.dg/template/error60a.C: In function ‘void
> > > usage()’:
> > > gcc/testsuite/g++.dg/template/error60a.C:24:3: error:
> > > ‘unrelated_error’ was
> > > not declared in this scope
> > >     24 |   unrelated_error; // { dg-error "not declared" }
> > >    |   ^~~
> > > gcc/testsuite/g++.dg/template/error60a.C: In instantiation of
> > > ‘void
> > > test(Foo) [with Foo = int]’:
> > > gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from
> > > here
> > > gcc/testsuite/g++.dg/template/error60a.C:24:3: error:    25 |  
> > > test
> > > (42); // { dg-message " required from here" }
> > > gcc/testsuite/g++.dg/template/error60a.C:24:3: error:   |
> > > ~~^~~~
> > > gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid
> > > conversion
> > > from ‘int’ to ‘int*’ [-fpermissive]
> > >     19 |   my_pointer ptr (val); // { dg-error "invalid
> > > conversion from
> > > 'int' to 'int\\*'" }
> > >    |    ^~~
> > >    |    |
> > >    |    int
> > > gcc/testsuite/g++.dg/template/error60a.C:9:20: note:  
> > > initializing argument
> > > 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
> > >  9 |   my_pointer (Foo *ptr) // { dg-message " initializing
> > > argument 1"
> > > }
> > >    |   ~^~~
> > > 
> > > and afterward we print
> > > 
> > > gcc/testsuite/g++.dg/template/error60a.C: In function ‘void
> > > usage()’:
> > > gcc/testsuite/g++.dg/template/error60a.C:24:3: error:
> > > ‘unrelated_error’ was
> > > not declared in this scope
> > >     24 |   unrelated_error; // { dg-error "not declared" }
> > >    |   ^~~
> > > gcc/testsuite/g++.dg/template/error60a.C: In instantiation of
> > > ‘void
> > > test(Foo) [with Foo = int]’:
> > > gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from
> > > here
> > >     25 |   test (42); // { dg-message " required from here"
> > > }
> > >    |   ~~^~~~
> > > gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid
> > > conversion
> > > from ‘int’ to ‘int*’ [-fpermissive]
> > >     19 |   my_pointer ptr (val); // { dg-error "invalid
> > > conversion from
> > > 'int' to 'int\\*'" }
> > >    |    ^~~
> > >    |    |
> > >    |    int
> > > gcc/testsuite/g++.dg/template/error60a.C:9:20: note:  
> > > initializing argument
> > > 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
> > >  9 |   my_pointer (Foo *ptr) // { dg-message " initializing
> > > argument 1"
> > > }
> > >    |   ~^~~
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > > * error.cc (print_instantiation_partial_context_line):
> > > Clear
> > > context->printer->prefix around the call to
> > > diagnostic_show_locus.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > > * g++.dg/concepts/diagnostic2.C: Expect source line
> > > printed
> > > for the required from here message.
> > > * g++.dg/template/error60a.C: New test.
> > > ---
> > >   gcc/cp/error.cc |  2 +
> > >   gcc/testsuite/g++.dg/concepts/diagnostic2.C |  6 ++-
> > >   gcc/testsuite/g++.dg/template/error60a.C    | 46
> > > +
> > >   3 files changed, 53 insertions(+), 1 deletion(-)
> > >   create mode 100644 gcc/testsuite/g++.dg/template/error60a.C
> > > 
> > > diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
> > > index 7074845154e..a7067d4d2ed 100644
> > > --- a/gcc/cp/error.cc
> > > +++ b/gcc/cp/error.cc
> > > @@ -3793,7 +3793,9 @@ print_instantiation_partial_context_line
> > > (diagnostic_context *context,
> > >    : _("required from here\n"));
> > >   }
> > >     gcc_rich_location rich_loc (loc);
> > > +  char *saved_prefix = pp_take_prefix (context->printer);
> > >     diagnostic_show_locus (context, _loc, DK_NOTE);
> > > +  context->printer->prefix = saved_prefix;
> > 
> > I would follow the pattern of c_diagnostic_finalizer here, i.e.
> > using
> > pp_set_prefix for the restore.
> 
> 

Re: [PATCH] v2: DOCUMENTATION_ROOT_URL vs. release branches [PR114738]

2024-04-24 Thread David Malcolm
On Wed, 2024-04-24 at 11:07 +0200, Jakub Jelinek wrote:
> On Tue, Apr 23, 2024 at 07:07:17PM -0400, David Malcolm wrote:
> > That sounds like a better approach; thanks.
> 
> Attached below.  Tested by checking
> ../configure --disable-bootstrap --enable-languages=c --disable-
> multilib
> built trunk on
> void
> foo (int x)
> {
>   __builtin_printf ("%ld\n", x);
> }
> testcase and looking for the URL in there, then repeating that after
> changing gcc/BASE-VER to 14.1.0 and again after changing it to 14.1.1
> 
> > > Still, what do you think we should do on the release branches
> > > (recommend to
> > > developers and check with the post-commit CI)?
> > 
> > My hope is that the URL suffixes don't change: we shouldn't be
> > adding
> > new command-line options on the release branches, and I'd hope that
> > texinfo doesn't change the generated anchors from run to run.
> 
> Unfortunately that is not the case.  *.opt files change all the time
> on release branches.  Sure, not all the changes in there would cause
> *.urls changes, but many of them would.
> E.g. looking at 13 branch,
> r13-7022 r13-7130 r13-7169 r13-7276 r13-7336 r13-7415 r13-7518 r13-
> 7528
> r13-7650 r13-7651 r13-7728 r13-7794 r13-8039 r13-8040 r13-8223 r13-
> 8350
> r13-8351 r13-8357 r13-8419 r13-8545
> commits changed the *.opt files.

Thanks.

I looked through the commits you mentioned above.  For reference, the
following subset are the ones that added new options:

r13-7130 added -mamx-complex to i386
r13-7336 added -minline-atomics to riscv
r13-7415(*) added -Wextra and -Wmismatched-special-enum to D
r13-7518(*) added -fexceptions to D
r13-7528 added -fconstant-cfstrings to Darwin
r13-7650 added -Wuninit-variable-checking to Modula 2
r13-7651 added -Wuninit-variable-checking=all,known,cond to Modula 2
r13-7728 added -mgather and -mscatter to i386
r13-7794 added -Wcase-enum to Modula 2
r13-8039 added --param=uninit-max-chain-len= and --param=uninit-max-
num-chains=
r13-8350(*) added -mrelax to loongarch
r13-8351 added -mpass-mrelax-to-as to loongarch

Of the above, I've marked with a (*) those new options that share the
name with an existing option: -Wextra, -fexceptions in D (shared with C
family and Fortan), and -mrelax in loongarch (shared with various other
targets).  These are the ones that are likely to change URL suffixes,
due to texinfo's html generator using a counter internally to make
these be unique.

So yes, these changes are likely to invalidate a few existing URLs. 
Bother.

> 
> > > No regeneration of *.urls except before doing a new release
> > > candidate,
> > > or a different make goal that would grab html files from the web
> > > and
> > > regenerate against that?
> > 
> > That sounds overcomplicated. 
> > 
> > If the anchors do change, it's fairly trivial to run "make
> > regenerate-
> > opt-urls" locally, isn't it?
> 
> I think the primary question is, do we want the *.urls checking CI
> on the release branches as well or only on the trunk?
> Given the xz backdoor, I think checking release branches for the
> regeneration hiccups (primarily for configure, Makefile etc.) is
> desirable.

That's a fair point.

I suppose there's also the case where a downstream adds their own
command-line options (consider e.g. an out-of-tree frontend or target),
but they can just regenerate things themselves (or set up their own
CI).

> And with the patch posted here (or with what I've committed a week
> ago)
> on the release branches the default root will be initially identical
> but
> after some commits starts diverging.  If we can live with some URLs
> being
> stale or misplaced until next release in the default case (if people
> provide
> their own root it will be always accurate), we don't need to do
> anything
> further (except perhaps enable the autoregen CI on 14 branch).

The failure due to not regenerating the .opt.urls is that the final
"fragment" part of the URL (the anchor) will be slighly wrong, but the
page will be correct.  I think we can live with that.

The other possible failure is if the page is wrong: that the 
https://gcc.gnu.org/onlinedocs/gcc-MAJOR.MINOR.0/ doesn't exist. 
Presumably that is created on our server when the branch happens, so
there's only going to be a very short window between updating git and
the website being live.  If that's the case, then I think we can live
with that as well.

So I think this patch is good, and that we want the CI on the release
branches as well as on trunk.

Thanks
Dave



> 
> 2024-04-24  Jakub Jelinek  
> 
> PR other/114738
> * opts.cc (get_option_url): Revert 2024-04-17 changes.
> * gcc-urlifier.cc: Don't include diagnostic-core.h.
&

Re: [PATCH] DOCUMENTATION_ROOT_URL vs. release branches [PR114738]

2024-04-23 Thread David Malcolm
On Tue, 2024-04-23 at 17:45 +0200, Jakub Jelinek wrote:
> On Tue, Apr 23, 2024 at 11:40:55AM -0400, David Malcolm wrote:
> > > So, I think at least for the MAJOR.MINOR.0 releases we want to
> > > use
> > > URLs like above rather than the trunk ones and we can use the
> > > same
> > > process
> > > of updating *.opt.urls as well for that.
> > 
> > Would it make sense to instead update the default value in
> > gcc/configure.ac for DOCUMENTATION_ROOT_URL when branching or
> > releasing, from https://gcc.gnu.org/onlinedocs/ to
> > https://gcc.gnu.org/onlinedocs/gcc-MAJOR-MINOR.0/
> > 
> > ?
> > 
> > Before this patch the DOCUMENTATION_ROOT_URL expresses the location
> > of
> > a built texinfo html tree of docs, and the url suffixes express the
> > path within that tree.
> > 
> > As the patch is written, if a distributor overrides --with-
> > documentation-root-url= at configure time, then they need to mirror
> > the
> > structure of our website on their website, which seems like a
> > burden.
> 
> Sure, that is doable (of course, it shouldn't be done by updating
> gcc/configure.ac but by adjusting the default in there based on
> gcc_version,
> I'll post a patch tomorrow).

That sounds like a better approach; thanks.

> 
> Still, what do you think we should do on the release branches
> (recommend to
> developers and check with the post-commit CI)?

My hope is that the URL suffixes don't change: we shouldn't be adding
new command-line options on the release branches, and I'd hope that
texinfo doesn't change the generated anchors from run to run.

> No regeneration of *.urls except before doing a new release
> candidate,
> or a different make goal that would grab html files from the web and
> regenerate against that?

That sounds overcomplicated. 

If the anchors do change, it's fairly trivial to run "make regenerate-
opt-urls" locally, isn't it?

As mentioned above, I like the idea of having the
DOCUMENTATION_ROOT_URL express the location of a tree of docs built
with texinfo, and for the url suffixes to be relative to that.  We can
update the default in gcc/configure.ac for released branches, and drop
the logic from your previous patch.  So if a distributor wants to
upload their docs for a particular version to their own location,
they're responsible for providing a suitable value for  --with-
documentation-root-url= at configure time.

Or am I missing something here?

Dave



Re: [PATCH] DOCUMENTATION_ROOT_URL vs. release branches [PR114738]

2024-04-23 Thread David Malcolm
On Wed, 2024-04-17 at 13:16 +0200, Jakub Jelinek wrote:
> Hi!
> 
> Starting with GCC 14 we have the nice URLification of the options
> printed
> in diagnostics, say for in
> test.c:4:23: warning: format ‘%d’ expects argument of type ‘int’, but
> argument 2 has type ‘long int’ [-Wformat=]
> the -Wformat= is underlined in some terminals and hovering on it
> shows
> https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat
> link.

That isn't new in GCC 14; we've provided the URLs for the option
guarding a warning since GCC 10, I think.  What's new is that we now
"urlify" any quoted text that mentions an option, and that the option
URLs are now based on the anchors in the generated HTML (and thus more
likely to be correct).

> 
> This works nicely on the GCC trunk, where the online documentation is
> regenerated every day from a cron job and more importantly, people
> rarely
> use the trunk snapshots for too long, so it is unlikely that further
> changes
> in the documentation will make too many links stale, because users
> will
> simply regularly update to newer snapshots.
> 
> I think it doesn't work properly on release branches though.
> Some users only use the relased versions (i.e. MAJOR.MINOR.0) from
> tarballs
> but can use them for a couple of years, others use snapshots from the
> release branches, but again they could be in use for months or years
> and
> the above mentioned online docs which represent just the GCC trunk
> might
> diverge significantly.
> 
> Now, for the relases we always publish also online docs for the
> release,
> which unlike the trunk online docs will not change further, under
> e.g.
> https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/Warning-Options.html#index-Wformat
> or
> https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Warning-Options.html#index-Wformat
> etc.


> 
> So, I think at least for the MAJOR.MINOR.0 releases we want to use
> URLs like above rather than the trunk ones and we can use the same
> process
> of updating *.opt.urls as well for that.

Would it make sense to instead update the default value in
gcc/configure.ac for DOCUMENTATION_ROOT_URL when branching or
releasing, from https://gcc.gnu.org/onlinedocs/ to
https://gcc.gnu.org/onlinedocs/gcc-MAJOR-MINOR.0/

?

Before this patch the DOCUMENTATION_ROOT_URL expresses the location of
a built texinfo html tree of docs, and the url suffixes express the
path within that tree.

As the patch is written, if a distributor overrides --with-
documentation-root-url= at configure time, then they need to mirror the
structure of our website on their website, which seems like a burden.



> 
> For the snapshots from release branches, we don't have such docs.
> One option (implemented in the patch below for the URL printing side)
> is
> point to the MAJOR.MINOR.0 docs even for MAJOR.MINOR.1 snapshots.
> Most of the links will work fine, for options newly added on the
> release
> branches (rare thing but still happens) can have until the next
> release
> no URLs for them and get them with the next point release.
> The question is what to do about make regenerate-opt-urls for the
> release
> branch snapshots.  Either just document that users shouldn't
> make regenerate-opt-urls on release branches (and filter out
> *.opt.urls
> changes from their commits), add make regenerate-opt-urls task be RM
> responsibility before making first release candidate from a branch
> and
> adjust the autoregen CI to know about that.  Or add a separate goal
> which instead of relying on make html created files would download
> copy of the html files from the last release from web (kind of web
> mirroring the https://gcc.gnu.org/onlinedocs/gcc-14.1.0/ subtree
> locally)
> and doing regenerate-opt-urls on top of that?  But how to catch the
> point when first release candidate is made and we want to update to
> what will be the URLs once the release is made (but will be stale
> URLs
> for a week or so)?
> 
> Another option would be to add to cron daily regeneration of the
> online
> docs for the release branches.  I don't think that is a good idea
> though,
> because as I wrote earlier, not all users update to the latest
> snapshot
> frequently, so there can be users that use gcc 13.1.1 20230525 for
> months
> or years, and other users which use gcc 13.1.1 20230615 for years
> etc.
> 
> Another question is what is most sensible for users who want to
> override
> the default root and use the --with-documentation-root-url= configure
> option.  Do we expect them to grab the whole onlinedocs tree or for
> release
> branches at least include gcc-14.1.0/ subdirectory under the root?
> If so, the patch below deals with that.  Or should we just change the
> default documentation root url, so if user doesn't specify
> --with-documentation-root-url= and we are on a release branch,
> default that
> to https://gcc.gnu.org/onlinedocs/gcc-14.1.0/ or
> https://gcc.gnu.org/onlinedocs/gcc-14.2.0/ etc. and don't add any
> infix in
> get_option_url/make_doc_url, 

[pushed] analyzer: add SARIF property bag to -Wanalyzer-infinite-recursion

2024-04-10 Thread David Malcolm
Tested lightly by hand.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9900-g960e07d73a5295.

gcc/analyzer/ChangeLog:
* infinite-recursion.cc: Include "diagnostic-format-sarif.h".
(infinite_recursion_diagnostic::maybe_add_sarif_properties): New.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/infinite-recursion.cc | 13 +
 1 file changed, 13 insertions(+)

diff --git a/gcc/analyzer/infinite-recursion.cc 
b/gcc/analyzer/infinite-recursion.cc
index 112e4bd08f28..65f136ddad6b 100644
--- a/gcc/analyzer/infinite-recursion.cc
+++ b/gcc/analyzer/infinite-recursion.cc
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "make-unique.h"
 #include "analyzer/checker-path.h"
 #include "analyzer/feasible-graph.h"
+#include "diagnostic-format-sarif.h"
 
 /* A subclass of pending_diagnostic for complaining about suspected
infinite recursion.  */
@@ -236,6 +237,18 @@ public:
 return false;
   }
 
+  void maybe_add_sarif_properties (sarif_object _obj)
+const final override
+  {
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/infinite_recursion_diagnostic/"
+props.set_integer (PROPERTY_PREFIX "prev_entry_enode",
+  m_prev_entry_enode->m_index);
+props.set_integer (PROPERTY_PREFIX "new_entry_enode",
+  m_new_entry_enode->m_index);
+#undef PROPERTY_PREFIX
+  }
+
 private:
   /* Return true iff control flow along FEDGE was affected by
  a conjured_svalue.  */
-- 
2.26.3



[pushed] analyzer: fixes to internal docs

2024-04-10 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9897-g7f6599a201be2a.

gcc/ChangeLog:
* doc/analyzer.texi: Various tweaks.

Signed-off-by: David Malcolm 
---
 gcc/doc/analyzer.texi | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/analyzer.texi b/gcc/doc/analyzer.texi
index 8eb40272cb71..b53096e7b7d9 100644
--- a/gcc/doc/analyzer.texi
+++ b/gcc/doc/analyzer.texi
@@ -21,6 +21,9 @@
 
 @subsection Overview
 
+At a high-level, we're doing coverage-guided symbolic execution of the
+user's code.
+
 The analyzer implementation works on the gimple-SSA representation.
 (I chose this in the hopes of making it easy to work with LTO to
 do whole-program analysis).
@@ -55,7 +58,9 @@ Next is the heart of the analyzer: we use a worklist to 
explore state
 within the supergraph, building an "exploded graph".
 Nodes in the exploded graph correspond to  pairs, as in
  "Precise Interprocedural Dataflow Analysis via Graph Reachability"
- (Thomas Reps, Susan Horwitz and Mooly Sagiv).
+ (Thomas Reps, Susan Horwitz and Mooly Sagiv) - but note that
+we're not using the algorithm described in that paper, just the
+``exploded graph'' terminology.
 
 We reuse nodes for  pairs we've already seen, and avoid
 tracking state too closely, so that (hopefully) we rapidly converge
@@ -499,7 +504,8 @@ which dumps a @file{SRC.eg.txt} file containing the full 
@code{exploded_graph}.
 
 Assuming that you have the
 
@uref{https://gcc-newbies-guide.readthedocs.io/en/latest/debugging.html,,python 
support scripts for gdb}
-installed, you can use:
+installed (which you should do, it makes debugging GCC much easier),
+you can use:
 
 @smallexample
 (gdb) break-on-saved-diagnostic
-- 
2.26.3



[pushed] analyzer: fix ICE on negative values for size_t [PR114472]

2024-04-10 Thread David Malcolm
I made several attempts to fix this properly, but for now apply
a band-aid to at least prevent crashing on such cases.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9902-g4a94551d7eaaf7.

gcc/analyzer/ChangeLog:
PR analyzer/114472
* access-diagram.cc (bit_size_expr::maybe_get_formatted_str):
Reject attempts to print sizes that are too large.
* region.cc (region_offset::calc_symbolic_bit_offset): Use a
typeless svalue for the bit offset.
* store.cc (bit_range::intersects_p): Replace assertion with
test.
(bit_range::exceeds_p): Likewise.
(bit_range::falls_short_of_p): Likewise.

gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/out-of-bounds-pr114472.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/access-diagram.cc|  4 
 gcc/analyzer/region.cc|  2 +-
 gcc/analyzer/store.cc | 20 +++
 .../analyzer/out-of-bounds-pr114472.c | 17 
 4 files changed, 38 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr114472.c

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 4cb6570e90b9..873205c46499 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -373,6 +373,8 @@ bit_size_expr::maybe_get_formatted_str 
(text_art::style_manager ,
   if (tree cst = num_bytes->maybe_get_constant ())
{
  byte_size_t concrete_num_bytes = wi::to_offset (cst);
+ if (!wi::fits_uhwi_p (concrete_num_bytes))
+   return nullptr;
  if (concrete_num_bytes == 1)
return ::make_unique 
  (fmt_styled_string (sm, concrete_single_byte_fmt,
@@ -396,6 +398,8 @@ bit_size_expr::maybe_get_formatted_str 
(text_art::style_manager ,
   else if (tree cst = m_num_bits.maybe_get_constant ())
 {
   bit_size_t concrete_num_bits = wi::to_offset (cst);
+  if (!wi::fits_uhwi_p (concrete_num_bits))
+   return nullptr;
   if (concrete_num_bits == 1)
return ::make_unique 
  (fmt_styled_string (sm, concrete_single_bit_fmt,
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index 705816b62454..7d79b45563fd 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -89,7 +89,7 @@ region_offset::calc_symbolic_bit_offset (region_model_manager 
*mgr) const
m_sym_offset, bits_per_byte);
 }
   else
-return *mgr->get_or_create_int_cst (size_type_node, m_offset);
+return *mgr->get_or_create_int_cst (NULL_TREE, m_offset);
 }
 
 const svalue *
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e85a19647f7e..a36de13c1743 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -290,7 +290,10 @@ bit_range::intersects_p (const bit_range ,
   bit_offset_t overlap_next
= MIN (get_next_bit_offset (),
   other.get_next_bit_offset ());
-  gcc_assert (overlap_next > overlap_start);
+  if (overlap_next <= overlap_start)
+   /* If this has happened, some kind of overflow has happened in
+  our arithmetic.  For now, reject such cases.  */
+   return false;
   bit_range abs_overlap_bits (overlap_start, overlap_next - overlap_start);
   *out_this = abs_overlap_bits - get_start_bit_offset ();
   *out_other = abs_overlap_bits - other.get_start_bit_offset ();
@@ -316,7 +319,10 @@ bit_range::intersects_p (const bit_range ,
 other.get_start_bit_offset ());
   bit_offset_t overlap_next = MIN (get_next_bit_offset (),
other.get_next_bit_offset ());
-  gcc_assert (overlap_next > overlap_start);
+  if (overlap_next <= overlap_start)
+   /* If this has happened, some kind of overflow has happened in
+  our arithmetic.  For now, reject such cases.  */
+   return false;
   *out_num_overlap_bits = overlap_next - overlap_start;
   return true;
 }
@@ -339,7 +345,10 @@ bit_range::exceeds_p (const bit_range ,
   bit_offset_t start = MAX (get_start_bit_offset (),
 other.get_next_bit_offset ());
   bit_offset_t size = get_next_bit_offset () - start;
-  gcc_assert (size > 0);
+  if (size <= 0)
+   /* If this has happened, some kind of overflow has happened in
+  our arithmetic.  For now, reject such cases.  */
+   return false;
   out_overhanging_bit_range->m_start_bit_offset = start;
   out_overhanging_bit_range->m_size_in_bits = size;
   return true;
@@ -362,7 +371,10 @@ bit_range::falls_short_of_p (bit_offset_t offset,
   /* THIS falls short of OFFSET.  */
   bit_offset_t start = get_start_bit_offset ();
 

[pushed] analyzer: show size in SARIF property bag for -Wanalyzer-tainted-allocation-size

2024-04-10 Thread David Malcolm
Tested lightly by hand.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9898-g115d5c6b009456.

gcc/analyzer/ChangeLog:
* sm-taint.cc (tainted_allocation_size::tainted_allocation_size):
Add "size_in_bytes" param.
(tainted_allocation_size::maybe_add_sarif_properties): New.
(tainted_allocation_size::m_size_in_bytes): New field.
(region_model::check_dynamic_size_for_taint): Pass size_in_bytes
to tainted_allocation_size ctor.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-taint.cc | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index 1d1e208fdf49..a9c6d4db43f4 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -645,8 +645,10 @@ class tainted_allocation_size : public taint_diagnostic
 {
 public:
   tainted_allocation_size (const taint_state_machine , tree arg,
+  const svalue *size_in_bytes,
   enum bounds has_bounds, enum memory_space mem_space)
   : taint_diagnostic (sm, arg, has_bounds),
+m_size_in_bytes (size_in_bytes),
 m_mem_space (mem_space)
   {
   }
@@ -781,7 +783,18 @@ public:
}
   }
 
+  void maybe_add_sarif_properties (sarif_object _obj)
+const final override
+  {
+taint_diagnostic::maybe_add_sarif_properties (result_obj);
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/tainted_allocation_size/"
+props.set (PROPERTY_PREFIX "size_in_bytes", m_size_in_bytes->to_json ());
+#undef PROPERTY_PREFIX
+  }
+
 private:
+  const svalue *m_size_in_bytes;
   enum memory_space m_mem_space;
 };
 
@@ -1678,7 +1691,7 @@ region_model::check_dynamic_size_for_taint (enum 
memory_space mem_space,
 {
   tree arg = get_representative_tree (size_in_bytes);
   ctxt->warn (make_unique
-   (taint_sm, arg, b, mem_space));
+   (taint_sm, arg, size_in_bytes, b, mem_space));
 }
 }
 
-- 
2.26.3



[pushed] analyzer, testuite: comment fixes

2024-04-10 Thread David Malcolm
Successfully regrtested on x86_64-pc-linux-gnu.

Pushed to trunk as r14-9896-g082374f6570a31.

gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/memset-1.c: Clarify some comments.

Signed-off-by: David Malcolm 
---
 gcc/testsuite/c-c++-common/analyzer/memset-1.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/c-c++-common/analyzer/memset-1.c 
b/gcc/testsuite/c-c++-common/analyzer/memset-1.c
index 75aef53d3487..d6695d494111 100644
--- a/gcc/testsuite/c-c++-common/analyzer/memset-1.c
+++ b/gcc/testsuite/c-c++-common/analyzer/memset-1.c
@@ -58,7 +58,7 @@ void test_5 (int n)
   __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */
   memset (buf, 0, n);
 
-  /* We can't know if buf[42] was written to or not.  */
+  /* We can't know if buf[42] was overwritten by the memset or not.  */
   __analyzer_eval (buf[42] == 'A'); /* { dg-warning "UNKNOWN" } */
   __analyzer_eval (buf[42] == '\0'); /* { dg-warning "UNKNOWN" } */
 }
@@ -72,7 +72,7 @@ void test_5a (int n)
   __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */
   __builtin___memset_chk (buf, 0, n, __builtin_object_size (buf, 0));
 
-  /* We can't know if buf[42] was written to or not.  */
+  /* We can't know if buf[42] was overwritten by the memset or not.  */
   __analyzer_eval (buf[42] == 'A'); /* { dg-warning "UNKNOWN" } */
   __analyzer_eval (buf[42] == '\0'); /* { dg-warning "UNKNOWN" } */
 }
-- 
2.26.3



[pushed] testsuite: add some missing -fanalyzer to plugin tests

2024-04-10 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9895-gd09d70cdb2a4bc.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/copy_from_user-1.c: Add missing directives for an
analyzer test.
* gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c: Add missing
-fanalyzer to options.
* gcc.dg/plugin/taint-CVE-2011-0521-1.c: Likewise.
* gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c: Likewise.
(dvb_usercopy): Add default case to avoid complaints about NULL
derefs.
* gcc.dg/plugin/taint-CVE-2011-0521-2.c: Likewise.
* gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c: Add missing
-fanalyzer to options.
* gcc.dg/plugin/taint-CVE-2011-0521-3.c: Likewise.  Drop
xfail.

Signed-off-by: David Malcolm 
---
 gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c| 4 
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c | 2 +-
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1.c   | 2 +-
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c | 4 +++-
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2.c   | 4 +++-
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c | 2 +-
 gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3.c   | 5 ++---
 7 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c 
b/gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c
index a1415f38aa65..1acedc2e2ce8 100644
--- a/gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c
@@ -1,3 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
 typedef __SIZE_TYPE__ size_t;
 
 #define __user
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c 
b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c
index 51526b831c02..9ad05ff670a2 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-require-effective-target analyzer } */
-/* { dg-additional-options "-Wno-pedantic" } */
+/* { dg-additional-options "-fanalyzer -Wno-pedantic" } */
 
 /* See notes in this header.  */
 #include "taint-CVE-2011-0521.h"
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1.c 
b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1.c
index 3d11a75073c1..688d014956ec 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-additional-options "-Wno-pedantic" } */
+/* { dg-additional-options "-fanalyzer -Wno-pedantic" } */
 /* { dg-require-effective-target analyzer } */
 
 /* See notes in this header.  */
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c 
b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c
index d035266b16ad..7e597037ec24 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-additional-options "-Wno-pedantic" } */
+/* { dg-additional-options "-fanalyzer -Wno-pedantic" } */
 /* { dg-require-effective-target analyzer } */
 
 /* See notes in this header.  */
@@ -67,6 +67,8 @@ int dvb_usercopy(struct file *file,
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
break;
+   default:
+   goto out;
}
 
/* call driver */
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2.c 
b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2.c
index 5270e22f1a32..9189cdb2c37c 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-2.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-require-effective-target analyzer } */
-/* { dg-additional-options "-Wno-pedantic" } */
+/* { dg-additional-options "-fanalyzer -Wno-pedantic" } */
 
 /* See notes in this header.  */
 #include "taint-CVE-2011-0521.h"
@@ -67,6 +67,8 @@ int dvb_usercopy(struct file *file,
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
break;
+   default:
+   goto out;
}
 
/* call driver */
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c 
b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c
index b8268fa4a826..d10ce28b40e2 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-r

[pushed] analyzer: add SARIF property bag to -Wanalyzer-infinite-loop

2024-04-10 Thread David Malcolm
Tested lightly by hand.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9901-g107b0e63be023c.

gcc/analyzer/ChangeLog:
* infinite-loop.cc: Include "diagnostic-format-sarif.h".
(infinite_loop::to_json): New.
(infinite_loop_diagnostic::maybe_add_sarif_properties): New.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/infinite-loop.cc | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc
index 296489b1146d..e277a8384a04 100644
--- a/gcc/analyzer/infinite-loop.cc
+++ b/gcc/analyzer/infinite-loop.cc
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/checker-path.h"
 #include "analyzer/feasible-graph.h"
 #include "make-unique.h"
+#include "diagnostic-format-sarif.h"
 
 /* A bundle of data characterizing a particular infinite loop
identified within the exploded graph.  */
@@ -105,6 +106,18 @@ struct infinite_loop
&& m_loc == other.m_loc);
   }
 
+  json::object *
+  to_json () const
+  {
+json::object *loop_obj = new json::object ();
+loop_obj->set_integer ("enode", m_enode.m_index);
+json::array *edge_arr = new json::array ();
+for (auto eedge : m_eedge_vec)
+  edge_arr->append (eedge->to_json ());
+loop_obj->set ("eedges", edge_arr);
+return loop_obj;
+  }
+
   const exploded_node _enode;
   location_t m_loc;
   std::vector m_eedge_vec;
@@ -297,6 +310,15 @@ public:
   }
   }
 
+  void maybe_add_sarif_properties (sarif_object _obj)
+const final override
+  {
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/infinite_loop_diagnostic/"
+props.set (PROPERTY_PREFIX "inf_loop", m_inf_loop->to_json ());
+#undef PROPERTY_PREFIX
+  }
+
 private:
   std::unique_ptr m_inf_loop;
 };
-- 
2.26.3



[pushed] analyzer: add SARIF property bags to -Wanalyzer-overlapping-buffers

2024-04-10 Thread David Malcolm
Tested lightly by hand.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9899-g7a49d5dc0ef345.

gcc/analyzer/ChangeLog:
* call-details.cc: Include "diagnostic-format-sarif.h".
(overlapping_buffers::overlapping_buffers): Add params for new
fields.
(overlapping_buffers::maybe_add_sarif_properties): New.
(overlapping_buffers::m_byte_range_a): New field.
(overlapping_buffers::byte_range_b): New field.
(overlapping_buffers::m_num_bytes_read_sval): New field.
(call_details::complain_about_overlap): Pass new params to
overlapping_buffers ctor.
* ranges.cc (symbolic_byte_offset::to_json): New.
(symbolic_byte_range::to_json): New.
* ranges.h (symbolic_byte_offset::to_json): New decl.
(symbolic_byte_range::to_json): New decl.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/call-details.cc | 33 ++---
 gcc/analyzer/ranges.cc   | 15 +++
 gcc/analyzer/ranges.h|  4 
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc
index 5b145a2ce638..ca47953f1461 100644
--- a/gcc/analyzer/call-details.cc
+++ b/gcc/analyzer/call-details.cc
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "make-unique.h"
+#include "diagnostic-format-sarif.h"
 
 #if ENABLE_ANALYZER
 
@@ -425,8 +426,14 @@ class overlapping_buffers
 : public pending_diagnostic_subclass
 {
 public:
-  overlapping_buffers (tree fndecl)
-  : m_fndecl (fndecl)
+  overlapping_buffers (tree fndecl,
+  const symbolic_byte_range _range_a,
+  const symbolic_byte_range _range_b,
+  const svalue *num_bytes_read_sval)
+  : m_fndecl (fndecl),
+m_byte_range_a (byte_range_a),
+m_byte_range_b (byte_range_b),
+m_num_bytes_read_sval (num_bytes_read_sval)
   {
   }
 
@@ -469,8 +476,25 @@ public:
m_fndecl);
   }
 
+  void maybe_add_sarif_properties (sarif_object _obj)
+const final override
+  {
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/overlapping_buffers/"
+props.set (PROPERTY_PREFIX "bytes_range_a",
+  m_byte_range_a.to_json ());
+props.set (PROPERTY_PREFIX "bytes_range_b",
+  m_byte_range_b.to_json ());
+props.set (PROPERTY_PREFIX "num_bytes_read_sval",
+  m_num_bytes_read_sval->to_json ());
+#undef PROPERTY_PREFIX
+  }
+
 private:
   tree m_fndecl;
+  symbolic_byte_range m_byte_range_a;
+  symbolic_byte_range m_byte_range_b;
+  const svalue *m_num_bytes_read_sval;
 };
 
 
@@ -517,7 +541,10 @@ call_details::complain_about_overlap (unsigned arg_idx_a,
   if (!byte_range_a.intersection (byte_range_b, *model).is_true ())
 return;
 
-  ctxt->warn (make_unique (get_fndecl_for_call ()));
+  ctxt->warn (make_unique (get_fndecl_for_call (),
+   byte_range_a,
+   byte_range_b,
+   num_bytes_read_sval));
 }
 
 } // namespace ana
diff --git a/gcc/analyzer/ranges.cc b/gcc/analyzer/ranges.cc
index ffdd0d4c5722..659ada7609d6 100644
--- a/gcc/analyzer/ranges.cc
+++ b/gcc/analyzer/ranges.cc
@@ -103,6 +103,12 @@ symbolic_byte_offset::dump (bool simple) const
   pp_flush ();
 }
 
+json::value *
+symbolic_byte_offset::to_json () const
+{
+  return m_num_bytes_sval->to_json ();
+}
+
 tree
 symbolic_byte_offset::maybe_get_constant () const
 {
@@ -156,6 +162,15 @@ symbolic_byte_range::dump (bool simple, 
region_model_manager ) const
   pp_flush ();
 }
 
+json::value *
+symbolic_byte_range::to_json () const
+{
+  json::object *obj = new json::object ();
+  obj->set ("start", m_start.to_json ());
+  obj->set ("size", m_size.to_json ());
+  return obj;
+}
+
 bool
 symbolic_byte_range::empty_p () const
 {
diff --git a/gcc/analyzer/ranges.h b/gcc/analyzer/ranges.h
index 92d963b7a2bc..aca4554bde69 100644
--- a/gcc/analyzer/ranges.h
+++ b/gcc/analyzer/ranges.h
@@ -39,6 +39,8 @@ public:
   void dump_to_pp (pretty_printer *pp, bool) const;
   void dump (bool) const;
 
+  json::value *to_json () const;
+
   bool operator== (const symbolic_byte_offset ) const
   {
return m_num_bytes_sval == other.m_num_bytes_sval;
@@ -70,6 +72,8 @@ public:
   region_model_manager ) const;
   void dump (bool, region_model_manager ) const;
 
+  json::value *to_json () const;
+
   bool empty_p () const;
 
   symbolic_byte_offset get_start_byte_offset () const
-- 
2.26.3



[pushed] analyzer: respect GCC_COLORS in out-of-bounds diagrams [PR114588]

2024-04-05 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9817-g4b02dd48f531ea.

gcc/analyzer/ChangeLog:
PR analyzer/114588
* access-diagram.cc (access_diagram_impl::access_diagram_impl):
Replace hardcoded colors for valid_style and invalid_style with
calls to text_art::get_style_from_color_cap_name.

gcc/ChangeLog:
PR analyzer/114588
* diagnostic-color.cc (color_dict): Add "valid" and "invalid" as
color capability names.
* doc/invoke.texi: Document them in description of GCC_COLORS.
* text-art/style.cc: Include "diagnostic-color.h".
(text_art::get_style_from_color_cap_name): New.
* text-art/types.h (get_style_from_color_cap_name): New decl.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/access-diagram.cc |  8 ++--
 gcc/diagnostic-color.cc|  2 ++
 gcc/doc/invoke.texi| 10 +-
 gcc/text-art/style.cc  | 18 ++
 gcc/text-art/types.h   |  2 ++
 5 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 4cb6570e90b9..85e1049bb898 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -2059,14 +2059,10 @@ public:
 
 /* Register painting styles.  */
 {
-  style valid_style;
-  valid_style.m_fg_color = style::named_color::GREEN;
-  valid_style.m_bold = true;
+  style valid_style (get_style_from_color_cap_name ("valid"));
   m_valid_style_id = m_sm.get_or_create_id (valid_style);
 
-  style invalid_style;
-  invalid_style.m_fg_color = style::named_color::RED;
-  invalid_style.m_bold = true;
+  style invalid_style (get_style_from_color_cap_name ("invalid"));
   m_invalid_style_id = m_sm.get_or_create_id (invalid_style);
 }
 
diff --git a/gcc/diagnostic-color.cc b/gcc/diagnostic-color.cc
index 4859f36da6a9..f01a0fc2e377 100644
--- a/gcc/diagnostic-color.cc
+++ b/gcc/diagnostic-color.cc
@@ -101,6 +101,8 @@ static struct color_cap color_dict[] =
   { "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 }
 };
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c584664e1688..73bb2aec7c31 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5241,7 +5241,7 @@ The default @env{GCC_COLORS} is
 error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\
 quote=01:path=01;36:fixit-insert=32:fixit-delete=31:\
 diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
-type-diff=01;32:fnname=01;32:targs=35
+type-diff=01;32:fnname=01;32:targs=35:valid=01;31:invalid=01;32
 @end smallexample
 @noindent
 where @samp{01;31} is bold red, @samp{01;35} is bold magenta,
@@ -5324,6 +5324,14 @@ SGR substring for inserted lines within generated 
patches.
 @item type-diff=
 SGR substring for highlighting mismatching types within template
 arguments in the C++ frontend.
+
+@vindex valid GCC_COLORS @r{capability}
+@item valid=
+SGR substring for highlighting valid elements within text art diagrams.
+
+@vindex invalid GCC_COLORS @r{capability}
+@item invalid=
+SGR substring for highlighting invalid elements within text art diagrams.
 @end table
 
 @opindex fdiagnostics-urls
diff --git a/gcc/text-art/style.cc b/gcc/text-art/style.cc
index e74efe23014c..5c58d432cf48 100644
--- a/gcc/text-art/style.cc
+++ b/gcc/text-art/style.cc
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "text-art/selftests.h"
 #include "text-art/types.h"
 #include "color-macros.h"
+#include "diagnostic-color.h"
 
 using namespace text_art;
 
@@ -256,6 +257,23 @@ style::print_changes (pretty_printer *pp,
 }
 }
 
+/* Look up the current SGR codes for a color capability NAME
+   (from GCC_COLORS or the defaults), and convert them to
+   a text_art::style.  */
+
+style
+text_art::get_style_from_color_cap_name (const char *name)
+{
+  const char *sgr_codes = colorize_start (true, name);
+  gcc_assert (sgr_codes);
+
+  /* Parse the sgr codes.  We expect the resulting styled_string to be
+ empty; we're interested in the final style created during parsing.  */
+  style_manager sm;
+  styled_string styled_str (sm, sgr_codes);
+  return sm.get_style (sm.get_num_styles () - 1);
+}
+
 /* class text_art::style_manager.  */
 
 style_manager::style_manager ()
diff --git a/gcc/text-art/types.h b/gcc/text-art/types.h
index 02de2e86122e..2b9f8b387c71 100644
--- a/gcc/text-art/types.h
+++ b/gcc/text-art/types.h
@@ -332,6 +332,8 @@ 

[PATCH 8/9] wwwdocs: gcc-14: analyzer improvements

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 162 +
 1 file changed, 162 insertions(+)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 8b72bc20..d782c334 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -760,6 +760,168 @@ __asm (".global __flmap_lock"  "\n\t"
   
 
 
+
+Improvements to Static Analyzer
+
+  
+New warnings:
+
+  
+   
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-infinite-loop;>-Wanalyzer-infinite-loop
+   warns about paths through the code which appear to lead to an infinite 
loop.
+  
+  
+   
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-overlapping-buffers;>-Wanalyzer-overlapping-buffers
 warns for paths through the code in which overlapping buffers are passed to an 
API for which the behavior on such buffers is undefined.
+  
+  
+   
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-undefined-behavior-strtok;>-Wanalyzer-undefined-behavior-strtok
+   warns for paths through the code in which a call is made to
+   strtok with undefined behavior.
+  
+
+  
+  
+
+Previously, the analyzer's "taint" tracking to be explicitly enabled via
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-fanalyzer-checker;>-fanalyzer-checker=taint
+(along with
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-fanalyzer;>-fanalyzer).
+This is now enabled by default when
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-fanalyzer;>-fanalyzer
+is selected, thus also enabling the 6 taint-based warnings:
+
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-allocation-size;>-Wanalyzer-tainted-allocation-size
+  
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-array-index;>-Wanalyzer-tainted-array-index
+  
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-assertion;>-Wanalyzer-tainted-assertion
+  
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-divisor;>-Wanalyzer-tainted-divisor
+  
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-offset;>-Wanalyzer-tainted-offset
+  
+  
+   https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-size;>-Wanalyzer-tainted-size
+  
+
+  
+  
+
+The analyzer will now simulate API calls that expect null-terminated
+string arguments, and will warn about code paths in which such a call
+is made with a buffer that isn't properly terminated, either due to
+a read of an uninitialized byte or an out-of-range accesses seen
+before any zero byte is seen.
+This applies to functions that use the new
+https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-null_005fterminated_005fstring_005farg-function-attribute;>
 null_terminated_string_arg(PARAM_IDX)
+attribute, 
+functions that use the
+https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute;>format
+attribute, 
+and to the library functions
+error (parameter 3),
+error_at_line (parameter 5),
+putenv,
+strchr (parameter 1), and
+strcpy (parameter 2).
+  
+  
+
+The analyzer now makes use of the function attribute
+https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute;>alloc_size
+allowing
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-fanalyzer;>-fanalyzer
+to emit
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-allocation-size;>-Wanalyzer-allocation-size,
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-out-of-bounds;>-Wanalyzer-out-of-bounds,
+and
+https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-allocation-size;>-Wanalyzer-tainted-allocation-size
+on execution paths involving allocations using such functions.
+  
+  
+The analyzer's knowledge about the behavior of the standard library has 
been extended to cover
+fopen, 
+strcat, 
+strncpy, and 
+strstr. 
+The analyzer will also more precisely model the behavior of
+memcpy, 
+memmove, 
+strcpy, 
+strdup, 
+strlen, 
+and of various atomic built-in functions. 
+  
+  
+
+The warning
+  https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-o

[PATCH 6/9] wwwdocs: gcc-14: improvements to automatic doc URLs for options

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 2dc7e598..0701dc29 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -745,7 +745,20 @@ __asm (".global __flmap_lock"  "\n\t"
 
 
 
-
+Documentation improvements
+
+  
+
+
+
+
+
+GCC's ability to provide clickable hyperlinks to the documentation
+has been extended, so that whenever GCC refers to a command-line
+option in quotes in a diagnostic message, the option is a clickable
+hyperlink (assuming a suitably capable terminal).
+  
+
 
 
 
-- 
2.39.2



[PATCH 4/9] wwwdocs: gcc-14: c++: note changes to source quoting in template errors

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index f9ce4fe5..95ed00c9 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -262,6 +262,13 @@ a work-in-progress.
   constinit and optimized dynamic initialization
 
   
+  
+
+When a diagnostic occurrs involving a C++ template,
+GCC will now quote the source code of the context at which
+the template is instantiated ("required from here"),
+rather than just print filename and line/column numbers.
+  
 
 
 Runtime Library (libstdc++)
-- 
2.39.2



[PATCH 9/9] wwwdocs: gcc-14: add 'Improvements to SARIF support' section

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index d782c334..934cd1ad 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -922,6 +922,28 @@ it emits:
   
 
 
+
+Improvements to SARIF support
+
+  
+
+The SARIF output from
+https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-format;>-fdiagnostics-format=
+now adds indentation and newlines to reflect the logical JSON structure of 
the data.  The previous compact behavior can be restored via the new option
+https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html#index-fno-diagnostics-json-formatting;>-fno-diagnostics-json-formatting.
+This also applies to the older output format named "json".
+  
+  
+
+If profiling information about the compiler itself is requested via
+https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-ftime-report;>-ftime-report,
+and a SARIF output format is requested via
+https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-format;>-fdiagnostics-format=,
+then the timing and memory usage data is now written in JSON form into
+the SARIF output, rather than as plain text to stderr.
+  
+
+
 
 Improvements for plugin authors
 
-- 
2.39.2



[PATCH 3/9] wwwdocs: gcc-14: add null_terminated_string_arg attribute

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 397458d5..f9ce4fe5 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -191,6 +191,13 @@ a work-in-progress.
 not an optimization, to avoid relying on library
 implementations.
   
+  
+
+New function attribute
+https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-null_005fterminated_005fstring_005farg-function-attribute;>
 null_terminated_string_arg(PARAM_IDX)
+for indicating parameters that are expected to be null-terminated
+strings.
+  
 
 
 New Languages and Language specific improvements
-- 
2.39.2



[PATCH 5/9] wwwdocs: gcc-14: libgccjit changes

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 95ed00c9..2dc7e598 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -360,7 +360,36 @@ a work-in-progress.
 
 
 
-
+libgccjit
+
+  The libgccjit API gained 6 new entry points:
+
+  
+   
+   https://gcc.gnu.org/onlinedocs/jit/topics/types.html#c.gcc_jit_type_get_restrict;>gcc_jit_type_get_restrict
+   for adding restrict to types
+   (https://gcc.gnu.org/onlinedocs/jit/topics/compatibility.html#libgccjit-abi-25;>LIBGCCJIT_ABI_25).
+  
+  
+   
+   4 functions for setting attributes on functions and variables
+   (https://gcc.gnu.org/onlinedocs/jit/topics/compatibility.html#libgccjit-abi-26;>LIBGCCJIT_ABI_26):
+   
+  gcc_jit_function_add_attribute
+  gcc_jit_function_add_string_attribute
+  gcc_jit_function_add_integer_array_attribute
+  gcc_jit_lvalue_add_string_attribute
+   
+  
+  
+   
+   https://gcc.gnu.org/onlinedocs/jit/topics/expressions.html#c.gcc_jit_context_new_sizeof;>gcc_jit_context_new_sizeof
+   for accessing the size of a type
+   (https://gcc.gnu.org/onlinedocs/jit/topics/compatibility.html#libgccjit-abi-27;>LIBGCCJIT_ABI_27).
+  
+
+  
+
 
 
 New Targets and Target Specific Improvements
-- 
2.39.2



[PATCH 7/9] wwwdocs: gcc-14: improvements for plugin authors

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 0701dc29..8b72bc20 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -761,7 +761,28 @@ __asm (".global __flmap_lock"  "\n\t"
 
 
 
-
+Improvements for plugin authors
+
+  
+
+GCC diagnostics have been able to have execution paths associated
+with them since GCC 10, but previously these were required to be
+single-threaded.
+As of GCC 14, these execution paths can have multipled named threads
+associated with them, with each event being associated with one of the
+threads.
+No existing GCC diagnostics take advantage of this, but GCC plugins
+may find this useful for their own diagnostics; an
+https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=3a1e9f3ed7aa49adad02190ace0614e0b37fc089;>example
+is provided in the testsuite.
+  
+  
+
+GCC's diagnostics can now optionally add per-diagnostic property
+bags to the SARIF output, allowing plugins to capture custom data
+as needed with their diagnostics.
+  
+
 
 
 Other significant improvements
-- 
2.39.2



[PATCH 2/9] wwwdocs: gcc-14: add URLs to some options

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 5cc729c5..397458d5 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -149,26 +149,33 @@ a work-in-progress.
 to enable additional hardening.
   
   
-New option -fhardened, an umbrella option that enables a set
-of hardening flags.  The options it enables can be displayed using the
+New option
+https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fhardened;>-fhardened,
+an umbrella option that enables a set of hardening flags.
+The options it enables can be displayed using the
 --help=hardened option.
   
   
-New option -fharden-control-flow-redundancy, to
-verify, at the end of functions, that the visited basic blocks
+New option
+https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fharden-control-flow-redundancy;>-fharden-control-flow-redundancy,
+to verify, at the end of functions, that the visited basic blocks
 correspond to a legitimate execution path, so as to detect and
 prevent attacks that transfer control into the middle of
 functions.
   
   
-New type attribute hardbool, for C and Ada.  Hardened
+New type attribute
+https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-hardbool-type-attribute;>hardbool,
+for C and Ada.  Hardened
 booleans take user-specified representations for true
 and false, presumably with higher hamming distance
 than standard booleans, and get verified at every use, detecting
 memory corruption and some malicious attacks.
   
   
-New type attribute strub to control stack scrubbing
+New type attribute
+https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-strub-type-attribute;>strub
+to control stack scrubbing
 properties of functions and variables.  The stack frame used by
 functions marked with the attribute gets zeroed-out upon returning
 or exception escaping.  Scalar variables marked with the attribute
@@ -176,7 +183,9 @@ a work-in-progress.
 enabled implicitly.
   
   
-New option -finline-stringops, to force inline
+New option
+https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-finline-stringops;>-finline-stringops,
+to force inline
 expansion of memcmp, memcpy,
 memmove and memset, even when that is
 not an optimization, to avoid relying on library
-- 
2.39.2



[pushed] wwwdocs: gcc-14: various changes

2024-04-04 Thread David Malcolm
I've taken the liberty of pushing the following changes
to the GCC 14 release notes.  Hope they look reasonable.

David Malcolm (9):
  gcc-14: add caveat about not using analyzer on C++
  gcc-14: add URLs to some options
  gcc-14: add null_terminated_string_arg attribute
  gcc-14: c++: note changes to source quoting in template errors
  gcc-14: libgccjit changes
  gcc-14: improvements to automatic doc URLs for options
  gcc-14: improvements for plugin authors
  gcc-14: analyzer improvements
  gcc-14: add 'Improvements to SARIF support' section

 htdocs/gcc-14/changes.html | 294 +++--
 1 file changed, 284 insertions(+), 10 deletions(-)

-- 
2.39.2



[PATCH 1/9] wwwdocs: gcc-14: add caveat about not using analyzer on C++

2024-04-04 Thread David Malcolm
Signed-off-by: David Malcolm 
---
 htdocs/gcc-14/changes.html | 4 
 1 file changed, 4 insertions(+)

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 9fd224c1..5cc729c5 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -49,6 +49,10 @@ a work-in-progress.
   unmaintained for quite a while has been declared obsolete in GCC 14.
   The next release of GCC will have their sources permanently removed.
   
+  https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html;>-fanalyzer
+is still only suitable for analyzing C code.
+In particular, using it on C++ is unlikely to give meaningful output.
+  
 
 
 
-- 
2.39.2



[pushed] analyzer: prevent ICEs with null types

2024-04-02 Thread David Malcolm
Fixes some ICEs seen analyzing the Linux kernel.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9762-ge945d322fcbc68.

gcc/analyzer/ChangeLog:
* region-model-manager.cc (maybe_undo_optimize_bit_field_compare):
Guard against null types.
* region-model.cc (apply_constraints_for_gswitch): Likewise.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model-manager.cc | 2 ++
 gcc/analyzer/region-model.cc | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index 4feb349c9142..f155eeb87c0d 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -616,6 +616,8 @@ maybe_undo_optimize_bit_field_compare (tree type,
   tree cst,
   const svalue *arg1)
 {
+  if (!type)
+return nullptr;
   if (!INTEGRAL_TYPE_P (type))
 return NULL;
 
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 902b887fc074..98f287145c6c 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -5781,7 +5781,8 @@ apply_constraints_for_gswitch (const switch_cfg_superedge 
,
  && is_a  (unaryop->get_arg ()))
if (const initial_svalue *initvalop = (as_a 
   (unaryop->get_arg (
- if (TREE_CODE (initvalop->get_type ()) == ENUMERAL_TYPE)
+ if (initvalop->get_type ()
+ && TREE_CODE (initvalop->get_type ()) == ENUMERAL_TYPE)
{
  index_sval = initvalop;
  check_index_type = false;
-- 
2.26.3



Re: [PATCH] Allow `gcc_jit_type_get_size` to work with pointers

2024-03-29 Thread David Malcolm
On Thu, 2024-03-28 at 23:47 +0100, Guillaume Gomez wrote:
> Hi,
> 
> Here's a little fix to allow the `gcc_jit_type_get_size` function to
> work on pointer types as well.
> 
Thanks, looks good to me.

Are you able to push this, or do you want me to?

Dave



[pushed] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]

2024-03-27 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9697-gfdd59818e2abf6.

gcc/analyzer/ChangeLog:
PR analyzer/114473
* call-summary.cc
(call_summary_replay::convert_svalue_from_summary): Assert that
the types match.
(call_summary_replay::convert_region_from_summary): Likewise.
(call_summary_replay::convert_region_from_summary_1): Add missing
cast for the deref of RK_SYMBOLIC case.

gcc/testsuite/ChangeLog:
PR analyzer/114473
* gcc.dg/analyzer/call-summaries-pr114473.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/call-summary.cc  | 12 +++
 .../gcc.dg/analyzer/call-summaries-pr114473.c | 31 +++
 2 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a569bb94cec5..c2c9c71f79b4 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -235,6 +235,11 @@ call_summary_replay::convert_svalue_from_summary (const 
svalue *summary_sval)
 
   const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
 
+  if (caller_sval)
+if (summary_sval->get_type () && caller_sval->get_type ())
+  gcc_assert (types_compatible_p (summary_sval->get_type (),
+ caller_sval->get_type ()));
+
   /* Add to cache.  */
   add_svalue_mapping (summary_sval, caller_sval);
 
@@ -552,6 +557,11 @@ call_summary_replay::convert_region_from_summary (const 
region *summary_reg)
 
   const region *caller_reg = convert_region_from_summary_1 (summary_reg);
 
+  if (caller_reg)
+if (summary_reg->get_type () && caller_reg->get_type ())
+  gcc_assert (types_compatible_p (summary_reg->get_type (),
+ caller_reg->get_type ()));
+
   /* Add to cache.  */
   add_region_mapping (summary_reg, caller_reg);
 
@@ -603,6 +613,8 @@ call_summary_replay::convert_region_from_summary_1 (const 
region *summary_reg)
  = get_caller_model ()->deref_rvalue (caller_ptr_sval,
   NULL_TREE,
   get_ctxt ());
+   caller_reg = mgr->get_cast_region (caller_reg,
+  summary_reg->get_type ());
return caller_reg;
   }
   break;
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c 
b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
new file mode 100644
index ..4598840f0dff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
@@ -0,0 +1,31 @@
+/* { dg-additional-options "-fanalyzer-call-summaries" } */
+
+int a;
+extern int *q[];
+
+int *
+baz (int *src)
+{
+  while (a)
+{
+  src && a;
+  return src;
+}
+}
+
+void
+bar (int **src)
+{
+  for (unsigned j = 0; j;)
+a = 0;
+  while (a)
+baz (src[0]);
+}
+
+void
+foo (void)
+{
+  bar (q);
+  baz ();
+  bar (q);
+}
-- 
2.26.3



[pushed] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408]

2024-03-23 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9646-g80a0cb37456c49.

gcc/analyzer/ChangeLog:
PR analyzer/114408
* engine.cc (impl_run_checkers): Free up any dominance info that
we may have created.
* kf.cc (class kf_ubsan_handler): New.
(register_sanitizer_builtins): New.
(register_known_functions): Call register_sanitizer_builtins.

gcc/testsuite/ChangeLog:
PR analyzer/114408
* c-c++-common/analyzer/deref-before-check-pr114408.c: New test.
* c-c++-common/ubsan/analyzer-ice-pr114408.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/engine.cc|  7 ++
 gcc/analyzer/kf.cc| 22 +++
 .../analyzer/deref-before-check-pr114408.c| 22 +++
 .../ubsan/analyzer-ice-pr114408.c |  9 
 4 files changed, 60 insertions(+)
 create mode 100644 
gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr114408.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index ad310b4d8731..e0dc0e66e88c 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -6251,6 +6251,13 @@ impl_run_checkers (logger *logger)
 eng.get_model_manager ()->dump_untracked_regions ();
 
   delete purge_map;
+
+  /* Free up any dominance info that we may have created.  */
+  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+{
+  function *fun = node->get_fun ();
+  free_dominance_info (fun, CDI_DOMINATORS);
+}
 }
 
 /* Handle -fdump-analyzer and -fdump-analyzer-stderr.  */
diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index d197ccbd0f05..6931f07bd75e 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -2198,6 +2198,27 @@ register_atomic_builtins (known_function_manager )
   make_unique (BIT_IOR_EXPR));
 }
 
+/* Handle calls to the various __builtin___ubsan_handle_*.
+   These can return, but continuing after such a return
+   isn't likely to be interesting to the user of the analyzer.
+   Hence we terminate the analysis path at one of these calls.  */
+
+class kf_ubsan_handler : public internal_known_function
+{
+  void impl_call_post (const call_details ) const final override
+  {
+if (cd.get_ctxt ())
+  cd.get_ctxt ()->terminate_path ();
+  }
+};
+
+static void
+register_sanitizer_builtins (known_function_manager )
+{
+  kfm.add (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG,
+  make_unique ());
+}
+
 /* Populate KFM with instances of known functions supported by the core of the
analyzer (as opposed to plugins).  */
 
@@ -2224,6 +2245,7 @@ register_known_functions (known_function_manager ,
 kfm.add (BUILT_IN_STACK_SAVE, make_unique ());
 
 register_atomic_builtins (kfm);
+register_sanitizer_builtins (kfm);
 register_varargs_builtins (kfm);
   }
 
diff --git a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr114408.c 
b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr114408.c
new file mode 100644
index ..d55720271d0f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr114408.c
@@ -0,0 +1,22 @@
+extern void unknown_returns (const char *p);
+extern void unknown_noreturn (const char *p) __attribute__((__noreturn__));
+
+void test_1 (const char *p)
+{
+  if (p)
+unknown_returns (p);
+  __builtin_strcmp ("a", p); /* { dg-message "pointer 'p' is dereferenced 
here" "" { target c } } */
+  if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing 
it" "" { target c } } */
+unknown_returns (p);
+  __builtin_strcmp ("a", p);  
+}
+
+void test_2 (const char *p)
+{
+  if (p)
+unknown_noreturn (p);
+  __builtin_strcmp ("a", p);
+  if (p) /* { dg-bogus "check of 'p' for NULL after already dereferencing it" 
} */
+unknown_noreturn (p);
+  __builtin_strcmp ("a", p);  
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c 
b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
new file mode 100644
index ..55f918726eed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-require-effective-target analyzer } */
+/* { dg-options "-fanalyzer -fsanitize=undefined" } */
+
+int main(){}
+
+int HMAP_unset_copy(const char *key) {
+return __builtin_strcmp("a", key) + __builtin_strcmp("a", key);
+}
-- 
2.26.3



[pushed] analyzer: look through casts in taint sanitization [PR112974, PR112975]

2024-03-22 Thread David Malcolm
PR analyzer/112974 and PR analyzer/112975 record false positives
from the analyzer's taint detection where sanitization of the form

  if (VALUE CMP VALUE-OF-WIDER-TYPE)

happens, but wasn't being "noticed" by the taint checker, due to the
test being:

  (WIDER_TYPE)VALUE CMP VALUE-OF-WIDER-TYPE

at the gimple level, and thus taint_state_machine recording
sanitization of (WIDER_TYPE)VALUE, but not of VALUE.

Fix by stripping casts in taint_state_machine::on_condition so that
the state machine records sanitization of the underlying value.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9625-gc6cf5789135236.

gcc/analyzer/ChangeLog:
PR analyzer/112974
PR analyzer/112975
* sm-taint.cc (taint_state_machine::on_condition): Strip away
casts before considering LHS and RHS, to increase the chance of
detecting places where sanitization of a value may have happened.

gcc/testsuite/ChangeLog:
PR analyzer/112974
PR analyzer/112975
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
taint-pr112974.c and taint-pr112975.c to analyzer_kernel_plugin.c.
* gcc.dg/plugin/taint-pr112974.c: New test.
* gcc.dg/plugin/taint-pr112975.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-taint.cc |  8 +++
 gcc/testsuite/gcc.dg/plugin/plugin.exp   |  2 +
 gcc/testsuite/gcc.dg/plugin/taint-pr112974.c | 59 
 gcc/testsuite/gcc.dg/plugin/taint-pr112975.c | 53 ++
 4 files changed, 122 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112975.c

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index c873c9ebd333..1d1e208fdf49 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1109,6 +1109,14 @@ taint_state_machine::on_condition (sm_context *sm_ctxt,
   return;
 }
 
+  /* Strip away casts before considering LHS and RHS, to increase the
+ chance of detecting places where sanitization of a value may have
+ happened.  */
+  if (const svalue *inner = lhs->maybe_undo_cast ())
+lhs = inner;
+  if (const svalue *inner = rhs->maybe_undo_cast ())
+rhs = inner;
+
   // TODO
   switch (op)
 {
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp 
b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index c26dda1f324b..933f9a5850bc 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -172,6 +172,8 @@ set plugin_test_list [list \
  taint-pr112850-too-complex.c \
  taint-pr112850-unsanitized.c \
  taint-pr112927.c \
+ taint-pr112974.c \
+ taint-pr112975.c \
  taint-pr112977.c } \
 { analyzer_cpython_plugin.c \
  cpython-plugin-test-no-Python-h.c \
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c 
b/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
new file mode 100644
index ..1af505326c78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
@@ -0,0 +1,59 @@
+/* Reduced from false positive in Linux kernel in
+   drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+extern unsigned int __max_logical_packages;
+extern unsigned long
+copy_from_user(void* to, const void* from, unsigned long n);
+extern unsigned long
+copy_to_user(void* to, const void* from, unsigned long n);
+struct isst_tpmi_instance_count
+{
+  __u8 socket_id;
+  __u8 count;
+  __u16 valid_mask;
+};
+struct tpmi_per_power_domain_info
+{
+  void* sst_base;
+};
+struct tpmi_sst_struct
+{
+  int number_of_power_domains;
+  struct tpmi_per_power_domain_info* power_domain_info;
+};
+struct tpmi_sst_common_struct
+{
+  int max_index;
+  struct tpmi_sst_struct** sst_inst;
+};
+static struct tpmi_sst_common_struct isst_common;
+int
+isst_if_get_tpmi_instance_count(void* argp)
+{
+  struct isst_tpmi_instance_count tpmi_inst;
+  struct tpmi_sst_struct* sst_inst;
+  int i;
+  if (copy_from_user(_inst, argp, sizeof(tpmi_inst)))
+return -14;
+  if (tpmi_inst.socket_id >= (__max_logical_packages))
+return -22;
+  tpmi_inst.count =
+isst_common.sst_inst[tpmi_inst.socket_id]->number_of_power_domains; /* { 
dg-bogus "use of attacker-controlled value as offset without upper-bounds 
checking" } */
+  sst_inst = isst_common.sst_inst[tpmi_inst.socket_id];
+  tpmi_inst.valid_mask = 0;
+  for (i = 0; i < sst_inst->number_of_power_domains; ++i) {
+struct tpmi_per_power_domain_info* pd_info;
+pd_info = _inst->power_domain_info[i];
+if (pd_info->sst_base)
+  tpmi_inst.valid_mask |= 1UL))) << (i));
+  }
+  i

[pushed] analyzer: add SARIF property bags to taint diagnostics

2024-03-22 Thread David Malcolm
Another followup to r14-6057-g12b67d1e13b3cf to make it easier to debug
the analyzer.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9624-gd475a4571ef310.

gcc/analyzer/ChangeLog:
* sm-taint.cc: Include "diagnostic-format-sarif.h".
(bounds_to_str): New.
(taint_diagnostic::maybe_add_sarif_properties): New.
(tainted_offset::tainted_offset): Add "offset" param.
(tainted_offset::maybe_add_sarif_properties): New.
(tainted_offset::m_offset): New.
(region_model::check_region_for_taint): Pass offset to
tainted_offset ctor.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-taint.cc | 50 +---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index bbf683f82efc..c873c9ebd333 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/program-state.h"
 #include "analyzer/pending-diagnostic.h"
 #include "analyzer/constraint-manager.h"
+#include "diagnostic-format-sarif.h"
 
 #if ENABLE_ANALYZER
 
@@ -71,6 +72,22 @@ enum bounds
   BOUNDS_LOWER
 };
 
+static const char *
+bounds_to_str (enum bounds b)
+{
+  switch (b)
+{
+default:
+  gcc_unreachable ();
+case BOUNDS_NONE:
+  return "BOUNDS_NONE";
+case BOUNDS_UPPER:
+  return "BOUNDS_UPPER";
+case BOUNDS_LOWER:
+  return "BOUNDS_LOWER";
+}
+}
+
 /* An experimental state machine, for tracking "taint": unsanitized uses
of data potentially under an attacker's control.  */
 
@@ -193,6 +210,17 @@ public:
 return diagnostic_event::meaning ();
   }
 
+  void maybe_add_sarif_properties (sarif_object _obj)
+const override
+  {
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/taint_diagnostic/"
+props.set (PROPERTY_PREFIX "arg", tree_to_json (m_arg));
+props.set_string (PROPERTY_PREFIX "has_bounds",
+ bounds_to_str (m_has_bounds));
+#undef PROPERTY_PREFIX
+  }
+
 protected:
   const taint_state_machine _sm;
   tree m_arg;
@@ -315,8 +343,10 @@ class tainted_offset : public taint_diagnostic
 {
 public:
   tainted_offset (const taint_state_machine , tree arg,
-  enum bounds has_bounds)
-  : taint_diagnostic (sm, arg, has_bounds)
+ enum bounds has_bounds,
+ const svalue *offset)
+  : taint_diagnostic (sm, arg, has_bounds),
+m_offset (offset)
   {}
 
   const char *get_kind () const final override { return "tainted_offset"; }
@@ -409,6 +439,19 @@ public:
 " checking");
}
   }
+
+  void maybe_add_sarif_properties (sarif_object _obj)
+const final override
+  {
+taint_diagnostic::maybe_add_sarif_properties (result_obj);
+sarif_property_bag  = result_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/tainted_offset/"
+props.set (PROPERTY_PREFIX "offset", m_offset->to_json ());
+#undef PROPERTY_PREFIX
+  }
+
+private:
+  const svalue *m_offset;
 };
 
 /* Concrete taint_diagnostic subclass for reporting attacker-controlled
@@ -1554,7 +1597,8 @@ region_model::check_region_for_taint (const region *reg,
if (taint_sm.get_taint (state, effective_type, ))
  {
tree arg = get_representative_tree (offset);
-   ctxt->warn (make_unique (taint_sm, arg, b));
+   ctxt->warn (make_unique (taint_sm, arg, b,
+offset));
  }
  }
  break;
-- 
2.26.3



[pushed] analyzer: fix ignored constraints involving casts [PR113619]

2024-03-21 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9600-g7a5a4a4467b2e1.

gcc/analyzer/ChangeLog:
PR analyzer/113619
* region-model.cc (region_model::eval_condition): Fix
cast-handling from r14-3632-ge7b267444045c5 so that if those give
an unknown result, we continue trying the constraint manager.

gcc/testsuite/ChangeLog:
PR analyzer/113619
* c-c++-common/analyzer/taint-divisor-pr113619.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/region-model.cc  | 24 ++-
 .../analyzer/taint-divisor-pr113619.c | 29 +++
 2 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/analyzer/taint-divisor-pr113619.c

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c3a4ec7bcfc5..902b887fc074 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -4704,17 +4704,27 @@ region_model::eval_condition (const svalue *lhs,
 if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
&& rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
&& lhs_type == rhs_type)
-  return eval_condition (lhs_un_op->get_arg (),
-op,
-rhs_un_op->get_arg ());
-
+  {
+   tristate res = eval_condition (lhs_un_op->get_arg (),
+  op,
+  rhs_un_op->get_arg ());
+   if (res.is_known ())
+ return res;
+  }
 else if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
 && lhs_type == rhs_type)
-  return eval_condition (lhs_un_op->get_arg (), op, rhs);
-
+  {
+   tristate res = eval_condition (lhs_un_op->get_arg (), op, rhs);
+   if (res.is_known ())
+ return res;
+  }
 else if (rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
 && lhs_type == rhs_type)
-  return eval_condition (lhs, op, rhs_un_op->get_arg ());
+  {
+   tristate res = eval_condition (lhs, op, rhs_un_op->get_arg ());
+   if (res.is_known ())
+ return res;
+  }
   }
 
   /* Otherwise, try constraints.
diff --git a/gcc/testsuite/c-c++-common/analyzer/taint-divisor-pr113619.c 
b/gcc/testsuite/c-c++-common/analyzer/taint-divisor-pr113619.c
new file mode 100644
index ..15c881247ce7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/taint-divisor-pr113619.c
@@ -0,0 +1,29 @@
+/* Reduced from false positive in Linux kernel's fs/ceph/ioctl.c: */
+
+__extension__ typedef unsigned long long __u64;
+
+struct ceph_ioctl_layout
+{
+  __u64 stripe_unit, object_size;
+};
+static long
+__validate_layout(struct ceph_ioctl_layout* l)
+{
+  if ((l->object_size & ~(~(((1UL) << 12) - 1))) ||
+  (l->stripe_unit & ~(~(((1UL) << 12) - 1))) ||
+  ((unsigned)l->stripe_unit != 0 &&
+   ((unsigned)l->object_size % (unsigned)l->stripe_unit))) /* { dg-bogus 
"use of attacker-controlled value 'l.stripe_unit' as divisor without checking 
for zero" "PR analyzer/113619" } */
+return -22;
+  return 0;
+}
+
+long
+__attribute__((tainted_args))
+ceph_ioctl_set_layout_policy(struct ceph_ioctl_layout l)
+{
+  int err;
+  err = __validate_layout();
+  if (err)
+return err;
+  return err;
+}
-- 
2.26.3



[pushed] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251]

2024-03-20 Thread David Malcolm
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9586-g9093f275e0a343.

gcc/analyzer/ChangeLog:
PR analyzer/109251
* sm-malloc.cc (deref_before_check::emit): Reject cases where the
check is in a loop header within a macro expansion.
(deref_before_check::loop_header_p): New.

gcc/testsuite/ChangeLog:
PR analyzer/109251
* c-c++-common/analyzer/deref-before-check-pr109251-1.c: New test.
* c-c++-common/analyzer/deref-before-check-pr109251-2.c: New test.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-malloc.cc | 30 ++
 .../analyzer/deref-before-check-pr109251-1.c  | 60 +++
 .../analyzer/deref-before-check-pr109251-2.c  | 37 
 3 files changed, 127 insertions(+)
 create mode 100644 
gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-1.c
 create mode 100644 
gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-2.c

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index a518816b2b8..4e11d6dfc63 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -1563,6 +1563,21 @@ public:
 if (linemap_location_from_macro_definition_p (line_table, check_loc))
   return false;
 
+/* Reject warning if the check is in a loop header within a
+   macro expansion.  This rejects cases like:
+   |  deref of x;
+   |  [...snip...]
+   |  FOR_EACH(x) {
+   |[...snip...]
+   |  }
+   where the FOR_EACH macro tests for non-nullness of x, since
+   the user is hoping to encapsulate the details of iteration
+   in the macro, and the extra check on the first iteration
+   would just be noise if we reported it.  */
+if (loop_header_p (m_check_enode->get_point ())
+   && linemap_location_from_macro_expansion_p (line_table, check_loc))
+  return false;
+
 /* Reject if m_deref_expr is sufficiently different from m_arg
for cases where the dereference is spelled differently from
the check, which is probably two different ways to get the
@@ -1618,6 +1633,21 @@ public:
   }
 
 private:
+  static bool loop_header_p (const program_point )
+  {
+const supernode *snode = point.get_supernode ();
+if (!snode)
+  return false;
+for (auto _edge : snode->m_preds)
+  {
+   if (const cfg_superedge *cfg_in_edge
+ = in_edge->dyn_cast_cfg_superedge ())
+ if (cfg_in_edge->back_edge_p ())
+   return true;
+  }
+return false;
+  }
+
   static bool sufficiently_similar_p (tree expr_a, tree expr_b)
   {
 pretty_printer *pp_a = global_dc->printer->clone ();
diff --git 
a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-1.c 
b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-1.c
new file mode 100644
index 000..769cffae6d7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-1.c
@@ -0,0 +1,60 @@
+/* Reduced from linux-5.10.162's kernel/sched/fair.c,
+   with !CONFIG_FAIR_GROUP_SCHED.  */
+
+#define NULL ((void*)0)
+
+struct load_weight
+{
+  unsigned long weight;
+  /* [...snip...] */
+};
+
+struct sched_entity
+{
+  struct load_weight load;
+  /* [...snip...] */
+  unsigned int on_rq;
+  /* [...snip...] */
+};
+
+struct cfs_rq
+{
+  /* [...snip...] */
+  unsigned int nr_running;
+  /* [...snip...] */
+};
+
+extern int
+__calc_delta(int delta_exec, unsigned long weight /* [...snip...] */);
+
+/* !CONFIG_FAIR_GROUP_SCHED */
+#define for_each_sched_entity(se) \
+  for (; se; se = (struct sched_entity *)NULL)
+
+extern struct cfs_rq*
+cfs_rq_of(struct sched_entity* se);
+
+extern int
+__sched_period(unsigned long nr_running);
+
+int
+sched_slice(struct cfs_rq* cfs_rq, struct sched_entity* se)
+{
+  unsigned int nr_running = cfs_rq->nr_running;
+  int slice;
+
+  /* [...snip...] */
+
+  slice = __sched_period(nr_running + !se->on_rq);
+
+  for_each_sched_entity(se) {
+/* [...snip...] */
+cfs_rq = cfs_rq_of(se);
+/* [...snip...] */
+slice = __calc_delta(slice, se->load.weight);
+  }
+
+  /* [...snip...] */
+
+  return slice;
+}
diff --git 
a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-2.c 
b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-2.c
new file mode 100644
index 000..8e85a47d315
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109251-2.c
@@ -0,0 +1,37 @@
+struct node
+{
+  struct node *next;
+  int val;
+};
+
+int test_loop_1 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+return -1;
+  for (struct node *iter = n; iter; iter=iter->next)
+total += iter->val;
+  return total;
+}
+
+int test_loop_2 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+return -1;
+  for (; n; n=n->next)
+total += n-&

[pushed] analyzer: fix ICE due to corrupt MEM_REFs [PR113505]

2024-03-19 Thread David Malcolm
From: Jakub Jelinek 

Jakub wrote this patch for PR analyzer/113505.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9555-gc87f1f3d660f41.

gcc/analyzer/ChangeLog
PR analyzer/113505
* region-model.cc (get_tree_for_byte_offset,
region_model::get_representative_path_var_1,
test_mem_ref, test_POINTER_PLUS_EXPR_then_MEM_REF): Use
char __attribute__((may_alias)) * as type of MEM_REF second argument.

gcc/testsuite/ChangeLog
PR analyzer/113505
* gcc.dg/analyzer/pr113505.c: New test.
---
 gcc/analyzer/region-model.cc | 16 ++--
 gcc/testsuite/gcc.dg/analyzer/pr113505.c | 24 
 2 files changed, 34 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr113505.c

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index f079d1fb37e..8fff5324173 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3967,9 +3967,10 @@ static tree
 get_tree_for_byte_offset (tree ptr_expr, byte_offset_t byte_offset)
 {
   gcc_assert (ptr_expr);
+  tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode, true);
   return fold_build2 (MEM_REF,
  char_type_node,
- ptr_expr, wide_int_to_tree (size_type_node, byte_offset));
+ ptr_expr, wide_int_to_tree (ptype, byte_offset));
 }
 
 /* Simulate a series of reads of REG until we find a 0 byte
@@ -5360,9 +5361,10 @@ region_model::get_representative_path_var_1 (const 
region *reg,
tree addr_parent = build1 (ADDR_EXPR,
   build_pointer_type (reg->get_type ()),
   parent_pv.m_tree);
-   return path_var (build2 (MEM_REF,
-reg->get_type (),
-addr_parent, offset_pv.m_tree),
+   tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode,
+ true);
+   return path_var (build2 (MEM_REF, reg->get_type (), addr_parent,
+fold_convert (ptype, offset_pv.m_tree)),
 parent_pv.m_stack_depth);
   }
 
@@ -9024,7 +9026,8 @@ test_mem_ref ()
 
   tree int_17 = build_int_cst (integer_type_node, 17);
   tree addr_of_x = build1 (ADDR_EXPR, int_star, x);
-  tree offset_0 = build_int_cst (integer_type_node, 0);
+  tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode, true);
+  tree offset_0 = build_int_cst (ptype, 0);
   tree star_p = build2 (MEM_REF, integer_type_node, p, offset_0);
 
   region_model_manager mgr;
@@ -9074,7 +9077,8 @@ test_POINTER_PLUS_EXPR_then_MEM_REF ()
   tree a = build_global_decl ("a", int_star);
   tree offset_12 = build_int_cst (size_type_node, 12);
   tree pointer_plus_expr = build2 (POINTER_PLUS_EXPR, int_star, a, offset_12);
-  tree offset_0 = build_int_cst (integer_type_node, 0);
+  tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode, true);
+  tree offset_0 = build_int_cst (ptype, 0);
   tree mem_ref = build2 (MEM_REF, integer_type_node,
 pointer_plus_expr, offset_0);
   region_model_manager mgr;
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr113505.c 
b/gcc/testsuite/gcc.dg/analyzer/pr113505.c
new file mode 100644
index 000..58a2b6cd6f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr113505.c
@@ -0,0 +1,24 @@
+/* PR analyzer/113505 */
+/* { dg-additional-options "-O -fdump-analyzer" } */
+
+enum E **foo () __attribute__((__const__));
+char a[2];
+void bar (char *);
+
+void
+baz (void)
+{
+  char *s, *l;
+  for (;;)
+{
+  bar (a);
+  s = a;
+  while (foo ()[*s])
+   s++;
+  l = s;
+  *l++ = '\0';
+  while (foo ()[*l])
+   l++;
+  bar (s);
+}
+}
-- 
2.26.3



[pushed] diagnostics: fix corrupt json/SARIF on stderr [PR114348]

2024-03-19 Thread David Malcolm
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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Lightly tested manually.
Pushed to trunk as r14-9554-g0bf99b1b7eda2f.

gcc/ChangeLog:
PR middle-end/114348
* diagnostic-format-json.cc
(json_stderr_output_format::machine_readable_stderr_p): New.
(json_file_output_format::machine_readable_stderr_p): New.
* diagnostic-format-sarif.cc
(sarif_stream_output_format::machine_readable_stderr_p): New.
(sarif_file_output_format::machine_readable_stderr_p): New.
* diagnostic.cc (diagnostic_context::action_after_output): Move
"fnotice" to before "finish" call, so that we still have the
diagnostic_context.
(fnotice): Bail out if the user requested one of the
machine-readable diagnostic output formats on stderr.
* diagnostic.h
(diagnostic_output_format::machine_readable_stderr_p): New pure
virtual function.
(diagnostic_text_output_format::machine_readable_stderr_p): New.
(diagnostic_context::get_output_format): New accessor.

Signed-off-by: David Malcolm 
---
 gcc/diagnostic-format-json.cc  |  8 
 gcc/diagnostic-format-sarif.cc |  8 
 gcc/diagnostic.cc  | 12 +++-
 gcc/diagnostic.h   | 10 ++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 51e016b6463..0782ae831eb 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -314,6 +314,10 @@ public:
   {
 flush_to_file (stderr);
   }
+  bool machine_readable_stderr_p () const final override
+  {
+return true;
+  }
 };
 
 class json_file_output_format : public json_output_format
@@ -345,6 +349,10 @@ public:
 fclose (outf);
 free (filename);
   }
+  bool machine_readable_stderr_p () const final override
+  {
+return false;
+  }
 
 private:
   char *m_base_file_name;
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 307b2f56c28..97c5943cd33 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1750,6 +1750,10 @@ public:
   {
 m_builder.flush_to_file (m_stream);
   }
+  bool machine_readable_stderr_p () const final override
+  {
+return m_stream == stderr;
+  }
 private:
   FILE *m_stream;
 };
@@ -1782,6 +1786,10 @@ public:
 fclose (outf);
 free (filename);
   }
+  bool machine_readable_stderr_p () const final override
+  {
+return false;
+  }
 
 private:
   char *m_base_file_name;
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 1d143fa7498..8e4621f8031 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -802,8 +802,8 @@ diagnostic_context::action_after_output (diagnostic_t 
diag_kind)
 case DK_FATAL:
   if (m_abort_on_error)
real_abort ();
-  finish ();
   fnotice (stderr, "compilation terminated.\n");
+  finish ();
   exit (FATAL_EXIT_CODE);
 
 default:
@@ -2264,6 +2264,16 @@ diagnostic_context::emit_diagram (const 
diagnostic_diagram )
 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)
+if (const diagnostic_output_format *output_format
+ = global_dc->get_output_format ())
+  if (output_format->machine_readable_stderr_p ())
+   return;
+
   va_list ap;
 
   va_start (ap, cmsgid);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 0a7c7e02b37..065ac784e25 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -210,6 +210,7 @@ public:
   virtual void on_end_diagnostic (const diagnostic_info &,
  diagnostic_t orig_diag_kind) = 0;
   virtual void on_diagram (const diagnostic_diagram ) = 0;
+  virtual bool machine_readable_stderr_p () const = 0;
 
 protected:
   diagnostic_output_format (diagnostic_context )
@@ -238,6 +239,10 @@ public:
   void on_end_diagnostic (const diagnostic_info &,
  diagnostic_t orig_diag_kind) override;
   void on_diagram (const diagnostic_diagram ) override;
+  bool machine_readable_stderr_p () const final override
+  {
+return false;
+  }
 };
 
 /* A stack of sets of classifications: each entry in the stack is
@@ -432,6 +437,11 @@ public:
 
   void emit_diagram (const diagnostic_diagram );
 
+  const diagnostic_output_format *get_output_format () const
+  {
+return m_outp

Re: ping: [PATCH] diagnostics: Fix behavior of permerror options after diagnostic pop [PR111918]

2024-03-19 Thread David Malcolm
On Tue, 2024-03-19 at 09:03 -0400, Lewis Hyatt wrote:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638692.html

Sorry about the delay.

The patch looks good for trunk, assuming it's passed the usual
bootstrap and regression testing.

Thanks
Dave

> 
> Thanks!
> 
> On Fri, Feb 16, 2024 at 7:02 PM Lewis Hyatt  wrote:
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638692.html
> > 
> > On Thu, Jan 25, 2024 at 4:57 PM Lewis Hyatt 
> > wrote:
> > > 
> > > May I please ask again about this one? It's just a couple lines,
> > > and I
> > > think it fixes an important gap in the logic for #pragma GCC
> > > diagnostic. The PR was not reported by me so I think at least one
> > > other person does care about it :). Thanks!
> > > 
> > > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638692.html
> > > 
> > > -Lewis
> > > 
> > > On Mon, Jan 8, 2024 at 6:53 PM Lewis Hyatt 
> > > wrote:
> > > > 
> > > > Can I please ping this one again? It's 3 lines or so to fix the
> > > > PR. Thanks!
> > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638692.html
> > > > 
> > > > On Tue, Dec 19, 2023 at 6:20 PM Lewis Hyatt 
> > > > wrote:
> > > > > 
> > > > > Hello-
> > > > > 
> > > > > May I please ping this one? Thanks...
> > > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638692.html
> > > > > 
> > > > > -Lewis
> > > > > 
> > > > > On Wed, Nov 29, 2023 at 7:05 PM Lewis Hyatt
> > > > >  wrote:
> > > > > > 
> > > > > > On Thu, Nov 09, 2023 at 04:16:10PM -0500, Lewis Hyatt
> > > > > > wrote:
> > > > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111918
> > > > > > > 
> > > > > > > This patch fixes the behavior of `#pragma GCC diagnostic
> > > > > > > pop' for permissive
> > > > > > > error diagnostics such as -Wnarrowing (in C++11). Those
> > > > > > > currently do not
> > > > > > > return to the correct state after the last pop; they
> > > > > > > become effectively
> > > > > > > simple warnings instead. Bootstrap + regtest all
> > > > > > > languages on x86-64, does
> > > > > > > it look OK please? Thanks!
> > > > > > 
> > > > > > Hello-
> > > > > > 
> > > > > > May I please ping this bug fix?
> > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/635871.html
> > > > > > 
> > > > > > Please note, it requires a trivial rebase on top of recent
> > > > > > changes to
> > > > > > the class diagnostic_context public interface. I attached
> > > > > > the rebased patch
> > > > > > here as well. Thanks!
> > > > > > 
> > > > > > -Lewis
> 



  1   2   3   4   5   6   7   8   9   10   >