From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by sourceware.org (Postfix) with ESMTPS id 9D2363858D1E for ; Sat, 22 Jul 2023 14:48:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9D2363858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-31297125334so1757082f8f.0 for ; Sat, 22 Jul 2023 07:48:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1690037303; x=1690642103; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ExeMhWD5nrOEq7YuIqvdLR+8eVUFlDM1HHkZMDyQEMo=; b=J5lp9brXfVWJeaUXiEaeC+q2zNB6tq8BcZDpO6NBg7Nhmhhni9QImUo3cAxii6fYl2 qI+8N+3haTfdXDwyEyZLeTI5GdDHl+0nxhPPJN6UEQjwJMBLmSDO8qPWoae1JYlFw8JR 8+S+agTKMG8Ki/wHIaCARZJGGZRkYw9qAURBKHVfduMGvVQt2LuoQi+RWsdy3ZX2wc+S FrSreLY4EO0AF9JQ3MRIuWS+ITKCF2gR2aW+UJlN7sdLvf35PSX2Zv1vO6vnmy+S/nZS NIKSvikxfyvFVczklcjQJZIfljdbyMHd+AQp4kMybMimZmdpbXgNX4qUm1ZUKaDKe1cX fOVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690037303; x=1690642103; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ExeMhWD5nrOEq7YuIqvdLR+8eVUFlDM1HHkZMDyQEMo=; b=QTRK7IpQBIoECbbKuHFEdj8ikqBYLrvSS+lWFbQ6C9iqUmOMg2Z7klf6omMGI1cVNt XWNbVM6kSDGAhyeXi+o3dMvlT4Fv+93d0Q03jlnSYRWN75VXD7I4o4GgcKEsgrbHcp3S fT9jUWj8ywLL6dF0RHbJ2dMuN6VFd5iyoRL8oYZqHRIQhsvSkigQF6Rw3UwwO3DPPnVO e18R6qCmx13awX26Jn8vQnbiIUSFTjVul8LFrFi9Rk/FlA6ajY8lER7vz2N/RMXHp8Ln KCrXH68B2Zcg+Kb3V83C1P3gLNK13J/0aRRM98aPMs/AR323Nr4hySIRQABuIwuVdJNF oErw== X-Gm-Message-State: ABy/qLb70Y6civeHt2eZ69HmEpzfdfDbspb/ZvpXh7zpsDBUCBtpG7Gw SoN0ufDD3MeU9u0IZGYWXqLIbrz1iY4+/X94Dk62Cg== X-Google-Smtp-Source: APBJJlGs1xoNPYMVPbxyTVT6+Ye5z5n5BwLmHnoPj+VA4c+BXW0/CSSEPIB6C+vsdTt9uldSK4R5goh0gz6OQsukqvA= X-Received: by 2002:a05:6000:1813:b0:30f:c050:88dd with SMTP id m19-20020a056000181300b0030fc05088ddmr7904169wrh.8.1690037302377; Sat, 22 Jul 2023 07:48:22 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Prathamesh Kulkarni Date: Sat, 22 Jul 2023 20:17:47 +0530 Message-ID: Subject: Re: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543] To: Benjamin Priour Cc: gcc-patches@gcc.gnu.org, David Malcolm Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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=E2=80=AFPM > 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 speci= fy > an unsigned value > that prevents paths to go deeper than frames. > > fanalyzer-trim-diagnostics=3D > > Common Joined RejectNegative ToLower Var(flag_analyzer_trim_diagnostics= ) > > Init("system") > > -fanalyzer-trim-diagnostics=3D[never|system|] Trim diagnostic= s > > 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=3Dinline-events -fanalyzer-trim-diagnostics= =3Dnever" > > } */ > > /* { dg-skip-if "" { c++98_only } } */ > > > > #include > > struct A {int x; int y;}; > > > > int main () { > > std::shared_ptr a; > > a->x =3D 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 =3D A; __gnu_cxx::_Lock_pol= icy > > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > > false]': events 3-4 > > | > > | > > +--> 'std::__shared_ptr_access<_Tp, _Lp, , > > >::element_type* std::__shared_ptr_access<_Tp, _Lp, > > , >::_M_get() const [with _Tp =3D A; > > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > > false; bool =3D false]': events 5-6 > > | > > | > > +--> 'std::__shared_ptr<_Tp, _Lp>::element_type* > > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp =3D A; > > __gnu_cxx::_Lock_policy _Lp =3D __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 =3D A; > > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > > false; bool =3D false]': event 9 > > | > > | > > <------+ > > | > > 'std::__shared_ptr_access<_Tp, _Lp, , > > >::element_type* std::__shared_ptr_access<_Tp, _Lp, , > > >::operator->() const [with _Tp =3D A; __gnu_cxx::_Lock_pol= icy > > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > > 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 > > =E2=80=98int main()=E2=80=99: events 1-3 > > | > > | 8 | int main () { > > | | ^~~~ > > | | | > > | | (1) entry to =E2=80=98main=E2=80=99 > > | 9 | std::shared_ptr a; > > | | ~ > > | | | > > | | (2) > > =E2=80=98a.std::shared_ptr::.std::__shared_ptr > __gnu_cxx::_S_atomic>::_M_ptr=E2=80=99 is NULL > > | 10 | a->x =3D 4; /* { dg-line deref_a } */ > > | | ~~ > > | | | > > | | (3) calling =E2=80=98std::__shared_ptr_access > __gnu_cxx::_S_atomic, false, false>::operator->=E2=80=99 from =E2=80=98= main=E2=80=99 > > > > whereas c++17 and posterior give > > > // c++17 with fully detailed output > > > // ./xg++ -fanalyzer > > ../../gcc/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-nev= er.C > > -B. -shared-libgcc -fanalyzer-trim-diagnostics=3Dnever -std=3Dc++17 > > > =E2=80=98int main()=E2=80=99: events 1-2 > > | > > | 8 | int main () { > > | | ^~~~ > > | | | > > | | (1) entry to =E2=80=98main=E2=80=99 > > | 9 | std::shared_ptr a; > > | 10 | a->x =3D 4; /* { dg-line deref_a } */ > > | | ~~ > > | | | > > | | (2) calling =E2=80=98std::__shared_ptr_access > __gnu_cxx::_S_atomic, false, false>::operator->=E2=80=99 from =E2=80=98= main=E2=80=99 > > > > 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; becomes > > a.D.29392._M_ptr =3D 0B; > > a.D.29392._M_refcount._M_pi =3D 0B; > > > > whereas in c++17 > > > // c++17 -fdump-ipa-analyzer > > // std::shared_ptr a; becomes > > a =3D {}; > > > > I know shared_ptr limited support is a coincidence more than a feature, b= ut > 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 =3D 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 *cal= l, > 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=3D > +Common Joined RejectNegative ToLower Var(flag_analyzer_trim_diagnostics) > Init("system") > +-fanalyzer-trim-diagnostics=3D[never|system|] 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 gi= ven > + or a negative value otherwise. */ > + > +long trim_diagnostics_depth () > +{ > + if (trim_diagnostics_system_p () || trim_diagnostics_never_p ()) > + return -1; > + > + char *end =3D NULL; > + long depth =3D strtol (flag_analyzer_trim_diagnostics, &end, 10); > + gcc_assert (end =3D=3D NULL || *end =3D=3D '\0'); > + gcc_assert (!(end =3D=3D flag_analyzer_trim_diagnostics && depth =3D= =3D 0)); > + return depth; > +} > + > +/* Return true if fanalyzer-trim-diagnostics is set to "system". */ > + > +bool trim_diagnostics_system_p () > +{ > + int len =3D strlen (flag_analyzer_trim_diagnostics); > + return len =3D=3D 6 && strcmp (flag_analyzer_trim_diagnostics, "system= ") =3D=3D > 0; > +} > + > +/* Return true if fanalyzer-trim-diagnostics is set to "never". */ > + > +bool trim_diagnostics_never_p () > +{ > + int len =3D strlen (flag_analyzer_trim_diagnostics); > + return len =3D=3D 5 && strcmp (flag_analyzer_trim_diagnostics, "never"= ) =3D=3D 0; > +} Hi Benjamin, Just wondering if the len check is necessary here ? IIUC, strcmp should handle the case correctly when the strings are of different lengths ? Also, I suppose it'd be better to merge above two functions, taking the string to match against ("system" / "never") as argument. Thanks, Prathamesh > + > 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 =3D 1; > + while (idx >=3D 0 && nesting !=3D 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 =3D (signed)path->num_events () - 1; > + while (idx >=3D 0) > + { > + const checker_event *event =3D path->get_checker_event (idx); > + /* Prune everything between [..., system call, (...), system retur= n, > ...]. */ > + if (event->is_return_p () > + && in_system_header_at (event->get_location ())) > + { > + int ret_idx =3D 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 >=3D 0) > + path->delete_event (idx); > + } > + > + idx--; > + } > +} > + > +void > +diagnostic_manager::prune_events_too_deep (checker_path *path) const > +{ > + long depth =3D 0; > + long maxdepth =3D trim_diagnostics_depth (); > + gcc_assert (maxdepth >=3D 0); > + int idx =3D (signed)path->num_events () - 1; > + if (idx >=3D 0) > + { > + depth =3D path->get_checker_event (0)->get_stack_depth (); > + maxdepth +=3D depth; > + } > + > + while (idx >=3D 0) > + { > + const checker_event *event =3D 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 =3D 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 >=3D 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=3Dinline-events -fanalyzer-trim-diagnostics=3D0= " } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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=3Dinline-events -fanalyzer-trim-diagnostics=3D1= " } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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 =3D A; __gnu_cxx::_Lock_polic= y > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > 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=3Dinline-events -fanalyzer-trim-diagnostics=3D2= " } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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 =3D A; __gnu_cxx::_Lock_polic= y > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > false]': events 3-4 > + | > + | > + +--> 'std::__shared_ptr_access<_Tp, _Lp, , > >::element_type* std::__shared_ptr_access<_Tp, _Lp, > , >::_M_get() const [with _Tp =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > false; bool =3D false]': events 5-6 > + | > + | > + +--> 'std::__shared_ptr<_Tp, _Lp>::element_type* > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __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 =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > false; bool =3D false]': event 9 > + | > + | > + <------+ > + | > + 'std::__shared_ptr_access<_Tp, _Lp, , > >::element_type* std::__shared_ptr_access<_Tp, _Lp, , > >::operator->() const [with _Tp =3D A; __gnu_cxx::_Lock_polic= y > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > 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=3Dinline-events" } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +// Must behave like -fanalyzer-trim-diagnostics=3Dsystem > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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=3Dinline-events -fanalyzer-trim-diagnostics=3Dn= ever" > } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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 =3D A; __gnu_cxx::_Lock_polic= y > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > false]': events 3-4 > + | > + | > + +--> 'std::__shared_ptr_access<_Tp, _Lp, , > >::element_type* std::__shared_ptr_access<_Tp, _Lp, > , >::_M_get() const [with _Tp =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > false; bool =3D false]': events 5-6 > + | > + | > + +--> 'std::__shared_ptr<_Tp, _Lp>::element_type* > std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __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 =3D A; > __gnu_cxx::_Lock_policy _Lp =3D __gnu_cxx::_S_atomic; bool = =3D > false; bool =3D false]': event 9 > + | > + | > + <------+ > + | > + 'std::__shared_ptr_access<_Tp, _Lp, , > >::element_type* std::__shared_ptr_access<_Tp, _Lp, , > >::operator->() const [with _Tp =3D A; __gnu_cxx::_Lock_polic= y > _Lp =3D __gnu_cxx::_S_atomic; bool =3D false; bool =3D > 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=3Dinline-events -fanalyzer-trim-diagnostics=3Ds= ystem" > } */ > +/* { dg-skip-if "" { c++98_only } } */ > + > +#include > + > +struct A {int x; int y;}; > + > +int main () { > + std::shared_ptr a; > + a->x =3D 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 > -- > 2.34.1