[gcc r15-131] testsuite: fix analyzer C++ failures on Solaris [PR111475]

2024-05-03 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:5219414f3cde3c1037e289a6654cd722cfa75dea

commit r15-131-g5219414f3cde3c1037e289a6654cd722cfa75dea
Author: David Malcolm 
Date:   Fri May 3 09:05:29 2024 -0400

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

As part of PR analyzer/96395, these patches moved testcases from
gcc.dg/analyzer to c-c++-common/analyzer:
- r14-3503-g55f6a7d949abc7
- r14-3823-g50b5199cff6908
- r14-6564-gae034b9106fbdd

Unfortunately this led to numerous g++ testsuite failures on Solaris,
tracked as PR analyzer/111475.

Almost all of the failures are due to standard library differences where
including a C standard library on C++ e.g.  leads to the plain
symbols referencing the symbols "std::" via a "using" declaration,
whereas I had written the code expecting them to use symbols in the root
namespace.

The analyzer has special-case handling of many functions by name.
This patch generalizes such handling to also match against functions
in "std::" for all of the cases I found in the testsuite (via manual
inspection of the preprocessed test cases against Solaris headers).
This fixes cases where the analyzer was failing to "know about" the
behavior of such functions.

Other such failures are due to "std::" prefixes appearing in names of
functions in the output, leading to mismatches against expected output.
The patch adds regexes to some cases, and moves some other cases back
from c-c++-common to gcc.dg where the dg-multiline syntax isn't
expressive enough.

Various "fd-*.c" failures relate to Solaris's socket-handling functions
not being marked with "noexcept", where due to PR analyzer/97111 we
mishandle the exception-handling edges in the CFG, leading to leak
false positives.  The patch works around this by adding -fno-exceptions
to these cases, pending a proper fix for PR analyzer/97111.

gcc/analyzer/ChangeLog:
PR analyzer/111475
* analyzer.cc (is_special_named_call_p): Add "look_in_std" param.
(is_std_function_p): Make non-static.
* analyzer.h (is_special_named_call_p): Add optional "look_in_std"
param.
(is_std_function_p): New decl.
* engine.cc (stmt_requires_new_enode_p): Look for both "signal"
and "std::signal".
* kf.cc (register_known_functions): Add various "std::" copies
of the known functions.
* known-function-manager.cc
(known_function_manager::~known_function_manager): Clean up
m_std_ns_map_id_to_kf.
(known_function_manager::add_std_ns): New.
(known_function_manager::get_match): Also look for known "std::"
functions.
(known_function_manager::get_by_identifier_in_std_ns): New.
* known-function-manager.h
(known_function_manager::add_std_ns): New decl.
(known_function_manager::get_by_identifier_in_std_ns): New decl.
(known_function_manager::m_std_ns_map_id_to_kf): New field.
* sm-file.cc (register_known_file_functions): Add various "std::"
copies of the known functions.
* sm-malloc.cc (malloc_state_machine::on_stmt): Handle
"std::realloc".
* sm-signal.cc (signal_unsafe_p): Consider "std::" copies of the
functions as also being async-signal-unsafe.
(signal_state_machine::on_stmt): Consider "std::signal".

gcc/testsuite/ChangeLog:
PR analyzer/111475
* c-c++-common/analyzer/fd-glibc-byte-stream-socket.c: Add
-fno-exceptions for now.
* c-c++-common/analyzer/fd-manpage-getaddrinfo-client.c: Likewise.
* c-c++-common/analyzer/fd-mappage-getaddrinfo-server.c: Rename 
to...
* c-c++-common/analyzer/fd-manpage-getaddrinfo-server.c: ...this, 
and
add -fno-exceptions for now.
* c-c++-common/analyzer/fd-socket-meaning.c: Add -fno-exceptions
for now.
* c-c++-common/analyzer/fd-symbolic-socket.c: Likewise.
* c-c++-common/analyzer/flexible-array-member-1.c: Use regexp to
handle C vs C++ differences in spelling of function name, which
could have a "std::" prefix on some targets.
* c-c++-common/analyzer/pr106539.c: Likewise.
* c-c++-common/analyzer/malloc-ipa-8-unchecked.c: Move back to...
* 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 

[gcc r13-8741] analyzer: add caching to globals with initializers [PR110112]

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

commit r13-8741-g89feb3557a018893cfe50c2e07f91559bd3cde2b
Author: David Malcolm 
Date:   Thu May 9 13:09:26 2024 -0400

analyzer: add caching to globals with initializers [PR110112]

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 

Diff:
---
 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 fb81d43f91b2..18996c5e5e85 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 a18bfa50d09b..f982ce67509e 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_

[gcc r13-8742] analyzer: Fix allocation size false positive on conjured svalue [PR109577]

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

commit r13-8742-gccf8d3e3d26c6ba3d5e11fffeed8d64018e9c060
Author: Tim Lange 
Date:   Thu May 9 13:09:26 2024 -0400

analyzer: Fix allocation size false positive on conjured svalue [PR109577]

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 

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

diff --git a/gcc/analyzer/constraint-manager.cc 
b/gcc/analyzer/constraint-manager.cc
index 2c9c435527ea..9211366fb7c4 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 (&finder);
+ 

[gcc r13-8743] testsuite: Add more allocation size tests for conjured svalues [PR110014]

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

commit r13-8743-ge0c52905f666e3d23881f82dbf39466a24f009f4
Author: Tim Lange 
Date:   Thu May 9 13:09:26 2024 -0400

testsuite: Add more allocation size tests for conjured svalues [PR110014]

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 

Diff:
---
 gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c | 25 
 1 file changed, 25 insertions(+)

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 ..d76b87814136
--- /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), &cc))
+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));
+}


[gcc r13-8744] jit: avoid using __vector in testcase [PR110466]

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

commit r13-8744-gb38472ffc1e631bd357573b44d956ce16d94e666
Author: David Malcolm 
Date:   Thu May 9 13:09:27 2024 -0400

jit: avoid using __vector in testcase [PR110466]

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 

Diff:
---
 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 13b3baf79ea5..2337b01907ec 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};


[gcc r13-8752] analyzer: casting all zeroes should give all zeroes [PR113333]

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

commit r13-8752-g132eb1a210bc7806c4cf188ecac6c08339c94384
Author: David Malcolm 
Date:   Thu May 9 13:09:29 2024 -0400

analyzer: casting all zeroes should give all zeroes [PR11]

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 

Diff:
---
 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 1a9886fd83c2..51a2d8b029f2 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 bc28128671f9..efb1a24c96a7 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 159bc612576c..2121f20c4f02 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 aedf0464dc93..c06a5c02f795 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 } */
 }


[gcc r13-8750] analyzer: fix ICE for 2 bits before the start of base region [PR112889]

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

commit r13-8750-ga1cb188cb2ca2ad3f4e837dba2967f323669d36e
Author: David Malcolm 
Date:   Thu May 9 13:09:29 2024 -0400

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

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 

Diff:
---
 gcc/analyzer/store.h | 10 +-
 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c | 17 +
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 7ded650b6088..6b06be29d8f6 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 ..e90a53e79baf
--- /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;
+}


[gcc r13-8747] analyzer: fix ICE on zero-sized arrays [PR110882]

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

commit r13-8747-ga0b13d0860848dd5f2876897ada1e22e4e681e91
Author: David Malcolm 
Date:   Thu May 9 13:09:28 2024 -0400

analyzer: fix ICE on zero-sized arrays [PR110882]

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 

Diff:
---
 gcc/analyzer/region.cc   |  6 +-
 gcc/testsuite/gcc.dg/analyzer/pr110882.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index f982ce67509e..c1bfecabd158 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 ..80027184053e
--- /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);
+}


[gcc r13-8753] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969]

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

commit r13-8753-g0593151221ad21c2a67dfda597539c458ab731d8
Author: David Malcolm 
Date:   Thu May 9 13:09:30 2024 -0400

analyzer: fix defaults in compound assignments from non-zero offsets 
[PR112969]

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 

Diff:
---
 gcc/analyzer/store.cc  | 11 -
 .../gcc.dg/analyzer/compound-assignment-5.c| 29 +---
 .../gcc.dg/analyzer/compound-assignment-pr112969.c | 35 +++
 gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c| 52 ++
 gcc/testsuite/gcc.dg/plugin/plugin.exp |  1 +
 5 files changed, 109 insertions(+), 19 deletions(-)

diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e8c927b9fe9b..0acb0a2b1865 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 ccf8fe392bfa..e1f42177b08c 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

[gcc r13-8749] jit: dump string literal initializers correctly

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

commit r13-8749-gb8c772cae97b54386f7853edf0f9897012bfa90b
Author: Vibhav Pant 
Date:   Thu May 9 13:09:28 2024 -0400

jit: dump string literal initializers correctly

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 

Diff:
---
 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 df0368ff8f70..cf734cf7ef5f 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -4919,7 +4919,7 @@ recording::global::write_to_dump (dump &d)
   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");
 }


[gcc r13-8745] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466]

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

commit r13-8745-g60dcb710b6b4aa22ea96abc8df6dfe9067f3d7fe
Author: David Malcolm 
Date:   Thu May 9 13:09:27 2024 -0400

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

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 

Diff:
---
 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 35d38cec5bc1..83fb6371fd24 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 }
 }


[gcc r13-8755] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289]

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

commit r13-8755-g67d104f3a032ee64bae335269bf1b8434785cc63
Author: David Malcolm 
Date:   Thu May 9 13:09:31 2024 -0400

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

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 

Diff:
---
 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(-)

diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index aeea73a3899e..6e13271969a4 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 &sval, 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 
&arg_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 &cd) 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 ..33d83169c3e0
--- /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/tests

[gcc r13-8759] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700]

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

commit r13-8759-g230f672b3ed0f64c9110ef9dba616c17d713816d
Author: David Malcolm 
Date:   Thu May 9 13:09:32 2024 -0400

diagnostics: fix ICE on sarif output when source file is unreadable 
[PR111700]

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 

Diff:
---
 gcc/input.cc | 12 ++--
 .../c-c++-common/diagnostic-format-sarif-file-pr111700.c | 12 
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/gcc/input.cc b/gcc/input.cc
index eaf301ec7c15..d1668ef5dcd5 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 ..06605accf6e0
--- /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" } } */


[gcc r13-8746] analyzer: fix ICE on division of tainted floating-point values [PR110700]

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

commit r13-8746-g0df1ee083434ac00ecb19582b1e5b25e105981b2
Author: David Malcolm 
Date:   Thu May 9 13:09:28 2024 -0400

analyzer: fix ICE on division of tainted floating-point values [PR110700]

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 

Diff:
---
 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(-)

diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index fab5bba15d5f..1a9886fd83c2 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 f72f194460c2..7bce3ef79b2d 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 ..de9a1cb3a46f
--- /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;
+}


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

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

commit r13-8758-g96f7a3694c3e4c72af6258cc9b38bce30e609bee
Author: David Malcolm 
Date:   Thu May 9 13:09:32 2024 -0400

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

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 

Diff:
---
 gcc/analyzer/engine.cc |  7 +++
 gcc/analyzer/kf.cc | 22 ++
 .../c-c++-common/ubsan/analyzer-ice-pr114408.c |  9 +
 .../gcc.dg/analyzer/deref-before-check-pr114408.c  | 22 ++
 4 files changed, 60 insertions(+)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index a5965c2b8ff0..c5aadc41d114 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 93c46630f361..4389ff917b8f 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -987,6 +987,27 @@ region_model::impl_deallocation_call (const call_details 
&cd)
   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 &cd) const final override
+  {
+if (cd.get_ctxt ())
+  cd.get_ctxt ()->terminate_path ();
+  }
+};
+
+static void
+register_sanitizer_builtins (known_function_manager &kfm)
+{
+  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)
 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 ..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);
+}
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 ..d55720271d0f
--- /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);  
+}


[gcc r13-8748] testsuite, analyzer: add test case [PR108171]

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

commit r13-8748-g44968a0e00f656e9bb3e504bb2fa1a8282002015
Author: David Malcolm 
Date:   Thu May 9 13:09:28 2024 -0400

testsuite, analyzer: add test case [PR108171]

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 

Diff:
---
 gcc/testsuite/gcc.dg/analyzer/pr108171.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/analyzer/pr108171.c 
b/gcc/testsuite/gcc.dg/analyzer/pr108171.c
new file mode 100644
index ..5f7b9fd78754
--- /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;
+  sfctx = 0;
+  fill_sfeatures_bitmap(&nlctx);
+}


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

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

commit r13-8756-ged026106ce420c7d9dd4d89caac017b6f235e219
Author: David Malcolm 
Date:   Thu May 9 13:09:31 2024 -0400

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

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 

Diff:
---
 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(+)

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 64295cfb66e7..e9384a14dead 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 &point)
+  {
+const supernode *snode = point.get_supernode ();
+if (!snode)
+  return false;
+for (auto &in_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 ..769cffae6d74
--- /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 ..8e85a47d315e
--- /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)
+ 

[gcc r13-8751] analyzer: fix deref-before-check false positives due to inlining [PR112790]

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

commit r13-8751-g994477c41049d45b60a4d6db7f624fe5c89860fe
Author: David Malcolm 
Date:   Thu May 9 13:09:29 2024 -0400

analyzer: fix deref-before-check false positives due to inlining [PR112790]

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 

Diff:
---
 gcc/analyzer/checker-event.cc  | 40 --
 gcc/analyzer/inlining-iterator.h   | 40 ++
 gcc/analyzer/sm-malloc.cc  | 10 ++
 .../gcc.dg/analyzer/deref-before-check-pr112790.c  | 27 +++
 4 files changed, 77 insertions(+), 40 deletions(-)

diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 3612df7bd1d3..3cb2fb9175cd 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 7d4798ce6ea5..76ba1dc3cf4a 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 74701375409d..64295cfb66e7 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

[gcc r13-8757] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]

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

commit r13-8757-g810d35a7e054bcbb5b66d2e5924428e445f5fba9
Author: David Malcolm 
Date:   Thu May 9 13:09:31 2024 -0400

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

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 

Diff:
---
 gcc/analyzer/call-summary.cc   | 12 +
 .../gcc.dg/analyzer/call-summaries-pr114473.c  | 31 ++
 2 files changed, 43 insertions(+)

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a18a1b1b40a7..836dcd4318d4 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 ..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 (&a);
+  bar (q);
+}


[gcc r13-8754] analyzer: fix skipping of debug stmts [PR113253]

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

commit r13-8754-g2c688f6afce4cbb414f5baab1199cd525f309fca
Author: David Malcolm 
Date:   Thu May 9 13:09:30 2024 -0400

analyzer: fix skipping of debug stmts [PR113253]

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 

Diff:
---
 gcc/analyzer/region-model.cc   |   5 +
 gcc/analyzer/state-purge.cc|   9 ++
 gcc/analyzer/supergraph.cc |   4 +
 .../gcc.dg/analyzer/deref-before-check-pr113253.c  | 154 +
 4 files changed, 172 insertions(+)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c98b09d5322e..7e42fcdfd551 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 3a73146d928b..31a207436f09 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,
  map.log ("used by stmt: %s", pp_formatted_text (&pp));
}
 
+ 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 a23ff15ece45..f07d68c60b8d 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 (&gsi))
{
  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 ..d9015accd6ab
--- /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,
+  P

[gcc r13-8760] Fix ICE in -fdiagnostics-generate-patch [PR112684]

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

commit r13-8760-g2a6f99aef7c8522471967b171180d9ba4136da90
Author: David Malcolm 
Date:   Thu May 9 13:09:32 2024 -0400

Fix ICE in -fdiagnostics-generate-patch [PR112684]

Backported from r14-8255-ge254d1224df306.

gcc/ChangeLog:
PR middle-end/112684
* toplev.cc (toplev::main): Don't ICE in
-fdiagnostics-generate-patch when exiting after options,
since no edit context will have been created.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/toplev.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 109c9d58cbd1..19391208eac2 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2292,10 +2292,8 @@ toplev::main (int argc, char **argv)
  emit some diagnostics here.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
-  if (flag_diagnostics_generate_patch)
+  if (global_dc->edit_context_ptr)
 {
-  gcc_assert (global_dc->edit_context_ptr);
-
   pretty_printer pp;
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   global_dc->edit_context_ptr->print_diff (&pp, true);


[gcc r13-8761] diagnostics: fix corrupt json/SARIF on stderr [PR114348]

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

commit r13-8761-gb7a2697733d19a093cbdd0e200ffce069a4bc812
Author: David Malcolm 
Date:   Thu May 9 13:09:33 2024 -0400

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

Various values of -fdiagnostics-format= request machine-readable output
on stderr, using JSON, but in various places we use fnotice to write
free-form text to stderr, such as "compilation terminated", leading to
corrupt JSON.

Fix by having fnotice skip the output for such cases.

Backported from r14-9554-g0bf99b1b7eda2f (using a variable rather
than a vfunc of class diagnostic_output_format, since the latter
was added in gcc 14)

gcc/ChangeLog:
PR middle-end/114348
* diagnostic.cc (output_format): New variable.
(fnotice): Bail out if the user requested one of the
machine-readable diagnostic output formats on stderr.
(diagnostic_output_format_init): Set output_format.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic.cc | 24 
 1 file changed, 24 insertions(+)

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


[gcc r15-526] analyzer: fix ICE seen with -fsanitize=undefined [PR114899]

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:1779e22150b917e28e959623c819ef943fab02df

commit r15-526-g1779e22150b917e28e959623c819ef943fab02df
Author: David Malcolm 
Date:   Wed May 15 18:40:56 2024 -0400

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

gcc/analyzer/ChangeLog:
PR analyzer/114899
* access-diagram.cc
(written_svalue_spatial_item::get_label_string): Bulletproof
against SSA_NAME_VAR being null.

gcc/testsuite/ChangeLog:
PR analyzer/114899
* c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/access-diagram.cc|  3 ++-
 .../analyzer/out-of-bounds-diagram-pr114899.c | 15 +++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 500480b68328..8d7461fe381d 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -1632,7 +1632,8 @@ protected:
 if (rep_tree)
   {
if (TREE_CODE (rep_tree) == SSA_NAME)
- rep_tree = SSA_NAME_VAR (rep_tree);
+ if (tree var = SSA_NAME_VAR (rep_tree))
+   rep_tree = var;
switch (TREE_CODE (rep_tree))
  {
  default:
diff --git 
a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c 
b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c
new file mode 100644
index ..14ba540d4ec2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-pr114899.c
@@ -0,0 +1,15 @@
+/* Verify we don't ICE generating out-of-bounds diagram.  */
+
+/* { dg-additional-options " -fsanitize=undefined 
-fdiagnostics-text-art-charset=unicode" } */
+
+int * a() {
+  int *b = (int *)__builtin_malloc(sizeof(int));
+  int *c = b - 1;
+  ++*c;
+  return b;
+}
+
+/* We don't care about the exact diagram, just that we don't ICE.  */
+
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */


[gcc r15-532] diagnostics: handle SGR codes in line_label::m_display_width

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

commit r15-532-ga7be993806a90a58397e9d5bc9b54160ac9f35db
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: handle SGR codes in line_label::m_display_width

gcc/ChangeLog:
* diagnostic-show-locus.cc: Define INCLUDE_VECTOR and include
"text-art/types.h".
(line_label::line_label): Drop "policy" argument.  Use
styled_string::calc_canvas_width when computing m_display_width,
as this skips SGR codes.
(layout::print_any_labels): Update for line_label ctor change.
(selftest::test_one_liner_labels_utf8): Update expected text to
reflect that the labels can fit on one line if we don't get
confused by SGR colorization codes.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-show-locus.cc | 28 +---
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index ceccc0b793d1..f42006cfe2a1 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
 #include "version.h"
@@ -31,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest.h"
 #include "selftest-diagnostic.h"
 #include "cpplib.h"
+#include "text-art/types.h"
 
 #ifdef HAVE_TERMIOS_H
 # include 
@@ -1923,14 +1925,18 @@ struct pod_label_text
 class line_label
 {
 public:
-  line_label (const cpp_char_column_policy &policy,
- int state_idx, int column,
+  line_label (int state_idx, int column,
  label_text text)
   : m_state_idx (state_idx), m_column (column),
 m_text (std::move (text)), m_label_line (0), m_has_vbar (true)
   {
-const int bytes = strlen (m_text.m_buffer);
-m_display_width = cpp_display_width (m_text.m_buffer, bytes, policy);
+/* Using styled_string rather than cpp_display_width here
+   lets us skip SGR formatting characters for color and URLs.
+   It doesn't handle tabs and unicode escaping, but we don't
+   expect to see either of those in labels.  */
+text_art::style_manager sm;
+text_art::styled_string str (sm, m_text.m_buffer);
+m_display_width = str.calc_canvas_width ();
   }
 
   /* Sorting is primarily by column, then by state index.  */
@@ -1990,7 +1996,7 @@ layout::print_any_labels (linenum_type row)
if (text.get () == NULL)
  continue;
 
-   labels.safe_push (line_label (m_policy, i, disp_col, std::move (text)));
+   labels.safe_push (line_label (i, disp_col, std::move (text)));
   }
   }
 
@@ -4382,9 +4388,9 @@ test_one_liner_labels_utf8 ()
   ASSERT_STREQ (" _foo = _bar._field;\n"
" ^    ~~~\n"
" |   ||\n"
-   " |   |label 2\xcf\x80\n"
-   " |   label 1\xcf\x80\n"
-   " label 0\xf0\x9f\x98\x82\n",
+   " label 0\xf0\x9f\x98\x82"
+   /* ... */ "   label 1\xcf\x80"
+   /* ...*/ " label 2\xcf\x80\n",
pp_formatted_text (dc.printer));
 }
 {
@@ -4395,9 +4401,9 @@ test_one_liner_labels_utf8 ()
(" <9f><98><82>_foo = 
<80>_bar.<9f><98><82>_field<80>;\n"
 " ^~~~    ~~\n"
 " |  ||\n"
-" |  |label 2\xcf\x80\n"
-" |  label 1\xcf\x80\n"
-" label 0\xf0\x9f\x98\x82\n",
+" label 0\xf0\x9f\x98\x82"
+/* ... */ "  label 1\xcf\x80"
+/* ..*/ " label 2\xcf\x80\n",
 pp_formatted_text (dc.printer));
 }
   }


[gcc r15-534] diagnostics: add warning emoji to events with VERB_danger

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

commit r15-534-g0b7ebe5427a4af0956e0aed5e7432b98559ca7b5
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: add warning emoji to events with VERB_danger

Tweak the printing of -fdiagnostics-path-format=inline-events so that
any event with diagnostic_event::VERB_danger gains a warning emoji,
provided that the text art theme enables emoji support.

VERB_danger is set by the analyzer on the last event in a path, and so
this emoji appears at the end of all analyzer execution paths
highlighting the location of the problem.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
output to include warning emoji.
* gcc.dg/analyzer/warning-emoji.c: New test.

gcc/ChangeLog:
* tree-diagnostic-path.cc: Include "text-art/theme.h".
(path_label::get_text): If the event has
diagnostic_event::VERB_danger, and the theme enables emojis, then
add a warning emoji between the event number and the event text.

Signed-off-by: David Malcolm 

Diff:
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c   |  2 +-
 gcc/testsuite/gcc.dg/analyzer/warning-emoji.c  | 29 +
 gcc/tree-diagnostic-path.cc| 30 +++---
 3 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
index 1c6125225ff2..7b4ecf0d6b0c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -29,7 +29,7 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
|   arr[10] = x;
|   ^~~
|   |
-   |   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
+   |   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
|
{ dg-end-multiline-output "" } */
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
new file mode 100644
index ..47e5fb0acf90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
@@ -0,0 +1,29 @@
+/* Verify that the final event in an analyzer path gets a "warning" emoji 
+   when -fdiagnostics-text-art-charset=emoji (and
+   -fdiagnostics-path-format=inline-events).  */
+
+/* { dg-additional-options "-fdiagnostics-show-line-numbers" } */
+/* { dg-additional-options "-fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=emoji" } */
+/* { dg-enable-nn-line-numbers "" } */
+
+void test (void *p)
+{
+  __builtin_free (p);
+  __builtin_free (p); /* { dg-warning "double-'free'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+   NN |   __builtin_free (p);
+  |   ^~
+  'test': events 1-2
+   NN |   __builtin_free (p);
+  |   ^~
+  |   |
+  |   (1) first 'free' here
+   NN |   __builtin_free (p);
+  |   ~~
+  |   |
+  |   (2) ⚠️  second 'free' here; first 'free' was at (1)
+   { dg-end-multiline-output "" } */
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 33389ef5d33e..bc90aaf321cc 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-event-id.h"
 #include "selftest.h"
 #include "selftest-diagnostic.h"
+#include "text-art/theme.h"
 
 /* Anonymous namespace for path-printing code.  */
 
@@ -60,13 +61,36 @@ class path_label : public range_label
 /* Get the description of the event, perhaps with colorization:
normally, we don't colorize within a range_label, but this
is special-cased for diagnostic paths.  */
-bool colorize = pp_show_color (global_dc->printer);
+const bool colorize = pp_show_color (global_dc->printer);
 label_text event_text (event.get_desc (colorize));
 gcc_assert (event_text.get ());
+
+const diagnostic_event::meaning meaning (event.get_meaning ());
+
 pretty_printer pp;
-pp_show_color (&pp) = pp_show_color (global_dc->printer);
+pp_show_color (&pp) = colorize;
 diagnostic_event_id_t event_id (event_idx);
-pp_printf (&pp, "%@ %s", &event_id, event_text.get ());
+
+pp_printf (&pp, "%@", &event_id);
+pp_space (&pp);
+
+if (meaning.m_verb == diagnostic_event::VERB_danger)
+  if (text_art::theme *theme = global_dc->get_diagram_theme ())
+   if (theme->emojis_p ())
+ {
+   pp_unicode_character (&pp, 0x26A0); /* U+26A0 WARNING SIGN.  */
+   /* Append U+F

[gcc r15-533] diagnostics: simplify output of purely intraprocedural execution paths

2024-05-15 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3cd267446755ab6b2c59936a718d34c8bc474ca5

commit r15-533-g3cd267446755ab6b2c59936a718d34c8bc474ca5
Author: David Malcolm 
Date:   Wed May 15 21:22:51 2024 -0400

diagnostics: simplify output of purely intraprocedural execution paths

Diagnostic path printing was added in r10-5901-g4bc1899b2e883f.  As of
that commit, with -fdiagnostics-path-format=inline-events (the default),
we print a vertical line to the left of the source line numbering,
visualizing the stack depth and interprocedural calls and returns as
indentation changes.

For cases where the events on a thread are purely interprocedural, this
line does nothing except take up space and complicate the output.

This patch adds logic to omit it for such cases, simpifying the output,
and, I believe, improving readability.

gcc/ChangeLog:
* diagnostic-path.h: Update leading comment to reflect
intraprocedural cases.  Fix typo in comment.
* doc/invoke.texi: Update intraprocedural example.

gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/allocation-size-multiline-1.c: Update
expected results for purely intraprocedural path.
* c-c++-common/analyzer/allocation-size-multiline-2.c: Likewise.
* c-c++-common/analyzer/allocation-size-multiline-3.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-0.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-1.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-2.c: Likewise.
* c-c++-common/analyzer/analyzer-verbosity-3.c: Likewise.
* c-c++-common/analyzer/malloc-macro-inline-events.c: Likewise.
Doing so for this file requires a rewrite since the paths
prefixing the "in expansion of macro" lines become the only thing
on their line and so are no longer pruned by multiline.exp logic
for pruning extra content on non-blank lines.
* c-c++-common/analyzer/malloc-paths-9-noexcept.c: Likewise.
* c-c++-common/analyzer/setjmp-2.c: Likewise.
* gcc.dg/analyzer/malloc-paths-9.c: Likewise.
* gcc.dg/analyzer/out-of-bounds-multiline-2.c: Likewise.
* gcc.dg/plugin/diagnostic-test-paths-2.c: Likewise.

gcc/ChangeLog:
* tree-diagnostic-path.cc (per_thread_summary::interprocedural_p):
New.
(thread_event_printer::print_swimlane_for_event_range): Don't
indent and print the stack depth line if this thread's events are
purely intraprocedural.
(selftest::test_intraprocedural_path): Update expected output.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-path.h  |  32 +-
 gcc/doc/invoke.texi|  30 +-
 .../analyzer/allocation-size-multiline-1.c |  68 +--
 .../analyzer/allocation-size-multiline-2.c |  72 +--
 .../analyzer/allocation-size-multiline-3.c |  48 +-
 .../c-c++-common/analyzer/analyzer-verbosity-0.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-1.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-2.c   |  40 +-
 .../c-c++-common/analyzer/analyzer-verbosity-3.c   |  40 +-
 .../analyzer/malloc-macro-inline-events.c  |  83 +--
 .../analyzer/malloc-paths-9-noexcept.c | 604 ++---
 gcc/testsuite/c-c++-common/analyzer/setjmp-2.c | 140 +++--
 gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c | 302 +--
 .../gcc.dg/analyzer/out-of-bounds-multiline-2.c|  21 +-
 .../gcc.dg/plugin/diagnostic-test-paths-2.c|  30 +-
 gcc/tree-diagnostic-path.cc|  86 ++-
 16 files changed, 799 insertions(+), 877 deletions(-)

diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index fb7abe88ed32..696991c6d736 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -41,22 +41,20 @@ class sarif_object;
 29 | PyList_Append(list, item);
| ^
'demo': events 1-3
-  |
-  |   25 |   list = PyList_New(0);
-  |  |  ^
-  |  |  |
-  |  |  (1) when 'PyList_New' fails, returning NULL
-  |   26 |
-  |   27 |   for (i = 0; i < count; i++) {
-  |  |   ~~~
-  |  |   |
-  |  |   (2) when 'i < count'
-  |   28 | item = PyLong_FromLong(random());
-  |   29 | PyList_Append(list, item);
-  |  | ~
-  |  | |
-  |  | (3) when calling 'PyList_Append', passing NULL from (1) 
as argument 1
-  |
+25 |   list = PyList_New(0);
+   |  ^
+   |  |
+   |  (1) when 'PyList_New' fails, returning NULL
+ 

[gcc r15-535] diagnostics: use unicode art for interprocedural depth

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

commit r15-535-ge656656e711949ef42a7e284f7cf81ca56f37374
Author: David Malcolm 
Date:   Wed May 15 21:22:52 2024 -0400

diagnostics: use unicode art for interprocedural depth

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
output to use unicode for depth indication.
* gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c: Likewise.

gcc/ChangeLog:
* text-art/theme.cc (ascii_theme::get_cppchar): Add
cell_kind::INTERPROCEDURAL_*.
(unicode_theme::get_cppchar): Likewise.
* text-art/theme.h (theme::cell_kind): Likewise.
* tree-diagnostic-path.cc:
(thread_event_printer::print_swimlane_for_event_range): Use the
above to get characters for indicating interprocedural stack
depth activity, falling back to ascii.
(selftest::test_interprocedural_path_1): Test with both ascii
and unicode themes.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c   |  26 +-
 .../analyzer/out-of-bounds-diagram-1-unicode.c |  26 +-
 gcc/text-art/theme.cc  |  30 ++
 gcc/text-art/theme.h   |  10 +
 gcc/tree-diagnostic-path.cc| 381 ++---
 5 files changed, 331 insertions(+), 142 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
index 7b4ecf0d6b0c..8d22e4109628 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
arr[10] = x;
^~~
   event 1 (depth 0)
-|
-| int32_t arr[10];
-| ^~~
-| |
-| (1) capacity: 40 bytes
-|
-+--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-   |
-   |   arr[10] = x;
-   |   ^~~
-   |   |
-   |   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
-   |
+│
+│ int32_t arr[10];
+│ ^~~
+│ |
+│ (1) capacity: 40 bytes
+│
+└──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+   │
+   │   arr[10] = x;
+   │   ^~~
+   │   |
+   │   (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
+   │
{ dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
index 71f66ff87c9e..58c4a7bedf34 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
arr[10] = x;
^~~
   event 1 (depth 0)
-|
-| int32_t arr[10];
-| ^~~
-| |
-| (1) capacity: 40 bytes
-|
-+--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-   |
-   |   arr[10] = x;
-   |   ^~~
-   |   |
-   |   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
-   |
+│
+│ int32_t arr[10];
+│ ^~~
+│ |
+│ (1) capacity: 40 bytes
+│
+└──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+   │
+   │   arr[10] = x;
+   │   ^~~
+   │   |
+   │   (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
+   │
{ dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/text-art/theme.cc b/gcc/text-art/theme.cc
index 4ac0cae92e26..cba4c585c469 100644
--- a/gcc/text-art/theme.cc
+++ b/gcc/text-art/theme.cc
@@ -125,6 +125,21 @@ ascii_theme::get_cppchar (enum cell_kind kind) const
 case cell_kind::Y_ARROW_UP_TAIL:
 case cell_kind::Y_ARROW_DOWN_TAIL:
   return '|';
+
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT:
+  return '+';
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE:
+  return '-';
+case cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT:
+  return '>';
+case cell_kind::INTERPROCEDURAL_DEPTH_MARKER:
+  return '|';
+case cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT:
+  return '<';
+case cell_kind::INTERPROC

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

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

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

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

This patch adds some ability for links between labelled ranges when
quoting the user's source code, and uses this to add links between
events when printing diagnostic_paths, chopping them up further into
event ranges that can be printed together.
It adds links to the various "from..." - "...to" events in the
analyzer.

For example, previously we emitted this for
c-c++-common/analyzer/infinite-loop-linked-list.c's
while_loop_missing_next':

infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] 
[-Wanalyzer-infinite-loop]
   30 |   while (n)
  |  ^
  'while_loop_missing_next': events 1-5
   30 |   while (n)
  |  ^
  |  |
  |  (1) infinite loop here
  |  (2) when 'n' is non-NULL: always following 'true' branch...
  |  (5) ...to here
   31 | {
   32 |   sum += n->val;
  |   ~
  |   |   |
  |   |   (3) ...to here
  |   (4) looping back...

whereas with the patch we now emit:

infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] 
[-Wanalyzer-infinite-loop]
   30 |   while (n)
  |  ^
  'while_loop_missing_next': events 1-3
   30 |   while (n)
  |  ^
  |  |
  |  (1) infinite loop here
  |  (2) when 'n' is non-NULL: always following 'true' 
branch... ->-+
  | 
|
  | 
|
  
|++
   31 ||{
   32 ||  sum += n->val;
  || ~~
  ||  |
  |+->(3) ...to here
  'while_loop_missing_next': event 4
   32 |   sum += n->val;
  |   ^
  |   |
  |   (4) looping back... ->-+
  |  |
  'while_loop_missing_next': event 5
  |  |
  |+-+
   30 ||  while (n)
  || ^
  || |
  |+>(5) ...to here

which I believe is easier to understand.

The patch also implements the use of unicode characters and colorization
for the lines (not shown in the above example).

There is a new option -fno-diagnostics-show-event-links for getting
back the old behavior (added to -fdiagnostics-plain-output).

gcc/analyzer/ChangeLog:
* checker-event.h (checker_event::connect_to_next_event_p):
Implement new diagnostic_event::connect_to_next_event_p vfunc.
(start_cfg_edge_event::connect_to_next_event_p): Likewise.
(start_consolidated_cfg_edges_event::connect_to_next_event_p):
Likewise.
* infinite-loop.cc (class looping_back_event): New subclass.
(infinite_loop_diagnostic::add_final_event): Use it.

gcc/ChangeLog:
* common.opt (fdiagnostics-show-event-links): New option.
* diagnostic-label-effects.h: New file.
* diagnostic-path.h (diagnostic_event::connect_to_next_event_p):
New pure virtual function.
(simple_diagnostic_event::connect_to_next_event_p): Implement it.
(simple_diagnostic_event::connect_to_next_event): New.
(simple_diagnostic_event::m_connected_to_next_event): New field.
(simple_diagnostic_path::connect_to_next_event): New decl.
* diagnostic-show-locus.cc: Include "text-art/theme.h" and
"diagnostic-label-effects.h".
(colorizer::set_cfg_edge): New.
(layout::m_fallback_theme): New field.
(layout::m_theme): New field.
(layout::m_effect_info): New field.
(layout::m_link_lhs_state): New enum and field.
(layout::m_link_rhs_column): New field.
(layout_range::has_in_edge): New.
(layout_range::has_out_edge): New.
(layout::layout): Add "effect_info" optional param.  Initialize
m_theme, m_link_lhs_state, and m_link_rhs_column.
(layout::maybe_add_location_range): Remove stray "FIXME" from
leading comment.
(layout::print_source_line): Replace space after margin with a
call to print_leftmost_column.
(layout::print_leftmost_column): New.
(layout::start_annotatio

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

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

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

Regenerate common.opt.urls

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

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

Signed-off-by: David Malcolm 

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

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


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

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

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

json.h: fix typo in comment

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

Signed-off-by: David Malcolm 

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

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


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

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

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

pretty-print: fixes to selftests

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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


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

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

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

testsuite: add event IDs to multithreaded event plugin test

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

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

  m_output_format->on_report_diagnostic (*diagnostic, orig_diag_kind);

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

testsuite: generalize support for Python tests for SARIF output

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

Use std::unique_ptr for optinfo_item

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

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

pretty-print: move class chunk_info into its own header

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

pretty-print: reimplement pp_format with a new struct pp_token

The following patch rewrites the internals of pp_format.

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

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

This led to various special-casing for handling:

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

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

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

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

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

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

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

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

No functional change intended.

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

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

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

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

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

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

pretty-print: add selftest of pp_format's stack

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

Signed-off-by: David Malcolm 

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

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


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

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

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

pretty-print: naming cleanups

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

No functional change intended.

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

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

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

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

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

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

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

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

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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

analyzer: fix "unused variable 'summary_cast_reg'" warning

I missed this in r15-1108-g70f26314b62e2d.

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: replace option_hooks with a diagnostic_option_manager class

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: rename dc.printer to m_printer [PR116613]

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

No functional change intended.

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

[gcc r15-3556] diagnostics: introduce struct diagnostic_option_id

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

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

diagnostics: introduce struct diagnostic_option_id

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Tested with Python 3.8 with check_jsonschema 0.28.6

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: eliminate various implicit uses of global_dc

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

No functional change intended.

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: introduce diagnostic-global-context.cc

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

analyzer: handle  at -O0 [PR115724]

At -O0, glibc's:

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

becomes just:

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

gcc-cvs@gcc.gnu.org

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

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

analyzer: convert sm_context * to sm_context &

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

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

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

For example, consider:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

json: add array::append_string

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

json: add dump overload for easier debugging

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

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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


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

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

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

diagnostics: SARIF output: add sarif_object subclasses throughout

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: SARIF output: use std::unique_ptr throughout

No functional change intended.

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: JSON output: use std::unique_ptr throughout

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

"rendered": {"text":

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

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

For example, given this textual output:

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: add selftests for SARIF output

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

diagnostics: SARIF output: tweak output for UNKNOWN_LOCATION

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

Signed-off-by: David Malcolm 

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

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

[gcc r14-9526] analyzer: support null operands in remove_ssa_names

2024-03-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:3c2827d75ea8fbf7b84bd69e8d10dc239e5daffe

commit r14-9526-g3c2827d75ea8fbf7b84bd69e8d10dc239e5daffe
Author: David Malcolm 
Date:   Mon Mar 18 18:44:32 2024 -0400

analyzer: support null operands in remove_ssa_names

gcc/analyzer/ChangeLog:
* access-diagram.cc (remove_ssa_names): Support operands being
NULL_TREE, such as e.g. for COMPONENT_REF's operand 2.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/access-diagram.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 2836308c019..a9c5c899950 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -311,7 +311,8 @@ remove_ssa_names (tree expr)
 return SSA_NAME_VAR (expr);
   tree t = copy_node (expr);
   for (int i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
-TREE_OPERAND (t, i) = remove_ssa_names (TREE_OPERAND (expr, i));
+if (TREE_OPERAND (expr, i))
+  TREE_OPERAND (t, i) = remove_ssa_names (TREE_OPERAND (expr, i));
   return t;
 }


[gcc r14-9527] analyzer: fix ICEs due to sloppy types in bounds-checking [PR110902, PR110928, PR111305, PR111441]

2024-03-18 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:1579394c9ecf3d1f678daa54b835c7fc3b76fb6d

commit r14-9527-g1579394c9ecf3d1f678daa54b835c7fc3b76fb6d
Author: David Malcolm 
Date:   Mon Mar 18 18:44:34 2024 -0400

analyzer: fix ICEs due to sloppy types in bounds-checking 
[PR110902,PR110928,PR111305,PR111441]

Various analyzer ICEs in our bugzilla relate to sloppy use of types
within bounds-checking.

The bounds-checking code works by comparing symbolic *bit* offsets, and
we don't have a good user-facing type that can represent such an offset
(ptrdiff_type_node is for *byte* offsets).

ana::svalue doesn't enforce valid combinations of types for things like
binary operations.  When I added the access diagrams for GCC 14, this
could lead to attempts to generate trees for such svalues, leading to
trees with invalid combinations of types (e.g. PLUS_EXPR or MULT_EXPR of
incompatible types), leading to ICEs inside the tree folding logic.

I tried two approaches to fixing this.

My first approach was to fix the type-handling throughout the
bounds-checking code to use correct types, using size_type_node for
sizes, ptrdiff_type_node for byte offsets, and trying ptrdiff_type_node
for bit offsets.  I implemented this, and it fixed the crashes, but
unfortunately it led to:
(a) numerous false negatives from the bounds-checking code, due to it
becoming unable to be sure that the accessed offset was beyond the valid
bounds, due to the expressions involved gaining complicated sets of
nested casts.
(b) ugly access diagrams full of nested casts (for capacities, gap
measurements, etc)

So my second approach, implemented in this patch, is to accept that we
don't have a tree type for representing bit offsets.  The patch
represents bit offsets using "typeless" symbolic values i.e. ones for
which get_type () is NULL_TREE, and implements enough support for basic
arithemetic as if these are mathematical integers (albeit ones for which
concrete values within an expression must fit within a signed wide int).
Such values can't be converted to tree, so the patch avoids such
conversions, instead implementing a new svalue::maybe_print_for_user for
printing them to a pretty_printer.  The patch uses ptrdiff_type_node for
byte offsets.

Doing so fixes the crashes, whilst appearing to preserve the behavior of
-Wanalyzer-out-of-bounds in my testing.

gcc/analyzer/ChangeLog:
PR analyzer/110902
PR analyzer/110928
PR analyzer/111305
PR analyzer/111441
* access-diagram.cc: Include "analyzer/analyzer-selftests.h".
(get_access_size_str): Reimplement for conversion of
implmementation of bit_size_expr from tree to const svalue &.  Use
svalue::maybe_print_for_user rather than tree printing routines.
(remove_ssa_names): Make non-static.
(bit_size_expr::get_formatted_str): Rename to...
(bit_size_expr::maybe_get_formatted_str): ...this, adding "model"
param and converting return type to a unique_ptr.  Update for
conversion of implementation of bit_size_expr from tree to
const svalue &.  Use svalue::maybe_print_for_user rather than tree
printing routines.
(bit_size_expr::print): Rename to...
(bit_size_expr::maybe_print_for_user): ...this, adding "model"
param and converting return type to bool.  Update for
conversion of implementation of bit_size_expr from tree to
const svalue &.  Use svalue::maybe_print_for_user rather than tree
printing routines.
(bit_size_expr::maybe_get_as_bytes): Add "mgr" param and convert
return type from tree to const svalue *; reimplement.
(access_range::access_range): Call strip_types when on region_offset
intializations.
(access_range::get_size): Update for conversion of implementation
of bit_size_expr from tree to const svalue &.
(access_operation::get_valid_bits): Pass manager to access_range
ctor.
(access_operation::maybe_get_invalid_before_bits): Likewise.
(access_operation::maybe_get_invalid_after_bits): Likewise.
(boundaries::add): Likewise.
(bit_to_table_map::populate): Add "mgr" param and pass it to
access_range ctor.
(access_diagram_impl::access_diagram_impl): Pass manager to
bit_to_table_map::populate.
(access_diagram_impl::maybe_add_gap): Use svalue rather than tree
for symbolic bit offsets.  Port to new bit_size_expr
representation.
(access_diagram_impl::add_valid_vs_invalid_ruler): Port to new
bit_size_expr representation.
(selftest::assert_eq_typeless_integer): New.

[gcc r14-9544] analyzer: fixes to __atomic_{exchange, load, store} [PR114286]

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

commit r14-9544-gc7a774edbf802d79b95871ede5b80f6e9adf8e88
Author: David Malcolm 
Date:   Tue Mar 19 09:06:45 2024 -0400

analyzer: fixes to __atomic_{exchange,load,store} [PR114286]

In r14-1497-gef768035ae8090 I added some support to the analyzer for
__atomic_ builtins (enough to fix false positives I was seeing in
my integration tests).

Unfortunately I messed up the implementation of
__atomic_{exchange,load,store}, leading to ICEs seen in
PR analyzer/114286.

Fixed thusly, fixing the ICEs.  Given that we're in stage 4, the patch
doesn't add support for any of the various __atomic_compare_exchange
builtins, so that these continue to fall back to the analyzer's
"anything could happen" handling of unknown functions.

Signed-off-by: David Malcolm 

gcc/analyzer/ChangeLog:
PR analyzer/114286
* kf.cc (class kf_atomic_exchange): Reimplement based on signature
seen in gimple, rather than user-facing signature.
(class kf_atomic_load): Likewise.
(class kf_atomic_store): New.
(register_atomic_builtins): Register kf_atomic_store.

gcc/testsuite/ChangeLog:
PR analyzer/114286
* c-c++-common/analyzer/atomic-builtins-pr114286.c: New test.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/kf.cc | 135 -
 .../analyzer/atomic-builtins-pr114286.c|  48 
 2 files changed, 150 insertions(+), 33 deletions(-)

diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index ed48ffbcba2..d197ccbd0f0 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -116,39 +116,54 @@ kf_alloca::impl_call_pre (const call_details &cd) const
   cd.maybe_set_lhs (ptr_sval);
 }
 
-/* Handler for:
-   void __atomic_exchange (type *ptr, type *val, type *ret, int memorder).  */
+/* Handler for __atomic_exchange.
+   Although the user-facing documentation specifies it as having this
+   signature:
+ void __atomic_exchange (type *ptr, type *val, type *ret, int memorder)
+
+   by the time the C/C++ frontends have acted on it, any calls that
+   can't be mapped to a _N variation end up with this signature:
+
+ void
+ __atomic_exchange (size_t sz, void *ptr, void *val, void *ret,
+   int memorder)
+
+   as seen in the gimple seen by the analyzer, and as specified
+   in sync-builtins.def.  */
 
 class kf_atomic_exchange : public internal_known_function
 {
 public:
   /* This is effectively:
-   *RET = *PTR;
-   *PTR = *VAL;
+   tmpA = *PTR;
+   tmpB = *VAL;
+   *PTR = tmpB;
+   *RET = tmpA;
   */
   void impl_call_pre (const call_details &cd) const final override
   {
-const svalue *ptr_ptr_sval = cd.get_arg_svalue (0);
-tree ptr_ptr_tree = cd.get_arg_tree (0);
-const svalue *val_ptr_sval = cd.get_arg_svalue (1);
-tree val_ptr_tree = cd.get_arg_tree (1);
-const svalue *ret_ptr_sval = cd.get_arg_svalue (2);
-tree ret_ptr_tree = cd.get_arg_tree (2);
+const svalue *num_bytes_sval = cd.get_arg_svalue (0);
+const svalue *ptr_sval = cd.get_arg_svalue (1);
+tree ptr_tree = cd.get_arg_tree (1);
+const svalue *val_sval = cd.get_arg_svalue (2);
+tree val_tree = cd.get_arg_tree (2);
+const svalue *ret_sval = cd.get_arg_svalue (3);
+tree ret_tree = cd.get_arg_tree (3);
 /* Ignore the memorder param.  */
 
 region_model *model = cd.get_model ();
 region_model_context *ctxt = cd.get_ctxt ();
 
-const region *val_region
-  = model->deref_rvalue (val_ptr_sval, val_ptr_tree, ctxt);
-const svalue *star_val_sval = model->get_store_value (val_region, ctxt);
-const region *ptr_region
-  = model->deref_rvalue (ptr_ptr_sval, ptr_ptr_tree, ctxt);
-const svalue *star_ptr_sval = model->get_store_value (ptr_region, ctxt);
-const region *ret_region
-  = model->deref_rvalue (ret_ptr_sval, ret_ptr_tree, ctxt);
-model->set_value (ptr_region, star_val_sval, ctxt);
-model->set_value (ret_region, star_ptr_sval, ctxt);
+const region *ptr_reg = model->deref_rvalue (ptr_sval, ptr_tree, ctxt);
+const region *val_reg = model->deref_rvalue (val_sval, val_tree, ctxt);
+const region *ret_reg = model->deref_rvalue (ret_sval, ret_tree, ctxt);
+
+const svalue *tmp_a_sval
+  = model->read_bytes (ptr_reg, ptr_tree, num_bytes_sval, ctxt);
+const svalue *tmp_b_sval
+  = model->read_bytes (val_reg, val_tree, num_bytes_sval, ctxt);
+model->write_bytes (ptr_reg, num_bytes_sval, tmp_b_sval, ctxt);
+model->write_bytes (ret_reg, num_bytes_sval, tmp_a_sval, ctxt);
   }
 };
 
@@ -265,32 +280,85 @@ private:
   enum tree_code m_op;
 };
 
-/* Handler for:
-   void __atomic_load (type *ptr, type *ret, int memorder).  */
+/* Handler for __atomic_load.
+   Although the user-facing documentation specifies 

[gcc r14-9554] diagnostics: fix corrupt json/SARIF on stderr [PR114348]

2024-03-19 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:0bf99b1b7eda2f4c34b9f56b895980ea1c261765

commit r14-9554-g0bf99b1b7eda2f4c34b9f56b895980ea1c261765
Author: David Malcolm 
Date:   Tue Mar 19 13:57:35 2024 -0400

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

Various values of -fdiagnostics-format= request machine-readable output
on stderr, using JSON, but in various places we use fnotice to write
free-form text to stderr, such as "compilation terminated", leading to
corrupt JSON.

Fix by having fnotice skip the output for such cases.

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 

Diff:
---
 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 &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 &diagram) = 0;
+  virtual bool machine_readable_stderr_p () const = 0;
 
 protected:
   diagnostic_output_format (diagnostic_context &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 &diagram) override;
+  bool machine_readable_stderr_p () const final override
+  {
+return false;
+  }
 };
 
 /* A stack of sets of classifications: e

[gcc r14-9555] analyzer: fix ICE due to corrupt MEM_REFs [PR113505]

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

commit r14-9555-gc87f1f3d660f4103c91c72a4d3e1d19ff2858671
Author: Jakub Jelinek 
Date:   Tue Mar 19 16:06:13 2024 -0400

analyzer: fix ICE due to corrupt MEM_REFs [PR113505]

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.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/region-model.cc | 16 ++--
 gcc/testsuite/gcc.dg/analyzer/pr113505.c | 24 
 2 files changed, 34 insertions(+), 6 deletions(-)

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);
+}
+}


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

2024-03-20 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:9093f275e0a3430e4517e782e7f5419d403113f7

commit r14-9586-g9093f275e0a3430e4517e782e7f5419d403113f7
Author: David Malcolm 
Date:   Wed Mar 20 18:33:11 2024 -0400

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

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 

Diff:
---
 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(+)

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 &point)
+  {
+const supernode *snode = point.get_supernode ();
+if (!snode)
+  return false;
+for (auto &in_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->val;
+  return total;
+}
+
+#define FOR_EACH

[gcc r14-9600] analyzer: fix ignored constraints involving casts [PR113619]

2024-03-21 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:7a5a4a4467b2e18ff4fe24f565e120280d3e6ba7

commit r14-9600-g7a5a4a4467b2e18ff4fe24f565e120280d3e6ba7
Author: David Malcolm 
Date:   Thu Mar 21 17:48:38 2024 -0400

analyzer: fix ignored constraints involving casts [PR113619]

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 

Diff:
---
 gcc/analyzer/region-model.cc   | 24 --
 .../c-c++-common/analyzer/taint-divisor-pr113619.c | 29 ++
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c3a4ec7bcfc..902b887fc07 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 000..15c881247ce
--- /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(&l);
+  if (err)
+return err;
+  return err;
+}


[gcc r14-9624] analyzer: add SARIF property bags to taint diagnostics

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

commit r14-9624-gd475a4571ef310a727a1023856b070f195910140
Author: David Malcolm 
Date:   Fri Mar 22 10:57:20 2024 -0400

analyzer: add SARIF property bags to taint diagnostics

Another followup to r14-6057-g12b67d1e13b3cf to make it easier to debug
the analyzer.

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 

Diff:
---
 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 bbf683f82ef..c873c9ebd33 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 &result_obj)
+const override
+  {
+sarif_property_bag &props = 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 &m_sm;
   tree m_arg;
@@ -315,8 +343,10 @@ class tainted_offset : public taint_diagnostic
 {
 public:
   tainted_offset (const taint_state_machine &sm, 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 &result_obj)
+const final override
+  {
+taint_diagnostic::maybe_add_sarif_properties (result_obj);
+sarif_property_bag &props = 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, &b))
  {
tree arg = get_representative_tree (offset);
-   ctxt->warn (make_unique (taint_sm, arg, b));
+   ctxt->warn (make_unique (taint_sm, arg, b,
+offset));
  }
  }
  break;


[gcc r14-9625] analyzer: look through casts in taint sanitization [PR112974, PR112975]

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

commit r14-9625-gc6cf5789135236c5639075c8f235e7dd461b6ff6
Author: David Malcolm 
Date:   Fri Mar 22 10:57:25 2024 -0400

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

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.

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 

Diff:
---
 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(+)

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index c873c9ebd33..1d1e208fdf4 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 c26dda1f324..933f9a5850b 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 000..1af505326c7
--- /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(&tpmi_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 = &sst_inst->power_domain_info[i];
+if (pd_info->sst_base)
+  tpmi_inst.val

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

2024-03-23 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:80a0cb37456c49dbc25cca7cd554f78bc504373e

commit r14-9646-g80a0cb37456c49dbc25cca7cd554f78bc504373e
Author: David Malcolm 
Date:   Sat Mar 23 09:52:38 2024 -0400

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

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 

Diff:
---
 gcc/analyzer/engine.cc |  7 +++
 gcc/analyzer/kf.cc | 22 ++
 .../analyzer/deref-before-check-pr114408.c | 22 ++
 .../c-c++-common/ubsan/analyzer-ice-pr114408.c |  9 +
 4 files changed, 60 insertions(+)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index ad310b4d873..e0dc0e66e88 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 d197ccbd0f0..6931f07bd75 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -2198,6 +2198,27 @@ register_atomic_builtins (known_function_manager &kfm)
   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 &cd) const final override
+  {
+if (cd.get_ctxt ())
+  cd.get_ctxt ()->terminate_path ();
+  }
+};
+
+static void
+register_sanitizer_builtins (known_function_manager &kfm)
+{
+  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,
 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 000..d55720271d0
--- /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 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);
+}


[gcc r14-9697] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]

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

commit r14-9697-gfdd59818e2abf6043f4d45aeb157e95956c71088
Author: David Malcolm 
Date:   Wed Mar 27 18:26:51 2024 -0400

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

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 

Diff:
---
 gcc/analyzer/call-summary.cc   | 12 +
 .../gcc.dg/analyzer/call-summaries-pr114473.c  | 31 ++
 2 files changed, 43 insertions(+)

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a569bb94cec..c2c9c71f79b 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 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 (&a);
+  bar (q);
+}


[gcc r14-9762] analyzer: prevent ICEs with null types

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

commit r14-9762-ge945d322fcbc68f91388b1d1297bdf6a6c6fcbaa
Author: David Malcolm 
Date:   Tue Apr 2 17:42:16 2024 -0400

analyzer: prevent ICEs with null types

Fixes some ICEs seen analyzing the Linux kernel.

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 

Diff:
---
 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 4feb349c914..f155eeb87c0 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 902b887fc07..98f287145c6 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 
&edge,
  && 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;


[gcc r14-9817] analyzer: respect GCC_COLORS in out-of-bounds diagrams [PR114588]

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

commit r14-9817-g4b02dd48f531ea88587edd2b75b6e5243b4389e8
Author: David Malcolm 
Date:   Fri Apr 5 14:49:53 2024 -0400

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

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 

Diff:
---
 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 4cb6570e90b..85e1049bb89 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 4859f36da6a..f01a0fc2e37 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 e2edf7a6c13..1006510fc6a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5244,7 +5244,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,
@@ -5327,6 +5327,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 e74efe23014..5c58d432cf4 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 02de2e86122..2b9f8b387c7 100644
--- a/gcc

[gcc r14-9896] analyzer, testuite: comment fixes

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

commit r14-9896-g082374f6570a311b0ef95cdf712dbc6eb1e7cd17
Author: David Malcolm 
Date:   Wed Apr 10 16:43:27 2024 -0400

analyzer, testuite: comment fixes

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

Signed-off-by: David Malcolm 

Diff:
---
 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 75aef53d348..d6695d49411 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" } */
 }


[gcc r14-9897] analyzer: fixes to internal docs

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

commit r14-9897-g7f6599a201be2a3f7d1d799087e4ba283ec0bee8
Author: David Malcolm 
Date:   Wed Apr 10 16:43:28 2024 -0400

analyzer: fixes to internal docs

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

Signed-off-by: David Malcolm 

Diff:
---
 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 8eb40272cb7..b53096e7b7d 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


[gcc r14-9895] testsuite: add some missing -fanalyzer to plugin tests

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

commit r14-9895-gd09d70cdb2a4bc45825fc887047ef4a20de590c6
Author: David Malcolm 
Date:   Wed Apr 10 16:43:27 2024 -0400

testsuite: add some missing -fanalyzer to plugin tests

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 

Diff:
---
 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 a1415f38aa6..1acedc2e2ce 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 51526b831c0..9ad05ff670a 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 3d11a75073c..688d014956e 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 d035266b16a..7e597037ec2 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 5270e22f1a3..9189cdb2c37 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 b8268fa4a82..d10ce28b40e 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 }

[gcc r14-9902] analyzer: fix ICE on negative values for size_t [PR114472]

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

commit r14-9902-g4a94551d7eaaf7a75c5195fc0bf4af94185a04c7
Author: David Malcolm 
Date:   Wed Apr 10 16:43:30 2024 -0400

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

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

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 

Diff:
---
 gcc/analyzer/access-diagram.cc   |  4 
 gcc/analyzer/region.cc   |  2 +-
 gcc/analyzer/store.cc| 20 
 .../c-c++-common/analyzer/out-of-bounds-pr114472.c   | 17 +
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index 85e1049bb89..500480b6832 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 &sm,
   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 &sm,
   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 705816b6245..7d79b45563f 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 e85a19647f7..a36de13c174 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -290,7 +290,10 @@ bit_range::intersects_p (const bit_range &other,
   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,
 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 &other,
   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 fal

[gcc r14-9898] analyzer: show size in SARIF property bag for -Wanalyzer-tainted-allocation-size

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

commit r14-9898-g115d5c6b009456e7e817dc5f1aeaea8d38929c93
Author: David Malcolm 
Date:   Wed Apr 10 16:43:28 2024 -0400

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

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 

Diff:
---
 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 1d1e208fdf4..a9c6d4db43f 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 &sm, 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 &result_obj)
+const final override
+  {
+taint_diagnostic::maybe_add_sarif_properties (result_obj);
+sarif_property_bag &props = 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));
 }
 }


[gcc r14-9899] analyzer: add SARIF property bags to -Wanalyzer-overlapping-buffers

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

commit r14-9899-g7a49d5dc0ef345fb2cb19a242272c973ead220e7
Author: David Malcolm 
Date:   Wed Apr 10 16:43:28 2024 -0400

analyzer: add SARIF property bags to -Wanalyzer-overlapping-buffers

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 

Diff:
---
 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 5b145a2ce63..ca47953f146 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 &byte_range_a,
+  const symbolic_byte_range &byte_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 &result_obj)
+const final override
+  {
+sarif_property_bag &props = 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 ffdd0d4c572..659ada7609d 100644
--- a/gcc/analyzer/ranges.cc
+++ b/gcc/analyzer/ranges.cc
@@ -103,6 +103,12 @@ symbolic_byte_offset::dump (bool simple) const
   pp_flush (&pp);
 }
 
+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 &mgr) const
   pp_flush (&pp);
 }
 
+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 92d963b7a2b..aca4554bde6 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 &other) const
   {
return m_num_bytes_sval == other.m_num_bytes_sval;
@@ -70,6 +72,8 @@ public:
   region_model_manager &mgr) const;
   void dump (bool, region_model_manager &mgr) const;
 
+  json::value *to_json () const;
+
   bool empty_p () const;
 
   symbolic_byte_offset get_start_byte_offset () const


[gcc r14-9900] analyzer: add SARIF property bag to -Wanalyzer-infinite-recursion

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

commit r14-9900-g960e07d73a5295adf059053907bcb395115606d2
Author: David Malcolm 
Date:   Wed Apr 10 16:43:29 2024 -0400

analyzer: add SARIF property bag to -Wanalyzer-infinite-recursion

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

Signed-off-by: David Malcolm 

Diff:
---
 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 112e4bd08f2..65f136ddad6 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 &result_obj)
+const final override
+  {
+sarif_property_bag &props = 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.  */


[gcc r14-9901] analyzer: add SARIF property bag to -Wanalyzer-infinite-loop

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

commit r14-9901-g107b0e63be023c11017aa53625a6557950df4d99
Author: David Malcolm 
Date:   Wed Apr 10 16:43:29 2024 -0400

analyzer: add SARIF property bag to -Wanalyzer-infinite-loop

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 

Diff:
---
 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 296489b1146..e277a8384a0 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 &m_enode;
   location_t m_loc;
   std::vector m_eedge_vec;
@@ -297,6 +310,15 @@ public:
   }
   }
 
+  void maybe_add_sarif_properties (sarif_object &result_obj)
+const final override
+  {
+sarif_property_bag &props = 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;
 };


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

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

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

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

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

For example, consider:

include-chain-1.c:

  #include "include-chain-1.h"

include-chain-1.h:

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

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

include-chain-1-1.h:

  int p;
  int q;

include-chain-1-1.h:

  char p;
  char q;

GCC's textual output emits:

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

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

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

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

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

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

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

effectively capturing the inclusion digraph in SARIF form:

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

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

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

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

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

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

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

diagnostics: SARIF output: tweak ASCII art in comment

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 5900b9ea9b75..2232883281bf 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1302,6 +1302,8 @@ sarif_builder::sarif_builder (diagnostic_context &context,
   m_tabstop (context.m_tabstop),
   m_formatted (formatted)
 {
+  gcc_assert (m_line_maps);
+
   /* Mark MAIN_INPUT_FILENAME_ as the artifact that the tool was
  instructed to scan.
  Only quote the contents if it gets referenced by physical locations,
@@ -2988,13 +2990,15 @@ diagnostic_output_format_init_sarif (diagnostic_context 
&context)
 
 void
 diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
+   const line_maps *line_maps,
const char *main_input_filename_,
bool formatted)
 {
+  gcc_assert (line_maps);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_stream_output_format (context,
-line_table,
+line_maps,
 main_input_filename_,
 formatted,
 stderr));
@@ -3005,14 +3009,16 @@ diagnostic_output_format_init_sarif_stderr 
(diagnostic_context &context,
 
 void
 diagnostic_output_format_init_sarif_file (diagnostic_context &context,
+ const line_maps *line_maps,
  const char *main_input_filename_,
  bool formatted,
  const char *base_file_name)
 {
+  gcc_assert (line_maps);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_file_output_format (context,
-  line_table,
+  line_maps,
   main_input_filename_,
   formatted,
   base_file_name));
@@ -3022,14 +3028,16 @@ diagnostic_output_format_init_sarif_file 
(diagnostic_context &context,
 
 void
 diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
+   const line_maps *line_maps,
const char *main_input_filename_,
bool formatted,
FILE *stream)
 {
+  gcc_assert (line_maps);
   diagnostic_output_format_init_sarif (context);
   context.set_output_format
 (new sarif_stream_output_format (context,
-line_table,
+line_maps,
 main_input_filename_,
 formatted,
 stream));
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 46cddfe94d1d..71d2f44e40c8 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -1857,12 +1857,14 @@ diagnostic_output_format_init (diagnostic_context 
&context,
 
 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
   diagnostic_output_format_init_sarif_stderr (context,
+ line_table,
  main_input_filename_,
  json_formatting);
   break;
 
 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
   diagnostic_output_format_init_sarif_file (context,
+  

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

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

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

diagnostics: SARIF output: capture unlabelled secondary locations

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

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

For example, given:

  int missing_semicolon (void)
  {
return 42
  }

for which the textual output looks like this:

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

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

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

where the result gains a related location :

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

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

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

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

testsuite: drop unused import within sarif.py

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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


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

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

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

diagnostics: handle logical locations with NULL name

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

Signed-off-by: David Malcolm 

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

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


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

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

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

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

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

No functional change intended.

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

Signed-off-by: David Malcolm 

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

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

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

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

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

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

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

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

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

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

Signed-off-by: David Malcolm 

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

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

  1   2   3   >