From patchwork Fri Jul 21 15:35:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benjamin Priour X-Patchwork-Id: 123926 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9010:0:b0:3e4:2afc:c1 with SMTP id l16csp288959vqg; Fri, 21 Jul 2023 08:36:16 -0700 (PDT) X-Google-Smtp-Source: APBJJlGpJTOTeOfAt5GM96Q2IGvNvbZirtOgzXHU9Q6UpKa1UcjWTCMpeavgED4NFNNjUngGdPz3 X-Received: by 2002:a17:907:7ba6:b0:99b:4867:5e1c with SMTP id ne38-20020a1709077ba600b0099b48675e1cmr6954091ejc.28.1689953776257; Fri, 21 Jul 2023 08:36:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689953776; cv=none; d=google.com; s=arc-20160816; b=wkmBwr1gN1cR1x6mOUILbQC2KDPirUemlvIyu7UkHk8CTzC5LSUckCbDEby7OYU6Me GFMhQutbQqZqNztGad6Nkb7EyCLaM91wUr7zfz4LM7wy6q+Vym2GyA8GF3mcBBz++fWa Sf9RQxpU2yv4NATEttlTXQySxGItJaj4Zx8Zyx9EqF5kGYX56r8O26DILZZwXu8tZ2L5 Iu6amWLlqBs3VaKsaaZOfTXFEqBgTMjYUPf5tVI8ojhmrUv7ESGDIFknUSzCByg4/z3C XDlQuUx3rzv4RNtBK1md9bl8Vo4B0ec2aKoEW1yQ4wgKfCizlkUSM/cAmblAGPV8o7c2 KhMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:to:subject:message-id:date:in-reply-to :references:mime-version:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=tN4FkaLszHyPADbZA868A/gOI/LwplgmIE0P82pkstg=; fh=KBf8F+fhBcazRfJcKrB3ZiZ6lAKqlDhgZ7ASUDtFE5U=; b=LYo7lP9Hwfrhoua/s4F69+j6HDJX4dWkfmeF5qRu/0um3cCKh8qUP39e2gIBsbxDvw 7/SLBTSg53hFCq2Ov4Orwg83aGTCqWGmSj5ih8is3jVG3fwPKz5hvkKb1/Kov1iW4UXQ h5RSLzTe1YQlJ+d6WePqpM4g+QBPii5E8JESGbwpZ1rDrMQ+3YM2AB2FwoVyLcUsa32r o3+IRXjL6GN3y93psAPGo9VFw4KKo13pU8pXonoQQd3wI871fPPuOwPVW3JS/QtfPTxI XKn2S83DlabGge3oy6j5KsRDSBXmnEqUGZjOHBoW+FlpeJT3QW+H0vtCbvf10xLIWb46 YC6g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=IxYa5JNA; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id i15-20020a170906850f00b009886d385534si2322959ejx.950.2023.07.21.08.36.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Jul 2023 08:36:16 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=IxYa5JNA; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 914A7385DC2D for ; Fri, 21 Jul 2023 15:36:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 914A7385DC2D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689953773; bh=tN4FkaLszHyPADbZA868A/gOI/LwplgmIE0P82pkstg=; h=References:In-Reply-To:Date:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=IxYa5JNAbt7mvWT/IP68F2OPGmmSu8G+V/eg5Da2R508/7r/tBv4fl8r8BUbcW6YI JUTBZHj+DzCCHB2k+wK+GOrr28FODFYHtUYp89a0xR0ISxGNcR7e9jZuovvyhJrR85 t2WrZsiiFeRZLMlOhx3wDkxDu4yqoq+QLUJ5kYhc= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by sourceware.org (Postfix) with ESMTPS id 464283858409 for ; Fri, 21 Jul 2023 15:35:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 464283858409 Received: by mail-pg1-x52d.google.com with SMTP id 41be03b00d2f7-53482b44007so1119678a12.2 for ; Fri, 21 Jul 2023 08:35:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689953723; x=1690558523; h=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=m7GFynI76iqJRCSL/TkPRX4NX3PGXfDT8uVbg30G3o8=; b=WiyYTm2axKOcQqpwtZcxVvQw/3MImN3TuB8/8nmMIr2Tind9u5qnUdxp8Fexn9w3G4 SW4g0/kISTr6t1+t9iEgKo+AoM2JEDPzp6HQTCcyIgG6eyl2617nVJyExq0YFlADJf2F n3NCmk+OXrelm0lP5IpH8vf9PThbCscLfv412dWLlflJdFHKxAbf+nyRvRXknhmVM2SP AlGiQDXBgUtBBEbczUpkCOW/oxmvcFNenML6fCCbh6aWFbdeN1JDgyPfhKzO1lOG5xIU C75XAo/SpV5oW9hBdYpgH5geSGqiLr+4BPc4nqzUshk8lS42juqO9Jt/HF1B8XaEE0lP wfxg== X-Gm-Message-State: ABy/qLaIm6bmN+HeOhOZyA7ZIFGlhZviMeBgV/2ZKMaJ7XyUQVrCRTdL fDIq0fPCs+Y8/8yfQbr8EtVfuQ4N2JbqNKEWszGEoPMChg== X-Received: by 2002:a17:90a:3486:b0:263:76e8:b66f with SMTP id p6-20020a17090a348600b0026376e8b66fmr1541534pjb.30.1689953723357; Fri, 21 Jul 2023 08:35:23 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 21 Jul 2023 17:35:11 +0200 Message-ID: Subject: [WIP RFC] analyzer: Add optional trim of the analyzer diagnostics going too deep [PR110543] To: gcc-patches@gcc.gnu.org, David Malcolm X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, 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 X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Benjamin Priour via Gcc-patches From: Benjamin Priour Reply-To: Benjamin Priour Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771765351560464549 X-GMAIL-MSGID: 1772044971243575401 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 divergence results from two slightly different IPA: // c++14 -fdump-ipa-analyzer > // std::shared_ptr 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; 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 + { dg-end-multiline-output "" } */ \ No newline at end of file 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|] 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 + +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 + | + | + { 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 + +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]': 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 + +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 "" } */ \ 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 + +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 + | + | + { 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 + +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 "" } */ \ 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 + +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 + | + |