From patchwork Fri Aug 14 22:51:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 1345226 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=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (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=ubMFMsbT; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (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 4BSzGQ3RHyz9sTH for ; Sat, 15 Aug 2020 08:52:12 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 50B6A386F417; Fri, 14 Aug 2020 22:52:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 50B6A386F417 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1597445529; bh=HbMctNgnfTF2fN1Os8L4CDvhTpVE70UGU9+rM3pdAsc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ubMFMsbTJvHzjdAfvMiwlM6dxyewIFpLX6mCbx/MAqeotbjGuqlvm2eSR7IvETNuX T9gQB+GTLt2G5pqtlaohJI+LHeeG2WXPF6Lf7Ncn3VfUy/bs4m2qnm1EU6hwVAJJ4n 2m9/jRmjul4z4eLBD79bZPx6INdqHBTse9iaOJ4g= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by sourceware.org (Postfix) with ESMTP id 6C426386F413 for ; Fri, 14 Aug 2020 22:52:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 6C426386F413 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-141-cJipaCgHPdyHv-MbC9z1aQ-1; Fri, 14 Aug 2020 18:52:01 -0400 X-MC-Unique: cJipaCgHPdyHv-MbC9z1aQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DDAB9800D53; Fri, 14 Aug 2020 22:51:59 +0000 (UTC) Received: from t470.redhat.com (ovpn-113-239.phx2.redhat.com [10.3.113.239]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5F38F60CC0; Fri, 14 Aug 2020 22:51:59 +0000 (UTC) To: gcc-patches@gcc.gnu.org Subject: [committed] analyzer: fix initialization from constant pool [PR96609, PR96616] Date: Fri, 14 Aug 2020 18:51:57 -0400 Message-Id: <20200814225157.2523-1-dmalcolm@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, 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: David Malcolm via Gcc-patches From: David Malcolm Reply-To: David Malcolm Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" PR testsuite/96609 and PR analyzer/96616 report various testsuite failures seen on powerpc64, aarch64, and arm in new tests added by r11-2694-g808f4dfeb3a95f50f15e71148e5c1067f90a126d. Some of these failures (in gcc.dg/analyzer/init.c, and on arm in gcc.dg/analyzer/casts-1.c) relate to initializations from var_decls in the constant pool. I wrote the tests assuming that the gimplified stmts would initialize the locals via a gassign of code CONSTRUCTOR, whereas on these targets some of the initializations are gassign from a VAR_DECL e.g.: c = *.LC0; where "*.LC0" is a var_decl with DECL_IN_CONSTANT_POOL set. For example, in test_7: struct coord c[2] = {{3, 4}, {5, 6}}; __analyzer_eval (c[0].x == 3); /* { dg-warning "TRUE" } */ after the initialization, the store was simply recording: cluster for: c: INIT_VAL(*.LC0) when I was expecting the cluster for c to have: cluster for: c key: {kind: direct, start: 0, size: 32, next: 32} value: 'int' {(int)3} key: {kind: direct, start: 32, size: 32, next: 64} value: 'int' {(int)4} key: {kind: direct, start: 64, size: 32, next: 96} value: 'int' {(int)5} key: {kind: direct, start: 96, size: 32, next: 128} value: 'int' {(int)6} The test for c[0].x == 3 would then generate: cluster for: _2: (SUB(SUB(INIT_VAL(*.LC0), c[(int)0]), c[(int)0].x)==(int)3) which is UNKNOWN, leading to the test failing. This patch fixes the init.c and casts-1.c failures by special-casing reads from a var_decl with DECL_IN_CONSTANT_POOL set, so that they build a compound_svalue containing the bindings implied by the CONSTRUCTOR node for DECL_INITIAL. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Manually verified the fixes to init.c and casts-1.c on aarch64-unknown-linux-gnu, arm-unknown-eabi, and powerpc64-linux-gnu (-m32 and -m64). Pushed to master as r11-2708-g2867118ddda9b56d991c16022f7d3d634ed08313. This doesn't address the bogus -Wanalyzer-too-complex messages for pr93032-mztools.c reported in the bugs, which seem to be a separate issue that I'm now investigating. gcc/analyzer/ChangeLog: PR testsuite/96609 PR analyzer/96616 * region-model.cc (region_model::get_store_value): Call maybe_get_constant_value on decl_regions first. * region-model.h (decl_region::maybe_get_constant_value): New decl. * region.cc (decl_region::get_stack_depth): Likewise. (decl_region::maybe_get_constant_value): New. * store.cc (get_subregion_within_ctor): New. (binding_map::apply_ctor_to_region): New. * store.h (binding_map::apply_ctor_to_region): New decl. --- gcc/analyzer/region-model.cc | 5 +++ gcc/analyzer/region-model.h | 2 ++ gcc/analyzer/region.cc | 27 +++++++++++++++++ gcc/analyzer/store.cc | 59 ++++++++++++++++++++++++++++++++++++ gcc/analyzer/store.h | 3 ++ 5 files changed, 96 insertions(+) diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 649e20438e4..3c7ea40e8d8 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -1192,6 +1192,11 @@ region_model::get_rvalue (tree expr, region_model_context *ctxt) const svalue * region_model::get_store_value (const region *reg) const { + /* Special-case: handle var_decls in the constant pool. */ + if (const decl_region *decl_reg = reg->dyn_cast_decl_region ()) + if (const svalue *sval = decl_reg->maybe_get_constant_value (m_mgr)) + return sval; + const svalue *sval = m_store.get_any_binding (m_mgr->get_store_manager (), reg); if (sval) diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 33aa3461611..3d044bf8d6c 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -1869,6 +1869,8 @@ public: tree get_decl () const { return m_decl; } int get_stack_depth () const; + const svalue *maybe_get_constant_value (region_model_manager *mgr) const; + private: tree m_decl; }; diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index f3f577c43de..afe416b001b 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -874,6 +874,33 @@ decl_region::get_stack_depth () const return 0; } +/* If the underlying decl is in the global constant pool, + return an svalue representing the constant value. + Otherwise return NULL. */ + +const svalue * +decl_region::maybe_get_constant_value (region_model_manager *mgr) const +{ + if (TREE_CODE (m_decl) == VAR_DECL + && DECL_IN_CONSTANT_POOL (m_decl) + && DECL_INITIAL (m_decl) + && TREE_CODE (DECL_INITIAL (m_decl)) == CONSTRUCTOR) + { + tree ctor = DECL_INITIAL (m_decl); + gcc_assert (!TREE_CLOBBER_P (ctor)); + + /* Create a binding map, applying ctor to it, using this + decl_region as the base region when building child regions + for offset calculations. */ + binding_map map; + map.apply_ctor_to_region (this, ctor, mgr); + + /* Return a compound svalue for the map we built. */ + return mgr->get_or_create_compound_svalue (get_type (), map); + } + return NULL; +} + /* class field_region : public region. */ /* Implementation of region::dump_to_pp vfunc for field_region. */ diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 950a7784542..232920019e0 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -366,6 +366,65 @@ binding_map::dump (bool simple) const pp_flush (&pp); } +/* Get the child region of PARENT_REG based upon INDEX within a + CONSTRUCTOR. */ + +static const region * +get_subregion_within_ctor (const region *parent_reg, tree index, + region_model_manager *mgr) +{ + switch (TREE_CODE (index)) + { + default: + gcc_unreachable (); + case INTEGER_CST: + { + const svalue *index_sval + = mgr->get_or_create_constant_svalue (index); + return mgr->get_element_region (parent_reg, + TREE_TYPE (parent_reg->get_type ()), + index_sval); + } + break; + case FIELD_DECL: + return mgr->get_field_region (parent_reg, index); + } +} + +/* Bind values from CONSTRUCTOR to this map, relative to + PARENT_REG's relationship to its base region. */ + +void +binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor, + region_model_manager *mgr) +{ + gcc_assert (parent_reg); + gcc_assert (TREE_CODE (ctor) == CONSTRUCTOR); + gcc_assert (!CONSTRUCTOR_NO_CLEARING (ctor)); + + unsigned ix; + tree index; + tree val; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, index, val) + { + if (!index) + index = build_int_cst (integer_type_node, ix); + const region *child_reg + = get_subregion_within_ctor (parent_reg, index, mgr); + if (TREE_CODE (val) == CONSTRUCTOR) + apply_ctor_to_region (child_reg, val, mgr); + else + { + gcc_assert (CONSTANT_CLASS_P (val)); + const svalue *cst_sval = mgr->get_or_create_constant_svalue (val); + const binding_key *k + = binding_key::make (mgr->get_store_manager (), child_reg, + BK_direct); + put (k, cst_sval); + } + } +} + /* class binding_cluster. */ /* binding_cluster's copy ctor. */ diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index 4f251d6420f..16bad030b36 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -340,6 +340,9 @@ public: void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const; void dump (bool simple) const; + void apply_ctor_to_region (const region *parent_reg, tree ctor, + region_model_manager *mgr); + private: map_t m_map; };