Re: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543]

2023-07-26 Thread David Malcolm via Gcc-patches
On Wed, 2023-07-26 at 11:27 +0200, Benjamin Priour wrote:
> On Sat, Jul 22, 2023 at 12:04 AM David Malcolm 
> 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  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 > __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 false>::operator->' from 'main'
> (12) dereference of NULL 'a.std::__shared_ptr_access __gnu_cxx::_S_atomic, false, false>::operator->()'
> (11) returning to 'main' from 'std::__shared_ptr_access __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).

I think we could still have events (11) and (12): what if for call and
return events we consider the location of both the call site and the
called function: we suppress if both are in a system header, but don't
suppress if only one is a system header.  That way by default we'd show
the call into a system header and show the return from the system
header, but we'd suppress all the implementation details within the
system header.

Does that seem like it could work?

Thanks
Dave



> 
> Thanks,
> Benjamin
> 
> 
> > Thanks
> > Dave
> > 
> 
> > 
> > > 
> > > -- Forwarded message -
> > > From: Benjamin Priour 
> > > Date: Tue, Jul 18, 2023 at 3:30 PM
> > > Subject: [RFC] analyzer: Add optional trim of the analyzer
> > > diagnostics
> > > going too deep [PR110543]
> > > To: , David Malcolm
> > > 
> > > 
> > > 
> > > 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 
> > > that prevents paths to go deeper than  frames.
> > > 
> > > fanalyzer-trim-diagnostics=
> > > > Common Joined RejectNegative ToLower
> > > > Var(flag_analyzer_trim_diagnostics)
> > > > Init("system")
> > > > -fanalyzer-trim-diagnostics=[never|system|] 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 
> > > > struct A {int x; int y;};
> > > > 
> > > > int main () {
> > > >   std::shared_ptr a;
> > 

Re: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543]

2023-07-26 Thread Benjamin Priour via Gcc-patches
On Sat, Jul 22, 2023 at 12:04 AM David Malcolm  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  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 __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::operator->' from 'main'
(12) dereference of NULL 'a.std::__shared_ptr_access::operator->()'
(11) returning to 'main' from 'std::__shared_ptr_access::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 
> > Date: Tue, Jul 18, 2023 at 3:30 PM
> > Subject: [RFC] analyzer: Add optional trim of the analyzer
> > diagnostics
> > going too deep [PR110543]
> > To: , David Malcolm 
> >
> >
> > 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 
> > that prevents paths to go deeper than  frames.
> >
> > fanalyzer-trim-diagnostics=
> > > Common Joined RejectNegative ToLower
> > > Var(flag_analyzer_trim_diagnostics)
> > > Init("system")
> > > -fanalyzer-trim-diagnostics=[never|system|] 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 
> > > struct A {int x; int y;};
> > >
> > > int main () {
> > >   std::shared_ptr 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, ,
> > > 
> > > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
> > >  >::operator->() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy
> > > _Lp = __gnu_cxx::_S_atomic; bool  = false; bool
> > >  =
> > > false]': events 3-4
> > >|
> > >|
> > >+--> 'std::__shared_ptr_access<_Tp, _Lp, ,
> > >  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > > ,  >::_M_get() const [with _Tp = A;
> > > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool
> > >  =
> > > false; bool  = false]': events 5-6
> > >   |
> > >   |
> > >   +--> 'std::__shared_ptr<_Tp, 

Re: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543]

2023-07-22 Thread Prathamesh Kulkarni via Gcc-patches
On Fri, 21 Jul 2023 at 21:05, Benjamin Priour via Gcc-patches
 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.
>
> -- Forwarded message -
> From: Benjamin Priour 
> Date: Tue, Jul 18, 2023 at 3:30 PM
> Subject: [RFC] analyzer: Add optional trim of the analyzer diagnostics
> going too deep [PR110543]
> To: , David Malcolm 
>
>
> 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 
> that prevents paths to go deeper than  frames.
>
> fanalyzer-trim-diagnostics=
> > Common Joined RejectNegative ToLower Var(flag_analyzer_trim_diagnostics)
> > Init("system")
> > -fanalyzer-trim-diagnostics=[never|system|] 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 
> > struct A {int x; int y;};
> >
> > int main () {
> >   std::shared_ptr 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, , 
> > >::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool  = false; bool  =
> > false]': events 3-4
> >|
> >|
> >+--> 'std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > ,  >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  =
> > false; bool  = 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, ,
> >  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > ,  >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  =
> > false; bool  = false]': event 9
> >   |
> >   |
> ><--+
> >|
> >  'std::__shared_ptr_access<_Tp, _Lp, , 
> > >::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool  = false; bool  =
> > 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;
> > |  |  ~
> > |  |  |
> > |  |  (2)
> > ‘a.std::shared_ptr::.std::__shared_ptr > __gnu_cxx::_S_atomic>::_M_ptr’ is NULL
> > |   10 |   a->x = 4; /* { dg-line deref_a } */
> > |  |~~
> > |  ||
> > |  |(3) calling ‘std::__shared_ptr_access > __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;
> >   

Re: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543]

2023-07-21 Thread David Malcolm via Gcc-patches
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.

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::operator->()'

What does the output look like with your patch?

Thanks
Dave





> 
> -- Forwarded message -
> From: Benjamin Priour 
> Date: Tue, Jul 18, 2023 at 3:30 PM
> Subject: [RFC] analyzer: Add optional trim of the analyzer
> diagnostics
> going too deep [PR110543]
> To: , David Malcolm 
> 
> 
> 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 
> that prevents paths to go deeper than  frames.
> 
> fanalyzer-trim-diagnostics=
> > Common Joined RejectNegative ToLower
> > Var(flag_analyzer_trim_diagnostics)
> > Init("system")
> > -fanalyzer-trim-diagnostics=[never|system|] 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 
> > struct A {int x; int y;};
> > 
> > int main () {
> >   std::shared_ptr 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, ,
> > 
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool  = false; bool
> >  =
> > false]': events 3-4
> >    |
> >    |
> >    +--> 'std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > ,  >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool
> >  =
> > false; bool  = 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, ,
> >  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> > ,  >::_M_get() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool
> >  =
> > false; bool  = false]': event 9
> >   |
> >   |
> >    <--+
> >    |
> >  'std::__shared_ptr_access<_Tp, _Lp, ,
> > 
> > > ::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
> >  >::operator->() const [with _Tp = A;
> > __gnu_cxx::_Lock_policy
> > _Lp = __gnu_cxx::_S_atomic; bool  = false; bool
> >  =
> > false]': event 10
> >    |
> >    |
> >     <--+
> >     |
> >   'int main()': events 11-12
> >     |
> >     

[WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543]

2023-07-21 Thread Benjamin Priour via Gcc-patches
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.

-- Forwarded message -
From: Benjamin Priour 
Date: Tue, Jul 18, 2023 at 3:30 PM
Subject: [RFC] analyzer: Add optional trim of the analyzer diagnostics
going too deep [PR110543]
To: , David Malcolm 


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 
that prevents paths to go deeper than  frames.

fanalyzer-trim-diagnostics=
> Common Joined RejectNegative ToLower Var(flag_analyzer_trim_diagnostics)
> Init("system")
> -fanalyzer-trim-diagnostics=[never|system|] 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 
> struct A {int x; int y;};
>
> int main () {
>   std::shared_ptr 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, , 
> >::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
>  >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
> _Lp = __gnu_cxx::_S_atomic; bool  = false; bool  =
> false]': events 3-4
>|
>|
>+--> 'std::__shared_ptr_access<_Tp, _Lp, ,
>  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> ,  >::_M_get() const [with _Tp = A;
> __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  =
> false; bool  = 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, ,
>  >::element_type* std::__shared_ptr_access<_Tp, _Lp,
> ,  >::_M_get() const [with _Tp = A;
> __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  =
> false; bool  = false]': event 9
>   |
>   |
><--+
>|
>  'std::__shared_ptr_access<_Tp, _Lp, , 
> >::element_type* std::__shared_ptr_access<_Tp, _Lp, ,
>  >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
> _Lp = __gnu_cxx::_S_atomic; bool  = false; bool  =
> 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;
> |  |  ~
> |  |  |
> |  |  (2)
> ‘a.std::shared_ptr::.std::__shared_ptr __gnu_cxx::_S_atomic>::_M_ptr’ is NULL
> |   10 |   a->x = 4; /* { dg-line deref_a } */
> |  |~~
> |  ||
> |  |(3) calling ‘std::__shared_ptr_access __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;
> |   10 |   a->x = 4; /* { dg-line deref_a } */
> |  |~~
> |  ||
> |  |(2) calling ‘std::__shared_ptr_access __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