On Sat, Jul 22, 2023 at 12:04 AM David Malcolm <dmalc...@redhat.com> wrote:

> On Fri, 2023-07-21 at 17:35 +0200, Benjamin Priour wrote:
> > Hi,
> >
> > Upon David's request I've joined the in progress patch to the below
> > email.
> > I hope it makes more sense now.
> >
> > Best,
> > Benjamin.
>
> Thanks for posting the work-in-progress patch; it makes the idea
> clearer.
>
> Some thoughts about this:
>
> - I like the idea of defaulting to *not* showing events within system
> headers, which the patch achieves
> - I don't like the combination of never/system with maxdepth, in that
> it seems complicated and I don't think a user is likely to experiment
> with different depths.
> - Hence I think it would work better as a simple boolean, perhaps
>   "-fanalyzer-show-events-in-system-headers"
>   or somesuch?  It seems like the sort of thing that we want to provide
> a sensible default for, but have the option of turning off for
> debugging the analyzer itself, but I don't expect an end-user to touch
> that option.
>

A boolean sounds good, I will trust your experience with the end-user here,
especially since <maxdepth> and "never" had some overlap, it could have
been confusing.


> FWIW the patch seems to have been mangled somewhat via email, so I
> don't have a sense of what the actual output from patched analyzer
> looks like.  What should we output to the user with -fanalyzer and no
> other options for the case in PR 110543?  Currently, for
> https://godbolt.org/z/sb9dM9Gqa trunk emits 12 events, of which
> probably only this last one is useful:
>
>   (12) dereference of NULL 'a.std::__shared_ptr_access<A,
> __gnu_cxx::_S_atomic, false, false>::operator->()'
>
> What does the output look like with your patch?
>

The plan with this patch was to get events :
(1) entry to 'main'
(2) calling 'std::__shared_ptr_access<A, __gnu_cxx::_S_atomic, false,
false>::operator->' from 'main'
(12) dereference of NULL 'a.std::__shared_ptr_access<A,
__gnu_cxx::_S_atomic, false, false>::operator->()'
(11) returning to 'main' from 'std::__shared_ptr_access<A,
__gnu_cxx::_S_atomic, false, false>::operator->'

This way, we get the entry and exit point to the system headers ( (2) and
(11) ), and the actual injurious event ( (12) ).
We could however go as you suggest, with an even more succint path and only
keep (1) and (12).

Thanks,
Benjamin


> Thanks
> Dave
>

>
> >
> > ---------- Forwarded message ---------
> > From: Benjamin Priour <priour...@gmail.com>
> > Date: Tue, Jul 18, 2023 at 3:30 PM
> > Subject: [RFC] analyzer: Add optional trim of the analyzer
> > diagnostics
> > going too deep [PR110543]
> > To: <gcc-patches@gcc.gnu.org>, David Malcolm <dmalc...@redhat.com>
> >
> >
> > Hi,
> >
> > I'd like to request comments on a patch I am writing for PR110543.
> > The goal of this patch is to reduce the noise of the analyzer emitted
> > diagnostics when dealing with
> > system headers, or simply diagnostic paths that are too long. The new
> > option only affects the display
> > of the diagnostics, but doesn't hinder the actual analysis.
> >
> > I've defaulted the new option to "system", thus preventing the
> > diagnostic
> > paths from showing system headers.
> > "never" corresponds to the pre-patch behavior, whereas you can also
> > specify
> > an unsigned value <maxdepth>
> > that prevents paths to go deeper than <maxdepth> frames.
> >
> > fanalyzer-trim-diagnostics=
> > > Common Joined RejectNegative ToLower
> > > Var(flag_analyzer_trim_diagnostics)
> > > Init("system")
> > > -fanalyzer-trim-diagnostics=[never|system|<maxdepth>] Trim
> > > diagnostics
> > > path that are too long before emission.
> > >
> >
> > Does it sounds reasonable and user-friendly ?
> >
> > Regstrapping was a success against trunk, although one of the newly
> > added
> > test case fails for c++14.
> > Note that the test case below was done with "never", thus behaves
> > exactly
> > as the pre-patch analyzer
> > on x86_64-linux-gnu.
> >
> > /* { dg-additional-options "-fdiagnostics-plain-output
> > > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > > diagnostics=never"
> > > } */
> > > /* { dg-skip-if "" { c++98_only }  } */
> > >
> > > #include <memory>
> > > struct A {int x; int y;};
> > >
> > > int main () {
> > >   std::shared_ptr<A> a;
> > >   a->x = 4; /* { dg-line deref_a } */
> > >   /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > > } */
> > >
> > >   return 0;
> > > }
> > >
> > > /* { dg-begin-multiline-output "" }
> > >   'int main()': events 1-2
> > >     |
> > >     |
> > >     +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous>
> > > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous> >::operator->() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy
> > > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > > <anonymous> =
> > > false]': events 3-4
> > >            |
> > >            |
> > >            +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool
> > > <anonymous> =
> > > false; bool <anonymous> = false]': events 5-6
> > >                   |
> > >                   |
> > >                   +--> 'std::__shared_ptr<_Tp, _Lp>::element_type*
> > > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': events 7-8
> > >                          |
> > >                          |
> > >                   <------+
> > >                   |
> > >                 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool
> > > <anonymous> =
> > > false; bool <anonymous> = false]': event 9
> > >                   |
> > >                   |
> > >            <------+
> > >            |
> > >          'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous>
> > > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > > <anonymous> >::operator->() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy
> > > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > > <anonymous> =
> > > false]': event 10
> > >            |
> > >            |
> > >     <------+
> > >     |
> > >   'int main()': events 11-12
> > >     |
> > >     |
> > >    { dg-end-multiline-output "" } */
> > >
> >
> >
> > The first events "'int main()': events 1-2" vary in c++14 (get events
> > 1-3).
> >
> > >
> > > // c++14 with fully detailed output
> > >   ‘int main()’: events 1-3
> > >     |
> > >     |    8 | int main () {
> > >     |      |     ^~~~
> > >     |      |     |
> > >     |      |     (1) entry to ‘main’
> > >     |    9 |   std::shared_ptr<A> a;
> > >     |      |                      ~
> > >     |      |                      |
> > >     |      |                      (2)
> > > ‘a.std::shared_ptr<A>::<anonymous>.std::__shared_ptr<A,
> > > __gnu_cxx::_S_atomic>::_M_ptr’ is NULL
> > >     |   10 |   a->x = 4; /* { dg-line deref_a } */
> > >     |      |    ~~
> > >     |      |    |
> > >     |      |    (3) calling ‘std::__shared_ptr_access<A,
> > > __gnu_cxx::_S_atomic, false, false>::operator->’ from ‘main’
> > >
> >
> > whereas c++17 and posterior give
> >
> > > // c++17 with fully detailed output
> > >
> > // ./xg++ -fanalyzer
> > >  ../../gcc/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-
> > > diagnostics-never.C
> > >  -B. -shared-libgcc -fanalyzer-trim-diagnostics=never -std=c++17
> > >
> >   ‘int main()’: events 1-2
> > >     |
> > >     |    8 | int main () {
> > >     |      |     ^~~~
> > >     |      |     |
> > >     |      |     (1) entry to ‘main’
> > >     |    9 |   std::shared_ptr<A> a;
> > >     |   10 |   a->x = 4; /* { dg-line deref_a } */
> > >     |      |    ~~
> > >     |      |    |
> > >     |      |    (2) calling ‘std::__shared_ptr_access<A,
> > > __gnu_cxx::_S_atomic, false, false>::operator->’ from ‘main’
> > >
> >
> > Is there a way to make dg-multiline-output check for a regex ? Or
> > would
> > checking the multiline-output only for c++17 and c++20 be acceptable
> > ?
> > This divergence results from two slightly different IPA:
> >
> > // c++14 -fdump-ipa-analyzer
> > > // std::shared_ptr<A> a; becomes
> > > a.D.29392._M_ptr = 0B;
> > > a.D.29392._M_refcount._M_pi = 0B;
> > >
> >
> > whereas in c++17
> >
> > > // c++17 -fdump-ipa-analyzer
> > > // std::shared_ptr<A> a; becomes
> > > a = {};
> > >
> >
> > I know shared_ptr limited support is a coincidence more than a
> > feature, but
> > maybe there is still a way to make the above test case work ?
> > Otherwise, I'd fallback to a supported system function. If you have
> > any
> > that you fancy, do tell me.
> >
> > Thanks,
> > Benjamin.
> >
> > ---
> >  gcc/analyzer/analyzer.cc                      |   2 +-
> >  gcc/analyzer/analyzer.h                       |   1 +
> >  gcc/analyzer/analyzer.opt                     |   4 +
> >  gcc/analyzer/diagnostic-manager.cc            | 132
> > ++++++++++++++++++
> >  gcc/analyzer/diagnostic-manager.h             |   7 +
> >  .../analyzer/fanalyzer-trim-diagnostics-0.C   |  19 +++
> >  .../analyzer/fanalyzer-trim-diagnostics-1.C   |  28 ++++
> >  .../analyzer/fanalyzer-trim-diagnostics-2.C   |  44 ++++++
> >  .../fanalyzer-trim-diagnostics-default.C      |  21 +++
> >  .../fanalyzer-trim-diagnostics-never.C        |  44 ++++++
> >  .../fanalyzer-trim-diagnostics-system.C       |  19 +++
> >  11 files changed, 320 insertions(+), 1 deletion(-)
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
> >  create mode 100644
> > gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
> >
> > diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
> > index 5091fb7a583..b27d8e359db 100644
> > --- a/gcc/analyzer/analyzer.cc
> > +++ b/gcc/analyzer/analyzer.cc
> > @@ -274,7 +274,7 @@ is_named_call_p (const_tree fndecl, const char
> > *funcname)
> >     Compare with cp/typeck.cc: decl_in_std_namespace_p, but this
> > doesn't
> >     rely on being the C++ FE (or handle inline namespaces inside of
> > std).
> >  */
> >
> > -static inline bool
> > +bool
> >  is_std_function_p (const_tree fndecl)
> >  {
> >    tree name_decl = DECL_NAME (fndecl);
> > diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
> > index 579517c23e6..31597079153 100644
> > --- a/gcc/analyzer/analyzer.h
> > +++ b/gcc/analyzer/analyzer.h
> > @@ -386,6 +386,7 @@ extern bool is_special_named_call_p (const gcall
> > *call,
> > const char *funcname,
> >  extern bool is_named_call_p (const_tree fndecl, const char
> > *funcname);
> >  extern bool is_named_call_p (const_tree fndecl, const char
> > *funcname,
> >       const gcall *call, unsigned int num_args);
> > +extern bool is_std_function_p (const_tree fndecl);
> >  extern bool is_std_named_call_p (const_tree fndecl, const char
> > *funcname);
> >  extern bool is_std_named_call_p (const_tree fndecl, const char
> > *funcname,
> >   const gcall *call, unsigned int num_args);
> > diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
> > index 2760aaa8151..78ff2c07483 100644
> > --- a/gcc/analyzer/analyzer.opt
> > +++ b/gcc/analyzer/analyzer.opt
> > @@ -362,4 +362,8 @@ fdump-analyzer-untracked
> >  Common RejectNegative Var(flag_dump_analyzer_untracked)
> >  Emit custom warnings with internal details intended for analyzer
> > developers.
> >
> > +fanalyzer-trim-diagnostics=
> > +Common Joined RejectNegative ToLower
> > Var(flag_analyzer_trim_diagnostics)
> > Init("system")
> > +-fanalyzer-trim-diagnostics=[never|system|<maxdepth>] Trim
> > diagnostics
> > path that are too long before emission.
> > +
> >  ; This comment is to ensure we retain the blank line above.
> > diff --git a/gcc/analyzer/diagnostic-manager.cc
> > b/gcc/analyzer/diagnostic-manager.cc
> > index cfca305d552..d946ad5bac7 100644
> > --- a/gcc/analyzer/diagnostic-manager.cc
> > +++ b/gcc/analyzer/diagnostic-manager.cc
> > @@ -20,9 +20,11 @@ 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"
> >  #include "tree.h"
> > +#include "input.h"
> >  #include "pretty-print.h"
> >  #include "gcc-rich-location.h"
> >  #include "gimple-pretty-print.h"
> > @@ -60,6 +62,37 @@ along with GCC; see the file COPYING3.  If not see
> >
> >  #if ENABLE_ANALYZER
> >
> > +/* Return positive value of fanalyzer-trim-diagnostics if a depth
> > was given
> > +  or a negative value otherwise.  */
> > +
> > +long trim_diagnostics_depth ()
> > +{
> > +  if (trim_diagnostics_system_p () ||  trim_diagnostics_never_p ())
> > +    return -1;
> > +
> > +  char *end = NULL;
> > +  long depth = strtol (flag_analyzer_trim_diagnostics, &end, 10);
> > +  gcc_assert (end == NULL || *end == '\0');
> > +  gcc_assert (!(end == flag_analyzer_trim_diagnostics && depth ==
> > 0));
> > +  return depth;
> > +}
> > +
> > +/* Return true if fanalyzer-trim-diagnostics is set to "system".  */
> > +
> > +bool trim_diagnostics_system_p ()
> > +{
> > +  int len = strlen (flag_analyzer_trim_diagnostics);
> > +  return len == 6 && strcmp (flag_analyzer_trim_diagnostics,
> > "system") ==
> > 0;
> > +}
> > +
> > +/* Return true if fanalyzer-trim-diagnostics is set to "never".  */
> > +
> > +bool trim_diagnostics_never_p ()
> > +{
> > +  int len = strlen (flag_analyzer_trim_diagnostics);
> > +  return len == 5 && strcmp (flag_analyzer_trim_diagnostics,
> > "never") == 0;
> > +}
> > +
> >  namespace ana {
> >
> >  class feasible_worklist;
> > @@ -2281,6 +2314,8 @@ diagnostic_manager::prune_path (checker_path
> > *path,
> >    path->maybe_log (get_logger (), "path");
> >    prune_for_sm_diagnostic (path, sm, sval, state);
> >    prune_interproc_events (path);
> > +  if (! trim_diagnostics_never_p ())
> > +    trim_diagnostic_path (path);
> >    consolidate_conditions (path);
> >    finish_pruning (path);
> >    path->maybe_log (get_logger (), "pruned");
> > @@ -2667,6 +2702,103 @@ diagnostic_manager::prune_interproc_events
> > (checker_path *path) const
> >    while (changed);
> >  }
> >
> > +void
> > +diagnostic_manager::trim_diagnostic_path (checker_path *path) const
> > +{
> > +  if (trim_diagnostics_system_p ())
> > +    prune_system_headers (path);
> > +  else
> > +    prune_events_too_deep (path);
> > +}
> > +
> > +/* Remove everything within ]callsite, IDX].  */
> > +static void
> > +prune_within_frame (checker_path *path, int &idx)
> > +{
> > +  int nesting = 1;
> > +  while (idx >= 0 && nesting != 0)
> > +    {
> > +      if (path->get_checker_event (idx)->is_call_p ())
> > +        nesting--;
> > +      else if (path->get_checker_event (idx)->is_return_p ())
> > +        nesting++;
> > +
> > +      path->delete_event (idx--);
> > +    }
> > +}
> > +
> > +void
> > +diagnostic_manager::prune_system_headers (checker_path *path) const
> > +{
> > +  int idx = (signed)path->num_events () - 1;
> > +  while (idx >= 0)
> > +    {
> > +      const checker_event *event = path->get_checker_event (idx);
> > +      /* Prune everything between [..., system call, (...), system
> > return,
> > ...].  */
> > +      if (event->is_return_p ()
> > +          && in_system_header_at (event->get_location ()))
> > +      {
> > +        int ret_idx = idx;
> > +        prune_within_frame (path, idx);
> > +
> > +        if (get_logger ())
> > +        {
> > +          label_text desc
> > +            (path->get_checker_event (idx)->get_desc (false));
> > +          log ("filtering event %i-%i:"
> > +              " system header event: %s",
> > +              idx, ret_idx, desc.get ());
> > +        }
> > +        // delete callsite
> > +        if (idx >= 0)
> > +          path->delete_event (idx);
> > +      }
> > +
> > +      idx--;
> > +    }
> > +}
> > +
> > +void
> > +diagnostic_manager::prune_events_too_deep (checker_path *path) const
> > +{
> > +  long depth = 0;
> > +  long maxdepth = trim_diagnostics_depth ();
> > +  gcc_assert (maxdepth >= 0);
> > +  int idx = (signed)path->num_events () - 1;
> > +  if (idx >= 0)
> > +  {
> > +    depth = path->get_checker_event (0)->get_stack_depth ();
> > +    maxdepth += depth;
> > +  }
> > +
> > +  while (idx >= 0)
> > +    {
> > +      const checker_event *event = path->get_checker_event (idx);
> > +      /* Prune everything between [..., call too deep, (...), return
> > too
> > deep, ...].  */
> > +      if (event->is_return_p ()
> > +          && event->get_stack_depth () > maxdepth)
> > +      {
> > +        int ret_idx = idx;
> > +        prune_within_frame (path, idx);
> > +
> > +        if (get_logger ())
> > +        {
> > +          label_text desc
> > +            (path->get_checker_event (idx)->get_desc (false));
> > +          log ("filtering event %i-%i:"
> > +              " event too deep: %s",
> > +              idx, ret_idx, desc.get ());
> > +        }
> > +        // delete callsite
> > +        if (idx >= 0)
> > +          path->delete_event (idx);
> > +      }
> > +
> > +      idx--;
> > +    }
> > +
> > +}
> > +
> >  /* Return true iff event IDX within PATH is on the same line as
> > REF_EXP_LOC.  */
> >
> >  static bool
> > diff --git a/gcc/analyzer/diagnostic-manager.h
> > b/gcc/analyzer/diagnostic-manager.h
> > index 9b3e903fc5d..9afef0975be 100644
> > --- a/gcc/analyzer/diagnostic-manager.h
> > +++ b/gcc/analyzer/diagnostic-manager.h
> > @@ -21,6 +21,10 @@ along with GCC; see the file COPYING3.  If not see
> >  #ifndef GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
> >  #define GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
> >
> > +long trim_diagnostics_depth ();
> > +bool trim_diagnostics_system_p ();
> > +bool trim_diagnostics_never_p ();
> > +
> >  namespace ana {
> >
> >  class epath_finder;
> > @@ -180,6 +184,9 @@ private:
> >   state_machine::state_t state) const;
> >    void update_for_unsuitable_sm_exprs (tree *expr) const;
> >    void prune_interproc_events (checker_path *path) const;
> > +  void trim_diagnostic_path (checker_path *path) const;
> > +  void prune_system_headers (checker_path *path) const;
> > +  void prune_events_too_deep (checker_path *path) const;
> >    void consolidate_conditions (checker_path *path) const;
> >    void finish_pruning (checker_path *path) const;
> >
> > diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-
> > diagnostics-0.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
> > new file mode 100644
> > index 00000000000..ddf39ed1690
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
> > @@ -0,0 +1,19 @@
> > +/* { dg-additional-options "-fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > diagnostics=0" } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
> > diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-
> > diagnostics-1.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
> > new file mode 100644
> > index 00000000000..83a132078a1
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
> > @@ -0,0 +1,28 @@
> > +/* { dg-additional-options "-fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > diagnostics=1" } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous>
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > <anonymous> =
> > false]': event 3
> > +           |
> > +           |
> > +    <------+
> > +    |
> > +  'int main()': events 4-5
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
> > diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-
> > diagnostics-2.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
> > new file mode 100644
> > index 00000000000..cf065929ec9
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
> > @@ -0,0 +1,44 @@
> > +/* { dg-additional-options "-fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > diagnostics=2" } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous>
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > <anonymous> =
> > false]': events 3-4
> > +           |
> > +           |
> > +           +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous>
> > =
> > false; bool <anonymous> = false]': events 5-6
> > +                  |
> > +                  |
> > +                  +--> 'std::__shared_ptr<_Tp, _Lp>::element_type*
> > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': events 7-8
> > +                         |
> > +                         |
> > +                  <------+
> > +                  |
> > +                'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous>
> > =
> > false; bool <anonymous> = false]': event 9
> > +                  |
> > +                  |
> > +           <------+
> > +           |
> > +         'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous>
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > <anonymous> =
> > false]': event 10
> > +           |
> > +           |
> > +    <------+
> > +    |
> > +  'int main()': events 11-12
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
> > diff --git
> > a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
> > new file mode 100644
> > index 00000000000..fc271309d4e
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-
> > default.C
> > @@ -0,0 +1,21 @@
> > +/* { dg-additional-options "-O0 -fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events" } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +// Must behave like -fanalyzer-trim-diagnostics=system
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
> > diff --git
> > a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
> > new file mode 100644
> > index 00000000000..a69416608da
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-
> > never.C
> > @@ -0,0 +1,44 @@
> > +/* { dg-additional-options "-fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > diagnostics=never"
> > } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous>
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > <anonymous> =
> > false]': events 3-4
> > +           |
> > +           |
> > +           +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous>
> > =
> > false; bool <anonymous> = false]': events 5-6
> > +                  |
> > +                  |
> > +                  +--> 'std::__shared_ptr<_Tp, _Lp>::element_type*
> > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': events 7-8
> > +                         |
> > +                         |
> > +                  <------+
> > +                  |
> > +                'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > <anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous>
> > =
> > false; bool <anonymous> = false]': event 9
> > +                  |
> > +                  |
> > +           <------+
> > +           |
> > +         'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous>
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
> > <anonymous> >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool
> > <anonymous> =
> > false]': event 10
> > +           |
> > +           |
> > +    <------+
> > +    |
> > +  'int main()': events 11-12
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
> > diff --git
> > a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
> > b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
> > new file mode 100644
> > index 00000000000..22fadc84e75
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-
> > system.C
> > @@ -0,0 +1,19 @@
> > +/* { dg-additional-options "-fdiagnostics-plain-output
> > -fdiagnostics-path-format=inline-events -fanalyzer-trim-
> > diagnostics=system"
> > } */
> > +/* { dg-skip-if "" { c++98_only }  } */
> > +
> > +#include <memory>
> > +
> > +struct A {int x; int y;};
> > +
> > +int main () {
> > +  std::shared_ptr<A> a;
> > +  a->x = 4; /* { dg-line deref_a } */
> > +  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a
> > } */
> > +
> > +  return 0;
> > +}
> > +/* { dg-begin-multiline-output "" }
> > +  'int main()': events 1-2
> > +    |
> > +    |
> > +   { dg-end-multiline-output "" } */
> > \ No newline at end of file
>
>

Reply via email to