From patchwork Mon Oct 19 17:23:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 1384437 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=nYbAj+D3; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CFNsP0hHNz9sSs for ; Tue, 20 Oct 2020 04:24:07 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7627B386EC7A; Mon, 19 Oct 2020 17:24:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7627B386EC7A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1603128245; bh=hye2Jvna2XMCdiQwxgcfWP9ebpnl/JN01emYyzsRIHA=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=nYbAj+D3Ni71I4KGj4QxfZLqmIyQjvU7z6WqsiWOAtHt1YZAoh+hIKmv3jsvlQ5ky Mjbb8YyuZlEUFri4WdQWunYGFTfxkvudDs3NPJErK1C52sw5jeTl2hGScA8lbExLUT q0hRjFPfHZGsTdgp/VeTn9KoG+Q5r2q1ahunqGvI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id 4F2D43857C4F for ; Mon, 19 Oct 2020 17:24:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4F2D43857C4F Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-410-U1-vmD3nOfafx2miIpPzOg-1; Mon, 19 Oct 2020 13:23:58 -0400 X-MC-Unique: U1-vmD3nOfafx2miIpPzOg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5A5CD8014D8 for ; Mon, 19 Oct 2020 17:23:57 +0000 (UTC) Received: from abulafia.quesejoda.com (ovpn-113-7.ams2.redhat.com [10.36.113.7]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AA66175139; Mon, 19 Oct 2020 17:23:56 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.15.2/8.15.2) with ESMTPS id 09JHNs8G164142 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 19 Oct 2020 19:23:54 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.15.2/8.15.2/Submit) id 09JHNr9g164141; Mon, 19 Oct 2020 19:23:53 +0200 To: GCC patches Subject: PING: [PATCH] Convert -Wrestrict pass to ranger. Date: Mon, 19 Oct 2020 19:23:39 +0200 Message-Id: <20201019172338.164084-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Aldy Hernandez via Gcc-patches From: Aldy Hernandez Reply-To: Aldy Hernandez Cc: Martin Sebor Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Rebased on current trunk. There is one adjustment to a C++ test which now gives a false positive. After talking with Martin Sebor, we've concluded this is expected. There is no way to communicate that libstdc++ allocated objects are always less than PTRDIFF_MAX. OK? gcc/ChangeLog: * calls.c (get_size_range): Adjust to work with ranger. * calls.h (get_size_range): Add ranger argument to prototype. * gimple-ssa-warn-restrict.c (class wrestrict_dom_walker): Remove. (check_call): Pull out of wrestrict_dom_walker into a static function. (wrestrict_dom_walker::before_dom_children): Rename to... (wrestrict_walk): ...this. (pass_wrestrict::execute): Instantiate ranger. (class builtin_memref): Add stmt and query fields. (builtin_access::builtin_access): Add range_query field. (builtin_memref::builtin_memref): Same. (builtin_memref::extend_offset_range): Same. (builtin_access::builtin_access): Make work with ranger. (wrestrict_dom_walker::check_call): Pull out into... (check_call): ...here. (check_bounds_or_overlap): Add range_query argument. * gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Add range_query and gimple stmt arguments. gcc/testsuite/ChangeLog: * gcc.dg/Wrestrict-22.c: New test. * g++.dg/torture/pr92421.C: Adjust for ranger. libstdc++-v3/ChangeLog: * testsuite/21_strings/basic_string/capacity/1.cc: Pass -Wno-stringop-overflow to test. --- gcc/calls.c | 26 ++++- gcc/calls.h | 2 + gcc/gimple-ssa-warn-restrict.c | 99 +++++++++++-------- gcc/gimple-ssa-warn-restrict.h | 3 + gcc/testsuite/g++.dg/torture/pr92421.C | 4 + gcc/testsuite/gcc.dg/Wrestrict-22.c | 9 ++ .../21_strings/basic_string/capacity/1.cc | 2 + 7 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-22.c diff --git a/gcc/calls.c b/gcc/calls.c index d3120b23f60..a12b84744c0 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "gimple-fold.h" #include "attr-fnspec.h" +#include "value-query.h" #include "tree-pretty-print.h" @@ -1244,7 +1245,8 @@ alloc_max_size (void) in a multi-range, otherwise to the smallest valid subrange. */ bool -get_size_range (tree exp, tree range[2], int flags /* = 0 */) +get_size_range (range_query *query, tree exp, gimple *stmt, tree range[2], + int flags /* = 0 */) { if (!exp) return false; @@ -1263,7 +1265,21 @@ get_size_range (tree exp, tree range[2], int flags /* = 0 */) enum value_range_kind range_type; if (integral) - range_type = determine_value_range (exp, &min, &max); + { + value_range vr; + if (query && query->range_of_expr (vr, exp, stmt)) + { + range_type = vr.kind (); + if (!vr.undefined_p ()) + { + min = wi::to_wide (vr.min ()); + max = wi::to_wide (vr.max ()); + } + } + else + range_type = determine_value_range (exp, &min, &max); + + } else range_type = VR_VARYING; @@ -1369,6 +1385,12 @@ get_size_range (tree exp, tree range[2], int flags /* = 0 */) return true; } +bool +get_size_range (tree exp, tree range[2], int flags /* = 0 */) +{ + return get_size_range (/*query=*/NULL, exp, /*stmt=*/NULL, range, flags); +} + /* Diagnose a call EXP to function FN decorated with attribute alloc_size whose argument numbers given by IDX with values given by ARGS exceed the maximum object size or cause an unsigned oveflow (wrapping) when diff --git a/gcc/calls.h b/gcc/calls.h index 644ec45d92c..f32b6308b58 100644 --- a/gcc/calls.h +++ b/gcc/calls.h @@ -142,6 +142,8 @@ enum size_range_flags SR_USE_LARGEST = 2 }; extern bool get_size_range (tree, tree[2], int = 0); +extern bool get_size_range (class range_query *, tree, gimple *, + tree[2], int = 0); extern rtx rtx_for_static_chain (const_tree, bool); extern bool cxx17_empty_base_field_p (const_tree); diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index e2734c81456..3a79e7240f9 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -25,7 +25,6 @@ #include "backend.h" #include "tree.h" #include "gimple.h" -#include "domwalk.h" #include "tree-pass.h" #include "builtins.h" #include "ssa.h" @@ -41,6 +40,7 @@ #include "calls.h" #include "cfgloop.h" #include "intl.h" +#include "gimple-range.h" namespace { @@ -77,21 +77,10 @@ pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED) return warn_array_bounds || warn_restrict || warn_stringop_overflow; } -/* Class to walk the basic blocks of a function in dominator order. */ -class wrestrict_dom_walker : public dom_walker -{ - public: - wrestrict_dom_walker () : dom_walker (CDI_DOMINATORS) {} +static void check_call (range_query *, gimple *); - edge before_dom_children (basic_block) FINAL OVERRIDE; - bool handle_gimple_call (gimple_stmt_iterator *); - - private: - void check_call (gimple *); -}; - -edge -wrestrict_dom_walker::before_dom_children (basic_block bb) +static void +wrestrict_walk (range_query *query, basic_block bb) { /* Iterate over statements, looking for function calls. */ for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); @@ -101,21 +90,17 @@ wrestrict_dom_walker::before_dom_children (basic_block bb) if (!is_gimple_call (stmt)) continue; - check_call (stmt); + check_call (query, stmt); } - - return NULL; } -/* Execute the pass for function FUN, walking in dominator order. */ - unsigned pass_wrestrict::execute (function *fun) { - calculate_dominance_info (CDI_DOMINATORS); - - wrestrict_dom_walker walker; - walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun)); + gimple_ranger ranger; + basic_block bb; + FOR_EACH_BB_FN (bb, fun) + wrestrict_walk (&ranger, bb); return 0; } @@ -159,11 +144,15 @@ public: only the destination reference is. */ bool strbounded_p; - builtin_memref (tree, tree); + builtin_memref (range_query *, gimple *, tree, tree); tree offset_out_of_bounds (int, offset_int[3]) const; private: + /* Call statement to the built-in. */ + gimple *stmt; + + range_query *query; /* Ctor helper to set or extend OFFRANGE based on argument. */ void extend_offset_range (tree); @@ -197,7 +186,7 @@ class builtin_access && detect_overlap != &builtin_access::no_overlap); } - builtin_access (gimple *, builtin_memref &, builtin_memref &); + builtin_access (range_query *, gimple *, builtin_memref &, builtin_memref &); /* Entry point to determine overlap. */ bool overlap (); @@ -233,9 +222,10 @@ class builtin_access /* Initialize a memory reference representation from a pointer EXPR and a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed - to be unknown. */ + to be unknown. STMT is the statement in which expr appears in. */ -builtin_memref::builtin_memref (tree expr, tree size) +builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, + tree size) : ptr (expr), ref (), base (), @@ -245,7 +235,9 @@ builtin_memref::builtin_memref (tree expr, tree size) offrange (), sizrange (), maxobjsize (tree_to_shwi (max_object_size ())), - strbounded_p () + strbounded_p (), + stmt (stmt), + query (query) { /* Unfortunately, wide_int default ctor is a no-op so array members of the type must be set individually. */ @@ -264,7 +256,7 @@ builtin_memref::builtin_memref (tree expr, tree size) tree range[2]; /* Determine the size range, allowing for the result to be [0, 0] for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */ - get_size_range (size, range, SR_ALLOW_ZERO); + get_size_range (query, size, stmt, range, SR_ALLOW_ZERO); sizrange[0] = wi::to_offset (range[0]); sizrange[1] = wi::to_offset (range[1]); /* get_size_range returns SIZE_MAX for the maximum size. @@ -341,7 +333,24 @@ builtin_memref::extend_offset_range (tree offset) /* A pointer offset is represented as sizetype but treated as signed. */ wide_int min, max; - value_range_kind rng = get_range_info (offset, &min, &max); + value_range_kind rng; + value_range vr; + if (query && query->range_of_expr (vr, offset, stmt)) + { + rng = vr.kind (); + if (!vr.undefined_p ()) + { + min = wi::to_wide (vr.min ()); + max = wi::to_wide (vr.max ()); + } + } + else + { + /* There is a global version here because + check_bounds_or_overlap may be called from gimple + fold during gimple lowering. */ + rng = get_range_info (offset, &min, &max); + } if (rng == VR_ANTI_RANGE && wi::lts_p (max, min)) { /* Convert an anti-range whose upper bound is less than @@ -658,7 +667,8 @@ builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const /* Create an association between the memory references DST and SRC for access by a call EXPR to a memory or string built-in funtion. */ -builtin_access::builtin_access (gimple *call, builtin_memref &dst, +builtin_access::builtin_access (range_query *query, gimple *call, + builtin_memref &dst, builtin_memref &src) : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (), dstoff (), srcoff (), dstsiz (), srcsiz () @@ -797,7 +807,7 @@ builtin_access::builtin_access (gimple *call, builtin_memref &dst, tree size = gimple_call_arg (call, sizeargno); tree range[2]; - if (get_size_range (size, range, true)) + if (get_size_range (query, size, call, range, true)) { bounds[0] = wi::to_offset (range[0]); bounds[1] = wi::to_offset (range[1]); @@ -1873,8 +1883,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, /* Check a CALL statement for restrict-violations and issue warnings if/when appropriate. */ -void -wrestrict_dom_walker::check_call (gimple *call) +static void +check_call (range_query *query, gimple *call) { /* Avoid checking the call if it has already been diagnosed for some reason. */ @@ -1964,7 +1974,7 @@ wrestrict_dom_walker::check_call (gimple *call) || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) return; - if (!check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) + if (!check_bounds_or_overlap (query, call, dst, src, dstwr, NULL_TREE)) return; /* Avoid diagnosing the call again. */ @@ -1984,15 +1994,26 @@ int check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) +{ + return check_bounds_or_overlap (/*range_query=*/NULL, + call, dst, src, dstsize, srcsize, + bounds_only, do_warn); +} + +int +check_bounds_or_overlap (range_query *query, + gimple *call, tree dst, tree src, tree dstsize, + tree srcsize, bool bounds_only /* = false */, + bool do_warn /* = true */) { tree func = gimple_call_fndecl (call); - builtin_memref dstref (dst, dstsize); - builtin_memref srcref (src, srcsize); + builtin_memref dstref (query, call, dst, dstsize); + builtin_memref srcref (query, call, src, srcsize); /* Create a descriptor of the access. This may adjust both DSTREF and SRCREF based on one another and the kind of the access. */ - builtin_access acs (call, dstref, srcref); + builtin_access acs (query, call, dstref, srcref); /* Set STRICT to the value of the -Warray-bounds=N argument for string functions or when N > 1. */ diff --git a/gcc/gimple-ssa-warn-restrict.h b/gcc/gimple-ssa-warn-restrict.h index 7bae95a9ad1..3dba9c0fe58 100644 --- a/gcc/gimple-ssa-warn-restrict.h +++ b/gcc/gimple-ssa-warn-restrict.h @@ -22,5 +22,8 @@ extern int check_bounds_or_overlap (gimple *, tree, tree, tree, tree, bool = false, bool = true); +extern int check_bounds_or_overlap (class range_query *, gimple *, + tree, tree, tree, tree, + bool = false, bool = true); #endif /* GIMPLE_SSA_WARN_RESTRICT_H */ diff --git a/gcc/testsuite/g++.dg/torture/pr92421.C b/gcc/testsuite/g++.dg/torture/pr92421.C index 2146e9416db..0489eb75d9a 100644 --- a/gcc/testsuite/g++.dg/torture/pr92421.C +++ b/gcc/testsuite/g++.dg/torture/pr92421.C @@ -2,6 +2,10 @@ // { dg-do compile } // { dg-additional-options "-Wno-return-type" } +// VRP jump threading will create additional __builtin___memcpy_chk calls that +// may be out of bounds. +// { dg-additional-options "-Wno-stringop-overflow" } + typedef long a; void *b, *c; template class d {}; diff --git a/gcc/testsuite/gcc.dg/Wrestrict-22.c b/gcc/testsuite/gcc.dg/Wrestrict-22.c new file mode 100644 index 00000000000..46f507b56b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-22.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wrestrict" } */ + +void test_memcpy_warn (char *d, unsigned n) +{ + for (unsigned i = n; i < 30; ++i) + if (i > 10) + __builtin_memcpy (d, d + 2, i); /* { dg-warning "overlaps" } */ +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc index a60f2d62da8..92f2bf40f14 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc @@ -17,6 +17,8 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-Wno-stringop-overflow" } + // 21.3.3 string capacity #include