From patchwork Wed Dec 21 22:25:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 62245 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 639C838493CA for ; Wed, 21 Dec 2022 22:26:40 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from cross.elm.relay.mailchannels.net (cross.elm.relay.mailchannels.net [23.83.212.46]) by sourceware.org (Postfix) with ESMTPS id E2E283858281 for ; Wed, 21 Dec 2022 22:26:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E2E283858281 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gotplt.org 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 555588209FA; Wed, 21 Dec 2022 22:26:08 +0000 (UTC) Received: from pdx1-sub0-mail-a305.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id CB7AA8211BE; Wed, 21 Dec 2022 22:26:07 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1671661567; a=rsa-sha256; cv=none; b=lzaVvycrStvVc5O3KCkmlFTMYzgpZO4Y2pkpOKSyhAhGn6hdbNjE7pvpZiQqe6OYlWabaU hfi39SsHCiylJKwzSbm0M5aiH0WZ5tsID18kd4S56SgKHKyDWshXn6xh9SelzY2yC6wp3u gMlziCZqpJK3qX8DXCWe9Blc3KDjc0MmNH6OaPaKRju8Pk23IIX1/0EJKnw9kP+mA7Rc6F g90I+lXh14j9XwT4rdd0EM9SiZshf3f7Lg+mPc9MQrPHEAHOTpxzMPwggtmerpf64t9hAl 0YGOxnrOjgdPx0nsJ4dulR9LiPb+6urn1IE313Wx6443Fe3DQY8hs20cc4fe2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1671661567; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=RJJVg/5cekSwuTvB3Vuk3R0kCtaoNbyfCe76wcpmwKM=; b=qFXAkWal1GAG/baE1NAe2lDClKglVwvNXBQr5JzNGwrCuqenRNYK5jnklWRYIrSedczc5g Sn4apwPqCUtaHWei5hX3YEYUFpe7Fs2380COFopZlXxy7DPVnSKxma0O+Fr4inABNtdG1N ETVRQSR7vIy5UZdKalemnZjyJIzRUMRxk8S4YG7+QUtjj+KmWCpuIUfKTH04a/D5LqdWMe /z/MdtlbGWmqhlW6wW7y38EINwvI2AGJl4TaNAp/U8dd45+aSRuE8i/NlbpsthcxiYiw+V XHIkyNIvaoS8RIX232CO94Dp5N7PMioEOONZKfcPz3TxZYLZiPSgBaIWWKMnNQ== ARC-Authentication-Results: i=1; rspamd-896578cf5-wlk2c; auth=pass smtp.auth=dreamhost smtp.mailfrom=siddhesh@gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Illustrious-Name: 603608846f65d7a6_1671661568088_762573257 X-MC-Loop-Signature: 1671661568088:1230031640 X-MC-Ingress-Time: 1671661568088 Received: from pdx1-sub0-mail-a305.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.123.200.84 (trex/6.7.1); Wed, 21 Dec 2022 22:26:08 +0000 Received: from fedora.redhat.com (bras-base-toroon4834w-grc-23-76-68-24-147.dsl.bell.ca [76.68.24.147]) (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-a305.dreamhost.com (Postfix) with ESMTPSA id 4Ncp1q1gmFzC3; Wed, 21 Dec 2022 14:26:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gotplt.org; s=dreamhost; t=1671661567; bh=RJJVg/5cekSwuTvB3Vuk3R0kCtaoNbyfCe76wcpmwKM=; h=From:To:Cc:Subject:Date:Content-Transfer-Encoding; b=cm+HZOijv/eaRI+/s5u7CcGWzXrVHQ2cNvfxUx9o01bypv5uPL/reW3u0sa16c6DC iLNu/ys2mXbw1mK8SzEPUfUJ1n2raLlLnN8nCMBI+s6nx8n6XFBqaPTJENBlnJQ1AD rclDSTCzg5bMF2kAIKdsr5bZQ2VaPeCgUWGqtj5/JKCEd7mMtJzcWl4s/4GU+2bcyQ vu4mFOyIV09u4xWk0whxRRH4ca8xe3catUAPx0yQvXLCgEW2ywj7jJpUMvAOHzNLYl Z3Pm+oxA02lyn5+XKMNCmQ6GiJy05T9N59B1Uct6HkBeaF76LnGTbS7F26+f/w3fUC gL3vix0MzdzJg== From: Siddhesh Poyarekar To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com Subject: [PATCH 2/2] tree-object-size: More consistent behaviour with flex arrays Date: Wed, 21 Dec 2022 17:25:54 -0500 Message-Id: <20221221222554.4141678-3-siddhesh@gotplt.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221221222554.4141678-1-siddhesh@gotplt.org> References: <20221221222554.4141678-1-siddhesh@gotplt.org> MIME-Version: 1.0 X-Spam-Status: No, score=-3036.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SCC_5_SHORT_WORD_LINES, 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The tree object size pass tries to fail when it detects a flex array in the struct, but it ends up doing the right thing only when the flex array is in the outermost struct. For nested cases (such as arrays nested in a union or an inner struct), it ends up taking whatever value the flex array is declared with, using zero for the standard flex array, i.e. []. Rework subobject size computation to make it more consistent across the board, honoring -fstrict-flex-arrays. With this change, any array at the end of the struct will end up causing __bos to use the allocated value of the outer object, bailing out in the maximum case when it can't find it. In the minimum case, it will return the subscript value or the allocated value of the outer object, whichever is larger. gcc/ChangeLog: PR tree-optimization/107952 * tree-object-size.cc (size_from_objects): New function. (addr_object_size): Call it. Fully rely on array_ref_flexible_size_p call to determine flex array. gcc/testsuite/ChangeLog: PR tree-optimization/107952 * g++.dg/ext/builtin-object-size1.C (test1, test6, test7, test8): Adjust expected result for object size type 3 and 1. * g++.dg/ext/builtin-object-size2.C (test1, test6, test7, test8): Likewise. * gcc.dg/builtin-object-size-13.c (main): Likewise. * gcc.dg/builtin-object-size-6.c (test1, test6, test7, test8): Likewise. * gcc.dg/builtin-object-size-8.c (main): Likewise. * gcc.dg/builtin-object-size-flex-common.h: Common code for new tests. * gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c: New test. * gcc.dg/builtin-object-size-flex-nested-struct-zero.c: New test. * gcc.dg/builtin-object-size-flex-nested-struct.c: New test. * gcc.dg/builtin-object-size-flex-nested-union-nonzero.c: New test. * gcc.dg/builtin-object-size-flex-nested-union-zero.c: New test. * gcc.dg/builtin-object-size-flex-nested-union.c: New test. * gcc.dg/builtin-object-size-flex-nonzero.c: New test. * gcc.dg/builtin-object-size-flex-zero.c: New test. * gcc.dg/builtin-object-size-flex.c: New test. Signed-off-by: Siddhesh Poyarekar --- .../g++.dg/ext/builtin-object-size1.C | 10 +- .../g++.dg/ext/builtin-object-size2.C | 10 +- gcc/testsuite/gcc.dg/builtin-object-size-13.c | 4 +- gcc/testsuite/gcc.dg/builtin-object-size-6.c | 10 +- gcc/testsuite/gcc.dg/builtin-object-size-8.c | 4 +- .../gcc.dg/builtin-object-size-flex-common.h | 90 +++++++++++ ...n-object-size-flex-nested-struct-nonzero.c | 6 + ...ltin-object-size-flex-nested-struct-zero.c | 6 + .../builtin-object-size-flex-nested-struct.c | 22 +++ ...in-object-size-flex-nested-union-nonzero.c | 6 + ...iltin-object-size-flex-nested-union-zero.c | 6 + .../builtin-object-size-flex-nested-union.c | 28 ++++ .../gcc.dg/builtin-object-size-flex-nonzero.c | 6 + .../gcc.dg/builtin-object-size-flex-zero.c | 6 + .../gcc.dg/builtin-object-size-flex.c | 18 +++ gcc/tree-object-size.cc | 150 ++++++------------ 16 files changed, 265 insertions(+), 117 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex.c diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C index 165b415683b..5b863637123 100644 --- a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C +++ b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C @@ -103,7 +103,7 @@ test1 (A *p) FAIL (); if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) FAIL (); - if (__builtin_object_size (&p->c, 3) != 0) + if (__builtin_object_size (&p->c, 3) != 10) FAIL (); c = p->a; if (__builtin_object_size (c, 3) != sizeof (p->a)) @@ -118,7 +118,7 @@ test1 (A *p) if (__builtin_object_size (c, 3) != sizeof (p->b)) FAIL (); c = (char *) &p->c; - if (__builtin_object_size (c, 3) != 0) + if (__builtin_object_size (c, 3) != 10) FAIL (); } @@ -344,7 +344,7 @@ test6 (struct D *d) { if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) FAIL (); - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) + if (__builtin_object_size (&d->j.a[3], 1) != (size_t) -1) FAIL (); if (__builtin_object_size (&d->j.a[3], 2) != 0) FAIL (); @@ -380,7 +380,7 @@ test7 (struct E *e) FAIL (); if (__builtin_object_size ((char *) &e->j[0], 2) != 0) FAIL (); - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) FAIL (); } @@ -404,7 +404,7 @@ test8 (union F *f) FAIL (); if (__builtin_object_size (&f->d.c[3], 2) != 0) FAIL (); - if (__builtin_object_size (&f->d.c[3], 3) != 0) + if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3) FAIL (); } diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C index c5dbd96193c..665dad886d4 100644 --- a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C +++ b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C @@ -106,7 +106,7 @@ test1 (A *p) FAIL (); if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) FAIL (); - if (__builtin_object_size (&p->c, 3) != 0) + if (__builtin_object_size (&p->c, 3) != 10) FAIL (); c = p->a; if (__builtin_object_size (c, 3) != sizeof (p->a)) @@ -121,7 +121,7 @@ test1 (A *p) if (__builtin_object_size (c, 3) != sizeof (p->b)) FAIL (); c = (char *) &p->c; - if (__builtin_object_size (c, 3) != 0) + if (__builtin_object_size (c, 3) != 10) FAIL (); } @@ -347,7 +347,7 @@ test6 (struct D *d) { if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) FAIL (); - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) + if (__builtin_object_size (&d->j.a[3], 1) != (size_t) -1) FAIL (); if (__builtin_object_size (&d->j.a[3], 2) != 0) FAIL (); @@ -383,7 +383,7 @@ test7 (struct E *e) FAIL (); if (__builtin_object_size ((char *) &e->j[0], 2) != 0) FAIL (); - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) FAIL (); } @@ -407,7 +407,7 @@ test8 (union F *f) FAIL (); if (__builtin_object_size (&f->d.c[3], 2) != 0) FAIL (); - if (__builtin_object_size (&f->d.c[3], 3) != 0) + if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3) FAIL (); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-13.c b/gcc/testsuite/gcc.dg/builtin-object-size-13.c index c7d58c941d4..6429dcaf426 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-13.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-13.c @@ -332,9 +332,9 @@ main (void) o2 = __builtin_offsetof (struct H, h2.e1.c2); h1 = malloc (s); h2 = malloc (o2 + 212); - TA (h1->h2.e1.c2.a2, s - o2, sizeof (h1->h2.e1.c2.a2)); + TA (h1->h2.e1.c2.a2, s - o2, s - o2); s = o2 + 212; - TA (h2->h2.e1.c2.a2, s - o2, sizeof (h2->h2.e1.c2.a2)); + TA (h2->h2.e1.c2.a2, s - o2, s - o2); free (h2); free (h1); s = sizeof (struct H); diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-6.c b/gcc/testsuite/gcc.dg/builtin-object-size-6.c index 4ce05184143..1ae608d456b 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-6.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-6.c @@ -103,7 +103,7 @@ test1 (struct A *p) FAIL (); if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) FAIL (); - if (__builtin_object_size (&p->c, 3) != 0) + if (__builtin_object_size (&p->c, 3) != 10) FAIL (); c = p->a; if (__builtin_object_size (c, 3) != sizeof (p->a)) @@ -118,7 +118,7 @@ test1 (struct A *p) if (__builtin_object_size (c, 3) != sizeof (p->b)) FAIL (); c = (char *) &p->c; - if (__builtin_object_size (c, 3) != 0) + if (__builtin_object_size (c, 3) != 10) FAIL (); } @@ -344,7 +344,7 @@ test6 (struct D *d) { if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) FAIL (); - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) + if (__builtin_object_size (&d->j.a[3], 1) != -1) FAIL (); if (__builtin_object_size (&d->j.a[3], 2) != 0) FAIL (); @@ -380,7 +380,7 @@ test7 (struct E *e) FAIL (); if (__builtin_object_size ((char *) &e->j[0], 2) != 0) FAIL (); - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) FAIL (); } @@ -404,7 +404,7 @@ test8 (union F *f) FAIL (); if (__builtin_object_size (&f->d.c[3], 2) != 0) FAIL (); - if (__builtin_object_size (&f->d.c[3], 3) != 0) + if (__builtin_object_size (&f->d.c[3], 3) != 7) FAIL (); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-8.c b/gcc/testsuite/gcc.dg/builtin-object-size-8.c index f67902e29f0..184769f1bd8 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-8.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-8.c @@ -186,13 +186,13 @@ main (void) TS (h1->h1, s); TS (h1->h2.e1.c1, s - o); TS (h1->h2.e1.c2.a1, s - o2); - TA (h1->h2.e1.c2.a2, s - o2, sizeof (h1->h2.e1.c2.a2)); + TA (h1->h2.e1.c2.a2, s - o2, s - o2); TF (h1->h2.e2, s - o); s = o2 + 212; TS (h2->h1, s); TS (h2->h2.e1.c1, s - o); TS (h2->h2.e1.c2.a1, s - o2); - TA (h2->h2.e1.c2.a2, s - o2, sizeof (h2->h2.e1.c2.a2)); + TA (h2->h2.e1.c2.a2, s - o2, s - o2); TF (h2->h2.e2, s - o); free (h2); free (h1); diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h b/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h new file mode 100644 index 00000000000..b8b68da762d --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h @@ -0,0 +1,90 @@ +#include "builtin-object-size-common.h" + +typedef __SIZE_TYPE__ size_t; + +void +__attribute__ ((noinline)) +test_flexarray_allocate (const char *name) +{ + size_t n = sizeof (flex_t); + + if (name != (void *) 0) + n += __builtin_strlen (name) + 1; + + flex_t *p = __builtin_malloc (n); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + __builtin_free (p); +} + +void +__attribute__ ((noinline)) +__attribute__ ((access (read_only, 1, 2))) +test_flexarray_access (flex_t *p, size_t sz) +{ + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) + FAIL (); +} + +void +__attribute__ ((noinline)) +test_flexarray_none (flex_t *p) +{ + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) != -1) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) != -1) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) != 0) + FAIL (); + + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) != SIZEOF_FLEX_ARRAY) + FAIL (); +} + +int +main (int argc, char **argv) +{ + const char *str = "qwertyuiopasdfgghjklzxcvbnm"; + + test_flexarray_allocate (str); + + const size_t sz = 1024; + flex_t *p = __builtin_malloc (sz * sizeof (*p)); + + test_flexarray_access (p, sz); + + test_flexarray_none (p); + __builtin_free (p); + + DONE (); +} diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c new file mode 100644 index 00000000000..c50cd89a817 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 4 + +#include "builtin-object-size-flex-nested-struct.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c new file mode 100644 index 00000000000..554aece0b46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 0 + +#include "builtin-object-size-flex-nested-struct.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c new file mode 100644 index 00000000000..1adeac16ac4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#ifndef SIZEOF_FLEX_ARRAY +# define SIZEOF_FLEX_ARRAY_DECL +# define SIZEOF_FLEX_ARRAY 0 +#else +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY +#endif + +typedef struct { + unsigned pad; + struct { + unsigned pad; + char data[SIZEOF_FLEX_ARRAY_DECL]; + } s; +} flex_t; + +#define FLEX_ARRAY(p) p->s.data +#define SIZE_OF_FLEX sizeof (unsigned) + sizeof (unsigned) + +#include "builtin-object-size-flex-common.h" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c new file mode 100644 index 00000000000..58e387c8db6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 4 + +#include "builtin-object-size-flex-nested-union.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c new file mode 100644 index 00000000000..ec6429a5a9b --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 0 + +#include "builtin-object-size-flex-nested-union.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c new file mode 100644 index 00000000000..8326131c890 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#ifndef SIZEOF_FLEX_ARRAY +# define SIZEOF_FLEX_ARRAY_DECL +# define SIZEOF_FLEX_ARRAY 0 +#else +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY +#endif + +typedef struct { + unsigned pad; + union { + struct { + unsigned pad; + char data[SIZEOF_FLEX_ARRAY_DECL]; + } s1; + struct { + unsigned pad; + char data[SIZEOF_FLEX_ARRAY_DECL]; + } s2; + } u; +} flex_t; + +#define FLEX_ARRAY(p) p->u.s1.data +#define SIZE_OF_FLEX sizeof (unsigned) + sizeof (unsigned) + +#include "builtin-object-size-flex-common.h" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c new file mode 100644 index 00000000000..693d2e98758 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 4 + +#include "builtin-object-size-flex.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c new file mode 100644 index 00000000000..f38d0e01d4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define SIZEOF_FLEX_ARRAY 0 + +#include "builtin-object-size-flex.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex.c b/gcc/testsuite/gcc.dg/builtin-object-size-flex.c new file mode 100644 index 00000000000..34aba8942d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#ifndef SIZEOF_FLEX_ARRAY +# define SIZEOF_FLEX_ARRAY_DECL +# define SIZEOF_FLEX_ARRAY 0 +#else +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY +#endif + +typedef struct { + unsigned pad; + char data[SIZEOF_FLEX_ARRAY_DECL]; +} flex_t; + +#define FLEX_ARRAY(p) p->data + +#include "builtin-object-size-flex-common.h" diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index d9f25397c71..98ee3c2b527 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -499,6 +499,19 @@ decl_init_size (tree decl, bool min) return size; } +/* Return the size of SUBOBJ that is within VAR where the latter has VAR_SIZE + size. */ + +static tree +size_from_objects (const_tree subobj, const_tree var, tree var_size, + int object_size_type) +{ + tree bytes = compute_object_offset (subobj, var); + + return (bytes != error_mark_node ? size_for_offset (var_size, bytes) + : size_unknown (object_size_type)); +} + /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. If unknown, return size_unknown (object_size_type). */ @@ -589,105 +602,52 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, { var = TREE_OPERAND (ptr, 0); + /* Get the immediate containing subobject. Skip over conversions + because we don't need them. */ while (var != pt_var - && TREE_CODE (var) != BIT_FIELD_REF - && TREE_CODE (var) != COMPONENT_REF - && TREE_CODE (var) != ARRAY_REF - && TREE_CODE (var) != ARRAY_RANGE_REF - && TREE_CODE (var) != REALPART_EXPR - && TREE_CODE (var) != IMAGPART_EXPR) + && (!handled_component_p (var) + || TREE_CODE (var) == VIEW_CONVERT_EXPR)) var = TREE_OPERAND (var, 0); if (var != pt_var && TREE_CODE (var) == ARRAY_REF) var = TREE_OPERAND (var, 0); + + /* If the subobject size cannot be easily inferred or is smaller than + the whole size, just use the whole size. */ if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))) || (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; - else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) - { - tree v = var; - /* For &X->fld, compute object size if fld isn't a flexible array - member. */ - bool is_flexible_array_mem_ref = false; - while (v && v != pt_var) - switch (TREE_CODE (v)) - { - case ARRAY_REF: - 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)) - { - v = NULL_TREE; - break; - } - } - v = TREE_OPERAND (v, 0); - break; - case REALPART_EXPR: - case IMAGPART_EXPR: - v = NULL_TREE; - break; - case COMPONENT_REF: - if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) - { - v = NULL_TREE; - break; - } - is_flexible_array_mem_ref = array_ref_flexible_size_p (v); - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) - != UNION_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) - != QUAL_UNION_TYPE) - break; - else - v = TREE_OPERAND (v, 0); - if (TREE_CODE (v) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) - == RECORD_TYPE) - { - /* compute object size only if v is not a - flexible array member. */ - if (!is_flexible_array_mem_ref) - { - v = NULL_TREE; - break; - } - v = TREE_OPERAND (v, 0); - } - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) - != UNION_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) - != QUAL_UNION_TYPE) - break; - else - v = TREE_OPERAND (v, 0); - if (v != pt_var) - v = NULL_TREE; - else - v = pt_var; - break; - default: - v = pt_var; - break; - } - if (v == pt_var) - var = pt_var; - } } else var = pt_var; + bool is_flexible_array_mem_ref = false; + /* Find out if this is a flexible array. This will change + according to -fstrict-flex-arrays. */ + if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) + is_flexible_array_mem_ref = array_ref_flexible_size_p (var); + + /* We cannot get a maximum estimate for a flex array without the + whole object size. */ + if (is_flexible_array_mem_ref && !pt_var_size + && !(object_size_type & OST_MINIMUM)) + return false; + if (var != pt_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); + /* For flexible arrays, we prefer the size based on the whole object + if it is available. */ + if (is_flexible_array_mem_ref && pt_var_size) + var_size = size_from_objects (var, pt_var, pt_var_size, + object_size_type); + else + { + 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; } @@ -695,23 +655,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, return false; else var_size = pt_var_size; - bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); - if (bytes != error_mark_node) + + bytes = size_from_objects (TREE_OPERAND (ptr, 0), var, var_size, + object_size_type); + + if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF + && !is_flexible_array_mem_ref) { - bytes = size_for_offset (var_size, bytes); - if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF) - { - tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), - pt_var); - if (bytes2 != error_mark_node) - { - bytes2 = size_for_offset (pt_var_size, bytes2); - bytes = size_binop (MIN_EXPR, bytes, bytes2); - } - } + tree bytes2 = size_from_objects (TREE_OPERAND (ptr, 0), pt_var, + pt_var_size, object_size_type); + bytes = size_binop (MIN_EXPR, bytes, bytes2); } - else - bytes = size_unknown (object_size_type); wholebytes = object_size_type & OST_SUBOBJECT ? var_size : pt_var_wholesize;