From patchwork Tue Nov 9 19:01:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 1553138 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gotplt.org header.i=@gotplt.org header.a=rsa-sha1 header.s=gotplt.org header.b=EHrw4rwO; dkim-atps=neutral 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+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4HpctN6LRYz9sCD for ; Wed, 10 Nov 2021 06:07:23 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D280E3857C47 for ; Tue, 9 Nov 2021 19:07:21 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from eggs.gnu.org (eggs.gnu.org [209.51.188.92]) by sourceware.org (Postfix) with ESMTPS id 4E1CD3858020 for ; Tue, 9 Nov 2021 19:02:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4E1CD3858020 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=gotplt.org Received: from antelope.elm.relay.mailchannels.net ([23.83.212.4]:62989) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkWNs-0008Hq-3k for gcc-patches@gcc.gnu.org; Tue, 09 Nov 2021 14:02:19 -0500 X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id CDAF0402131; Tue, 9 Nov 2021 19:02:11 +0000 (UTC) Received: from pdx1-sub0-mail-a306.dreamhost.com (100-96-133-198.trex.outbound.svc.cluster.local [100.96.133.198]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 11FFD4022F1; Tue, 9 Nov 2021 19:02:11 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from pdx1-sub0-mail-a306.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.96.133.198 (trex/6.4.3); Tue, 09 Nov 2021 19:02:11 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-White-Shoe: 606e60af18309de0_1636484531420_1323757841 X-MC-Loop-Signature: 1636484531420:1065136300 X-MC-Ingress-Time: 1636484531419 Received: from rhbox.redhat.com (unknown [1.186.121.127]) (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) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a306.dreamhost.com (Postfix) with ESMTPSA id 4HpcmK0rcnz1Wh; Tue, 9 Nov 2021 11:02:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gotplt.org; s=gotplt.org; t=1636484530; bh=fgUBvOUoKj0BqtqVAxrz+qf6sk4=; h=From:To:Cc:Subject:Date:Content-Transfer-Encoding; b=EHrw4rwOj8/B2g5SyhdZg+w5jx3stioFcXzswrUWKMKrwM4szLDPW4a4nZtuip1S7 bm5EC/pnYPRuH/n17fFtBNKAAyXxxWmDcvWOBIcT2QMKGGvSAo7kIi4WiuT44oicuK HLzJZCaEDZ8AtfyZvmcbA1+Crpxb3t9087Mrg6sw= From: Siddhesh Poyarekar To: gcc-patches@gcc.gnu.org Subject: [PATCH 09/10] tree-object-size: Dynamic sizes for ADDR_EXPR Date: Wed, 10 Nov 2021 00:31:35 +0530 Message-Id: <20211109190137.1107736-10-siddhesh@gotplt.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211109190137.1107736-1-siddhesh@gotplt.org> References: <20211109190137.1107736-1-siddhesh@gotplt.org> MIME-Version: 1.0 Received-SPF: pass client-ip=23.83.212.4; envelope-from=siddhesh@gotplt.org; helo=antelope.elm.relay.mailchannels.net X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_SBL=0.141, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Status: No, score=-3038.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_SBL, SPF_FAIL, SPF_HELO_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: , Cc: jakub@redhat.com Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Allow dynamic expressions from ADDR_EXPR for __builtin_dynamic_object_size. Offsets in objects still need to be constant for now because offset computation need more validation to support, e.g. negative offsets with dynamic sizes. gcc/ChangeLog: * tree-object-size.c (size_known_p): New function. (addr_object_size): Build dynamic expressions for object sizes. (estimate_size): Limit PLUS_EXPR rewriting to static object sizes. (call_object_size): Call size_known_p. gcc/testsuite/ChangeLog: * gcc.dg/builtin-dynamic-object-size-0.c: Add new tests. * gcc.dg/builtin-object-size-1.c (test1) [DYNAMIC_OBJECT_SIZE]: Adjust expected output for dynamic object sizes. * gcc.dg/builtin-object-size-2.c (test1) [DYNAMIC_OBJECT_SIZE]: Likewise. * gcc.dg/builtin-object-size-3.c (test1) [DYNAMIC_OBJECT_SIZE]: Likewise. * gcc.dg/builtin-object-size-4.c (test1) [DYNAMIC_OBJECT_SIZE]: Likewise. Signed-off-by: Siddhesh Poyarekar --- .../gcc.dg/builtin-dynamic-object-size-0.c | 71 ++++++++++++++ gcc/testsuite/gcc.dg/builtin-object-size-1.c | 30 +++++- gcc/testsuite/gcc.dg/builtin-object-size-2.c | 43 +++++++-- gcc/testsuite/gcc.dg/builtin-object-size-3.c | 25 ++++- gcc/testsuite/gcc.dg/builtin-object-size-4.c | 17 ++-- gcc/tree-object-size.c | 93 +++++++++++-------- 6 files changed, 221 insertions(+), 58 deletions(-) diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c index 4ad49a51878..a1db63b2d45 100644 --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c @@ -219,6 +219,60 @@ test_deploop (size_t sz, size_t cond) return __builtin_dynamic_object_size (bin, 0); } +/* Address expressions. */ + +struct dynarray_struct +{ + long a; + char c[16]; + int b; +}; + +size_t +__attribute__ ((noinline)) +test_dynarray_struct (size_t sz, size_t off) +{ + struct dynarray_struct bin[sz]; + + return __builtin_dynamic_object_size (&bin[off].c, 0); +} + +size_t +__attribute__ ((noinline)) +test_dynarray_struct_subobj (size_t sz, size_t off) +{ + struct dynarray_struct bin[sz]; + + return __builtin_dynamic_object_size (&bin[off].c[4], 1); +} + +size_t +__attribute__ ((noinline)) +test_dynarray_struct_subobj2 (size_t sz, size_t off, size_t *objsz) +{ + struct dynarray_struct2 + { + long a; + int b; + char c[sz]; + }; + + struct dynarray_struct2 bin; + + *objsz = sizeof (bin); + + return __builtin_dynamic_object_size (&bin.c[off], 1); +} + +size_t +__attribute__ ((noinline)) +test_substring (size_t sz, size_t off) +{ + char str[sz]; + + return __builtin_dynamic_object_size (&str[off], 0); +} + size_t __attribute__ ((access (__read_write__, 1, 2))) test_parmsz_simple (void *obj, size_t sz) @@ -286,6 +340,23 @@ main (int argc, char **argv) FAIL (); if (test_dynarray (__builtin_strlen (argv[0])) != __builtin_strlen (argv[0])) FAIL (); + if (test_dynarray_struct (42, 4) != + ((42 - 4) * sizeof (struct dynarray_struct) + - __builtin_offsetof (struct dynarray_struct, c))) + FAIL (); + if (test_dynarray_struct (42, 48) != 0) + FAIL (); + if (test_substring (128, 4) != 128 - 4) + FAIL (); + if (test_substring (128, 142) != 0) + FAIL (); + if (test_dynarray_struct_subobj (42, 4) != 16 - 4) + FAIL (); + if (test_dynarray_struct_subobj (42, 48) != 0) + FAIL (); + size_t objsz = 0; + if (test_dynarray_struct_subobj2 (42, 4, &objsz) != objsz - 4 - 12) + FAIL (); if (test_dynarray_cond (0) != 16) FAIL (); if (test_dynarray_cond (1) != 8) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-object-size-1.c index 606141f9405..ba5a34c1f8e 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c @@ -81,30 +81,56 @@ test1 (void *q, int x) r = malloc (30); else r = calloc (2, 16); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else /* We may duplicate this test onto the two exit paths. On one path the size will be 32, the other it will be 30. If we don't duplicate this test, then the size will be 32. */ if (__builtin_object_size (r, 0) != 2 * 16 && __builtin_object_size (r, 0) != 30) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 14); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 14)) + abort (); +#else if (__builtin_object_size (r, 0) != 30) abort (); +#endif if (x < 30) r = malloc (sizeof (a)); else r = &a.a[3]; +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a)) abort (); +#endif r = memcpy (r, "a", 2); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a)) abort (); +#endif r = memcpy (r + 2, "b", 2) + 2; +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) + != (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a) - 4) abort (); +#endif r = &a.a[4]; r = memset (r, 'a', 2); if (__builtin_object_size (r, 0) @@ -140,14 +166,16 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 0) != x) abort (); + if (__builtin_object_size (&var[5], 0) != x + 5) + abort (); #else if (__builtin_object_size (var, 0) != (size_t) -1) abort (); if (__builtin_object_size (var + 10, 0) != (size_t) -1) abort (); -#endif if (__builtin_object_size (&var[5], 0) != (size_t) -1) abort (); +#endif if (__builtin_object_size (zerol, 0) != 0) abort (); if (__builtin_object_size (&zerol, 0) != 0) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c index 57fd17d5a45..4af30e8c580 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c @@ -75,30 +75,56 @@ test1 (void *q, int x) r = malloc (30); else r = calloc (2, 16); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else /* We may duplicate this test onto the two exit paths. On one path the size will be 32, the other it will be 30. If we don't duplicate this test, then the size will be 32. */ if (__builtin_object_size (r, 1) != 2 * 16 && __builtin_object_size (r, 1) != 30) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 14); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 14)) + abort (); +#else if (__builtin_object_size (r, 1) != 30) abort (); +#endif if (x < 30) r = malloc (sizeof (a)); else r = &a.a[3]; +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a)) abort (); +#endif r = memcpy (r, "a", 2); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a)) abort (); +#endif r = memcpy (r + 2, "b", 2) + 2; +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 0) + != (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a) - 4) abort (); +#endif r = &a.a[4]; r = memset (r, 'a', 2); if (__builtin_object_size (r, 1) != sizeof (a.a) - 4) @@ -142,27 +168,28 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 1) != x) abort (); + if (__builtin_object_size (&var[5], 1) != x + 5) + abort (); + if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A)) + abort (); + if (__builtin_object_size (&vara[5], 1) != (x + 5) * sizeof (struct A)) + abort (); #else if (__builtin_object_size (var, 1) != (size_t) -1) abort (); if (__builtin_object_size (var + 10, 1) != (size_t) -1) abort (); -#endif if (__builtin_object_size (&var[5], 1) != (size_t) -1) abort (); -#ifdef DYNAMIC_OBJECT_SIZE - if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A)) - abort (); - if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A)) - abort (); -#else if (__builtin_object_size (vara, 1) != (size_t) -1) abort (); if (__builtin_object_size (vara + 10, 1) != (size_t) -1) abort (); -#endif if (__builtin_object_size (&vara[5], 1) != (size_t) -1) abort (); +#endif if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a)) abort (); if (__builtin_object_size (&vara[10].a[0], 1) != sizeof (vara[0].a)) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-3.c index 5b323ca3527..ce4418e785b 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c @@ -42,9 +42,17 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (q, 2) != 0) abort (); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 2) + != (x < 0 + ? sizeof (a) - __builtin_offsetof (struct A, a) - 9 + : sizeof (a) - __builtin_offsetof (struct A, c) - 1)) + abort (); +#else if (__builtin_object_size (r, 2) != sizeof (a) - __builtin_offsetof (struct A, c) - 1) abort (); +#endif if (x < 6) r = &w[2].a[1]; else @@ -58,15 +66,28 @@ test1 (void *q, int x) if (__builtin_object_size (&y.b, 2) != sizeof (a) - __builtin_offsetof (struct A, b)) abort (); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 2) + != (x < 6 + ? 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1 + : sizeof (a) - __builtin_offsetof (struct A, a) - 6)) + abort (); +#else if (__builtin_object_size (r, 2) != sizeof (a) - __builtin_offsetof (struct A, a) - 6) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 16); +#ifdef DYNAMIC_OBJECT_SIZE + if (__builtin_object_size (r, 2) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else if (__builtin_object_size (r, 2) != 30) abort (); +#endif if (x < 20) r = malloc (30); else @@ -145,14 +166,16 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 2) != x) abort (); + if (__builtin_object_size (&var[5], 2) != x + 5) + abort (); #else if (__builtin_object_size (var, 2) != 0) abort (); if (__builtin_object_size (var + 10, 2) != 0) abort (); -#endif if (__builtin_object_size (&var[5], 2) != 0) abort (); +#endif if (__builtin_object_size (zerol, 2) != 0) abort (); if (__builtin_object_size (&zerol, 2) != 0) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c index 2d222301eff..81e0255dcc4 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -155,27 +155,28 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 3) != x) abort (); + if (__builtin_object_size (&var[5], 3) != x + 5) + abort (); + if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A)) + abort (); + if (__builtin_object_size (&vara[5], 3) != (x + 5) * sizeof (struct A)) + abort (); #else if (__builtin_object_size (var, 3) != 0) abort (); if (__builtin_object_size (var + 10, 3) != 0) abort (); -#endif if (__builtin_object_size (&var[5], 3) != 0) abort (); -#ifdef DYNAMIC_OBJECT_SIZE - if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A)) - abort (); - if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A)) - abort (); -#else if (__builtin_object_size (vara, 3) != 0) abort (); if (__builtin_object_size (vara + 10, 3) != 0) abort (); -#endif if (__builtin_object_size (&vara[5], 3) != 0) abort (); +#endif if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a)) abort (); if (__builtin_object_size (&vara[10].a[0], 3) != sizeof (vara[0].a)) diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index d5b0c8226f0..865fc3feea5 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -123,6 +123,16 @@ size_unknown_p (tree val, int object_size_type) && tree_to_uhwi (val) == unknown (object_size_type)); } +/* Return true if VAL is represents a known size for OBJECT_SIZE_TYPE. */ + +static inline bool +size_known_p (tree val, int object_size_type) +{ + return (!size_unknown_p (val, object_size_type) + && ((object_size_type & OST_DYNAMIC) + || TREE_CODE (val) == INTEGER_CST)); +} + /* Return a tree with initial value for OBJECT_SIZE_TYPE. */ static inline tree @@ -391,16 +401,15 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (!size_unknown_p (sz, object_size_type)) { tree offset = TREE_OPERAND (pt_var, 1); - if (TREE_CODE (offset) != INTEGER_CST - || TREE_CODE (sz) != INTEGER_CST) + if (TREE_CODE (offset) != INTEGER_CST) sz = size_unknown (object_size_type); else sz = size_for_offset (sz, offset); } if (!size_unknown_p (sz, object_size_type) - && TREE_CODE (sz) == INTEGER_CST - && compare_tree_int (sz, offset_limit) < 0) + && (TREE_CODE (sz) != INTEGER_CST + || compare_tree_int (sz, offset_limit) < 0)) pt_var_size = sz; } else if (DECL_P (pt_var)) @@ -416,8 +425,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (pt_var_size) { - /* Validate the size determined above. */ - if (compare_tree_int (pt_var_size, offset_limit) >= 0) + /* Validate the size determined above if it is a constant. */ + if (TREE_CODE (pt_var_size) == INTEGER_CST + && compare_tree_int (pt_var_size, offset_limit) >= 0) return false; } @@ -441,7 +451,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, var = TREE_OPERAND (var, 0); if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))) - || (pt_var_size + || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST && tree_int_cst_lt (pt_var_size, TYPE_SIZE_UNIT (TREE_TYPE (var))))) var = pt_var; @@ -455,17 +465,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, switch (TREE_CODE (v)) { case ARRAY_REF: - if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0))) - && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST) + if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))) { tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0))); - if (domain - && TYPE_MAX_VALUE (domain) - && TREE_CODE (TYPE_MAX_VALUE (domain)) - == INTEGER_CST - && tree_int_cst_lt (TREE_OPERAND (v, 1), - TYPE_MAX_VALUE (domain))) + if (domain && TYPE_MAX_VALUE (domain)) { v = NULL_TREE; break; @@ -532,20 +536,20 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, var = pt_var; if (var != pt_var) - var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + { + var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + if (!TREE_CONSTANT (var_size)) + var_size = get_or_create_ssa_default_def (cfun, var_size); + if (!var_size) + return false; + } else if (!pt_var_size) return false; else var_size = pt_var_size; bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); if (bytes != error_mark_node) - { - if (TREE_CODE (bytes) == INTEGER_CST - && tree_int_cst_lt (var_size, bytes)) - bytes = size_zero_node; - else - bytes = size_binop (MINUS_EXPR, var_size, bytes); - } + bytes = size_for_offset (var_size, bytes); if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF @@ -554,11 +558,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var); if (bytes2 != error_mark_node) { - if (TREE_CODE (bytes2) == INTEGER_CST - && tree_int_cst_lt (pt_var_size, bytes2)) - bytes2 = size_zero_node; - else - bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2); + bytes2 = size_for_offset (pt_var_size, bytes2); bytes = size_binop (MIN_EXPR, bytes, bytes2); } } @@ -568,8 +568,13 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, else bytes = pt_var_size; - *psize = bytes; - return true; + if (size_known_p (bytes, object_size_type)) + { + *psize = bytes; + return true; + } + + return false; } @@ -739,19 +744,27 @@ estimate_size (object_size_info *osi, tree size, bitmap *visitlog = NULL) case PLUS_EXPR: { tree ret = estimate_size (osi, TREE_OPERAND (size, 0), visitlog); + tree off = TREE_OPERAND (size, 1); if (size_unknown_p (ret, object_size_type)) return size_unknown (object_size_type); - tree off = TREE_OPERAND (size, 1); - gcc_checking_assert (TREE_CODE (off) == INTEGER_CST); - - if (code == PLUS_EXPR) - off = fold_build1 (NEGATE_EXPR, sizetype, off); - - if (tree_fits_uhwi_p (ret) && tree_int_cst_le (ret, off)) - return size_int (0); - return size_binop (MINUS_EXPR, ret, off); + /* We don't need this for dynamic object sizes because we don't make + reducing estimates like in case of static sizes. Instead, we + return an expression that gives the precise size after a specific + number of iterations, reducing to zero at runtime if the pointer + being evaluated overflows. */ + if (!(object_size_type & OST_DYNAMIC)) + { + gcc_checking_assert (TREE_CODE (off) == INTEGER_CST); + if (code == PLUS_EXPR) + { + off = fold_build1 (NEGATE_EXPR, sizetype, off); + ret = size_binop (MAX_EXPR, ret, off); + code = MINUS_EXPR; + } + } + return size_binop (code, ret, off); } case INTEGER_CST: default: @@ -1163,7 +1176,7 @@ call_object_size (struct object_size_info *osi, gcall *call) tree bytes = alloc_object_size (call, object_size_type); - if ((object_size_type & OST_DYNAMIC) || TREE_CODE (bytes) == INTEGER_CST) + if (size_known_p (bytes, object_size_type)) return bytes; return size_unknown (object_size_type);