From patchwork Mon Aug 14 15:48:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Li, Pan2 via Gcc-patches" X-Patchwork-Id: 135523 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2836241vqi; Mon, 14 Aug 2023 08:57:04 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG6u/kgAZgFecHePo0NBeJO2YZfHhetGw5rixgZkT0T8JXXyDNYqIyDkSjgd1XqEmtbIP/s X-Received: by 2002:a05:6512:3134:b0:4fe:5741:9eb9 with SMTP id p20-20020a056512313400b004fe57419eb9mr6491319lfd.49.1692028623898; Mon, 14 Aug 2023 08:57:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692028623; cv=none; d=google.com; s=arc-20160816; b=nEuuo9VBCmaooYaKgtQpcGKD4CWemvPvkAHMuMDOkV9/KZXuqIfx61MDi570Ou2q5A dn5wAKfZrRyIEF/OvLz/Ti9qxAw0VCs/eTG5fUPKgop6JEyXXPI8zlu4jI0Dm83yNMEI yrcwenySz+aC5sboOe6u5l9rrvel7kJaS3vFu9WJT/kSpchStjgvvgwuCGsWJC7iJKnH 3XzjdTGImLBe/OhKg5ig/MCExg0fWrr9pfWYymkjXsenTI59CjzxvczSs28FOIyFScHt kLKZsU1w4GfCX5T6wnYajMCiugpuctjHl9ysKp7DuAJtbRsQtTssLldPJK+sUso2qQXa 96zA== 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:mime-version:references:in-reply-to :message-id:date:subject:cc:to:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=uN2mUKbMdon2/y3taa1BlPEMDdivu9s1kvdtDE2FDq8=; fh=se9AvlvO6nAQ+5ltUc700CnLSEFsJZH/SLcWO+v9loY=; b=gDsLOQGT1imWvTfyIrxs59mu/xGQpa4tMXB0P3k5yJ5pXKtGcaQDqKp15TzG0j78bV ubqebQzqDABKCP/zldVK+cZ3whSdyzi0lMiE4hZUcbx2OyoviZ0UJKGTTav/yNbFQC4e FK5AAQPLABMlIDT6gSJTY6ODV6MQWtN63r6z7A56mrOORY9ZJiVBQU0pWeIMfpqzcWrt QoU78A0exm8A5yaHsGxsEDhK8khPqaJZYI9DFaSuoSr4I9kOI7BpfOP81YGUKXggTMP8 54lo4vu8U4WAXnkixoXvgFTXcckHcTTjvjihQ/zFTkSabhVR5d0qimwlx2lX9wUAZMfn 60GQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=k8peEihN; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 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 (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id h24-20020a50ed98000000b00523463529d3si8397744edr.277.2023.08.14.08.57.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Aug 2023 08:57:03 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=k8peEihN; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 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 B6C51385770F for ; Mon, 14 Aug 2023 15:56:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B6C51385770F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692028615; bh=uN2mUKbMdon2/y3taa1BlPEMDdivu9s1kvdtDE2FDq8=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=k8peEihNsHu7o/aSdgG9d1J/ROQZvlDwhAJb3aAvBFSx0IpJvLGcPipt52mjtuOPL ccJ/M8vPOUKBM0p09iO7yoUiAAGUFs9uAwBlsxrd0iF5U0W04bT3ioGfCi4DyscD/+ AqdjLEHLks57vM4Yor44DB28Kpk2XG+VxMA1h+L8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 437233858281; Mon, 14 Aug 2023 15:56:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 437233858281 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-318015ade49so4036296f8f.0; Mon, 14 Aug 2023 08:56:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1692028566; x=1692633366; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uN2mUKbMdon2/y3taa1BlPEMDdivu9s1kvdtDE2FDq8=; b=HcVlFrn+Cv1BzgG7+A6ZGQwVL2UqEaxQc9h1cix7gsaiB8u+I5VS9xnMXMpmYNoTMC b1475CJ9ZspQjti6GS49hl9tOvErBn6h5Fv/+keUdafLHPBl7ZH+Dv/mNE+duUbevdqJ ShGZcNDZznZ9FEIosmW2nQ2YpO5pAzNinCDZ9nV/6aJmvGMZzBYtN2LPvh0WVOjoC1nq 6NSk3f5WHk3Alx2ztDp9hgSAPIM+Fyn3Lh9A8KFQeczZlsj3Q+VqcMSl49n97ZegCmDc HKowvOCPTCAxH8T01ARUd00I3aQpQmMkJyZ0s3FsMWiysnpKNx6t57uvRpcWWHq7Qv3y kJzg== X-Gm-Message-State: AOJu0YzeRUuwFT4GPs93hUI7IrjXJt63c7g1N9i4Qv+Mr2WFK1RboAH4 SKXg1sAy7F0QN/ADiO3pgJ1VeqdKUA== X-Received: by 2002:adf:fc0f:0:b0:317:60c9:e826 with SMTP id i15-20020adffc0f000000b0031760c9e826mr7664195wrr.45.1692028565650; Mon, 14 Aug 2023 08:56:05 -0700 (PDT) Received: from localhost ([2a01:e0a:2ec:f0d0:c1e5:2023:9b39:1a12]) by smtp.gmail.com with UTF8SMTPSA id e7-20020a05600c218700b003fe3674bb39sm14842357wme.2.2023.08.14.08.56.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 14 Aug 2023 08:56:05 -0700 (PDT) X-Google-Original-From: vultkayn@gcc.gnu.org To: gcc-patches@gcc.gnu.org Cc: dmalcolm@redhat.com, benjamin priour Subject: [PATCH v2] analyzer: New option fanalyzer-show-events-in-system-headers [PR110543] Date: Mon, 14 Aug 2023 17:48:55 +0200 Message-Id: <20230814154853.2371420-1-vultkayn@gcc.gnu.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP 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-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: "Li, Pan2 via Gcc-patches" Reply-To: priour.be@gmail.com Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773933401979387551 X-GMAIL-MSGID: 1774220606179172609 From: benjamin priour Plenty useful, thanks David. I've adjusted some few things, especially the artifacts of earlier versions I missed when building the commit. I didn't how to test for warnings within , I couldn't figure a portable test. I cannot pinpoint the line the warning is issued at in an inline DejaGNU directive, nor can I safely say the stack depth if I check a multiline-output (nor the methods names) In the end, I found out an alternative, I am checking for the presence of event "entry of 'main'". Indeed, diagnostic_manager::finish_pruning comment's reads If all we're left with is in one function, then filter function entry events. The provided test case can only goes into main and std::* frames, so if "entry of 'main'" exists, it means we are also going into std::* frames. I've also adjusted the comment of prune_system_headers, analyzer.opt and added an entry to invoker.texi. Successfully regstrapped off trunk 54be338589ea93ad4ff53d22adde476a0582537b on x86_64-linux-gnu. Thanks, Benjamin. Patch below. ---- This patch introduces -fanalyzer-show-events-in-system-headers, disabled by default. This option reduces the noise of the analyzer emitted diagnostics when dealing with system headers. The new option only affects the display of the diagnostics, but doesn't hinder the actual analysis. Given a diagnostics path diving into a system header in the form [ prefix events..., system header call, system header entry, events within system headers..., system header return, suffix events... ] then disabling the option (either by default or explicitly) will shorten the path into: [ prefix events..., system header call, system header return, suffix events... ] Signed-off-by: benjamin priour gcc/analyzer/ChangeLog: PR analyzer/110543 * analyzer.opt: Add new option. * diagnostic-manager.cc (diagnostic_manager::prune_path): Call prune_system_headers. (prune_frame): New function that deletes all events in a frame. (diagnostic_manager::prune_system_headers): New function. * diagnostic-manager.h: Add prune_system_headers declaration. gcc/ChangeLog: PR analyzer/110543 * doc/invoke.texi: Add documentation of fanalyzer-show-events-in-system-headers gcc/testsuite/ChangeLog: PR analyzer/110543 * g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C: New test. * g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C: New test. * g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C: New test. --- gcc/analyzer/analyzer.opt | 4 + gcc/analyzer/diagnostic-manager.cc | 96 +++++++++++++++++++ gcc/analyzer/diagnostic-manager.h | 1 + gcc/doc/invoke.texi | 9 ++ ...er-show-events-in-system-headers-default.C | 18 ++++ ...nalyzer-show-events-in-system-headers-no.C | 19 ++++ .../fanalyzer-show-events-in-system-headers.C | 14 +++ 7 files changed, 161 insertions(+) create mode 100644 gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C create mode 100644 gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C create mode 100644 gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt index 2760aaa8151..7917473d122 100644 --- a/gcc/analyzer/analyzer.opt +++ b/gcc/analyzer/analyzer.opt @@ -290,6 +290,10 @@ fanalyzer-transitivity Common Var(flag_analyzer_transitivity) Init(0) Enable transitivity of constraints during analysis. +fanalyzer-show-events-in-system-headers +Common Var(flag_analyzer_show_events_in_system_headers) Init(0) +Show events within system headers in analyzer execution paths. + fanalyzer-call-summaries Common Var(flag_analyzer_call_summaries) Init(0) Approximate the effect of function calls to simplify analysis. diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index cfca305d552..430c4dc3d58 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #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" @@ -2281,6 +2282,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 (! flag_analyzer_show_events_in_system_headers) + prune_system_headers (path); consolidate_conditions (path); finish_pruning (path); path->maybe_log (get_logger (), "pruned"); @@ -2667,6 +2670,99 @@ diagnostic_manager::prune_interproc_events (checker_path *path) const while (changed); } +/* Remove everything within [call point, IDX]. For consistency, + IDX should represent the return event of the frame to delete, + or if there is none it should be the last event of the frame. + After this function, IDX designates the event prior to calling + this frame. */ + +static void +prune_frame (checker_path *path, int &idx) +{ + gcc_assert (idx >= 0); + int nesting = 1; + if (path->get_checker_event (idx)->is_return_p ()) + nesting = 0; + do + { + 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--); + } while (idx >= 0 && nesting != 0); +} + +/* This function is called when fanalyzer-show-events-in-system-headers + is disabled and will prune the diagnostic of all events within a + system header, only keeping the entry and exit events to the header. + This should be called after diagnostic_manager::prune_interproc_events + so that sucessive events [system header call, system header return] + are preserved thereafter. + + Given a diagnostics path diving into a system header in the form + [ + prefix events..., + system header call, + system header entry, + events within system headers..., + system header return, + suffix events... + ] + + then transforms it into + [ + prefix events..., + system header call, + system header return, + suffix events... + ]. */ + +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 entry, (...), system return, ...]. */ + if (event->is_return_p () + && in_system_header_at (event->get_location ())) + { + int ret_idx = idx; + prune_frame (path, idx); + + if (get_logger ()) + { + log ("filtering system headers events %i-%i:", + idx, ret_idx); + } + // Delete function entry within system headers. + if (idx >= 0) + { + event = path->get_checker_event (idx); + if (event->is_function_entry_p () + && in_system_header_at (event->get_location ())) + { + if (get_logger ()) + { + label_text desc (event->get_desc (false)); + log ("filtering event %i:" + "system header entry event: %s", + idx, desc.get ()); + } + + 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..d3022b888dd 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -180,6 +180,7 @@ 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 prune_system_headers (checker_path *path) const; void consolidate_conditions (checker_path *path) const; void finish_pruning (checker_path *path) const; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 674f956f4b8..c317d4b5af3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -430,6 +430,7 @@ Objective-C and Objective-C++ Dialects}. -fanalyzer-checker=@var{name} -fno-analyzer-feasibility -fanalyzer-fine-grained +-fanalyzer-show-events-in-system-headers -fno-analyzer-state-merge -fno-analyzer-state-purge -fno-analyzer-suppress-followups @@ -11203,6 +11204,14 @@ have been detected as being duplicates of each other, it emits a note when reporting the best diagnostic, giving the number of additional diagnostics that were suppressed by the deduplication logic. +@opindex fanalyzer-show-events-in-system-headers +@opindex fno-analyzer-show-events-in-system-headers +@item -fanalyzer-show-events-in-system-headers +By default the analyzer emits simplified diagnostics paths by hiding +events fully located within a system header. +With @option{-fanalyzer-show-events-in-system-headers} such +events are no longer suppressed. + @opindex fanalyzer-state-merge @opindex fno-analyzer-state-merge @item -fno-analyzer-state-merge diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C new file mode 100644 index 00000000000..26f047d5471 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C @@ -0,0 +1,18 @@ +/* { dg-skip-if "no shared_ptr in C++98" { c++98_only } } */ + +#include + +struct A {int x; int y;}; + +int main () { + std::shared_ptr a; /* { dg-line declare_a } */ + a->x = 4; /* { dg-line deref_a } */ + /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */ + + return 0; +} + +/* { dg-note "\\(1\\) 'a\\.std::.+::_M_ptr' is NULL" "" { target c++14_down } declare_a } */ +/* { dg-note "dereference of NULL 'a\\.std::.+::operator->\\(\\)'" "" { target *-*-* } deref_a } */ +/* { dg-note "calling 'std::.+::operator->' from 'main'" "" { target *-*-* } deref_a } */ +/* { dg-note "returning to 'main' from 'std::.+::operator->'" "" { target *-*-* } deref_a } */ diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C new file mode 100644 index 00000000000..fd0df318051 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C @@ -0,0 +1,19 @@ +/* { dg-additional-options "-fno-analyzer-show-events-in-system-headers" } */ +/* { dg-skip-if "no shared_ptr in C++98" { c++98_only } } */ + +#include + +struct A {int x; int y;}; + +int main () { + std::shared_ptr a; /* { dg-line declare_a } */ + a->x = 4; /* { dg-line deref_a } */ + /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */ + + return 0; +} + +/* { dg-note "\\(1\\) 'a\\.std::.+::_M_ptr' is NULL" "" { target c++14_down } declare_a } */ +/* { dg-note "dereference of NULL 'a\\.std::.+::operator->\\(\\)'" "" { target *-*-* } deref_a } */ +/* { dg-note "calling 'std::.+::operator->' from 'main'" "" { target *-*-* } deref_a } */ +/* { dg-note "returning to 'main' from 'std::.+::operator->'" "" { target *-*-* } deref_a } */ diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C new file mode 100644 index 00000000000..4cc93d129f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-show-events-in-system-headers.C @@ -0,0 +1,14 @@ +/* { dg-additional-options "-fanalyzer-show-events-in-system-headers" } */ +/* { dg-skip-if "no shared_ptr in C++98" { c++98_only } } */ + +#include + +struct A {int x; int y;}; + +int main () { /* { dg-message "\\(1\\) entry to 'main'" "telltale event that we are going within a deeper frame than 'main'" } */ + std::shared_ptr a; /* { dg-line declare_a } */ + a->x = 4; /* { dg-line deref_a } */ + /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */ + + return 0; +}