From patchwork Tue Jan 31 14:11:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qing Zhao X-Patchwork-Id: 64019 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 B764B384FFF1 for ; Tue, 31 Jan 2023 14:32:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B764B384FFF1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1675175538; bh=m2V633LSuROXnSpjmgkajYEStu1WBiVVeFItamCPelA=; 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=ob+li5JUr3n/mafbveIPX4Jsi5ZOL0oyoRaBe++hRvlpa3yQTwNjYFmY9xrgtKUAZ dSdPluQOYEf39ANmrhxmWcwaEs2Gw/sk72S1xQ1aHc8N3q+F3uVPJCNbsd41UaQoBG fxINAhNhGViDwZMZ0I9LdmdGCiN4RjKGcQK5Jpak= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from eggs.gnu.org (eggs.gnu.org [IPv6:2001:470:142:3::10]) by sourceware.org (Postfix) with ESMTPS id 344B6385F371 for ; Tue, 31 Jan 2023 14:31:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 344B6385F371 Received: from mx0a-00069f02.pphosted.com ([205.220.165.32]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pMrNW-0005lI-96 for gcc-patches@gcc.gnu.org; Tue, 31 Jan 2023 09:12:57 -0500 Received: from pps.filterd (m0333521.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30VEAqaP022167; Tue, 31 Jan 2023 14:11:51 GMT Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.appoci.oracle.com [138.1.114.2]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3ncvp15n54-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Jan 2023 14:11:51 +0000 Received: from pps.filterd (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30VE0wYS031873; Tue, 31 Jan 2023 14:11:50 GMT Received: from nam02-sn1-obe.outbound.protection.outlook.com (mail-sn1nam02lp2044.outbound.protection.outlook.com [104.47.57.44]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3nct55qj5e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Jan 2023 14:11:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Zgf4doaM+HqqjV99fKZ5nr8Qg0ekobfifHvwrqwSf3DbTVo8i+a/0S+fGfffczZBPaaEPtotKsMdxkcFJLjEjtWBzlKd4KPPaMw7KlQOh2fHSkiOYvdMNwrxeRwtMPzVt2ygttVszaYb/eMm8yRogNFRd5JWjismXt0E8mNQ8sIA9E6Kb9fmex64uyavKzhlQcB2cFKLL4HdhPQ203ldlC1CiM6hXXLCxunEcDKGq3JN2w0W47nqFYb0cuGWDPR1ZBJMPM0Ygf5Vgfj4hNz7r0U+opB7gtfkxc7Y6D5OXvggAODYTFh2zn8VgeCqp+4WJkB4F8VzWRtzkDmb2Nt7yQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=m2V633LSuROXnSpjmgkajYEStu1WBiVVeFItamCPelA=; b=FqIm0IQ9DJ5HgPi+aE437lHyvrJ7BpbnOO7BJENzJNufesoymOujUjLZMOor+OU9vpL2W2GtLM0KdRtuULaAhNktFyps+yLh2RkK18hM4SVXBwHkHAORImM4ub0cqZjAv7ZR2kAOGyEr1aHArRWbGZG4Ed5xo5QhVCKhI2R0C8ghLuK6FfXfGFXv99+fYDB37MBb2dRfmcaItL7nWF1iWe0lEJlG9mGu3G2n4Tomi8C9UYQjwA2q/V2/EPvCAG3tvhnctAIVnLzdNR7Xd3JylPW1CfotsbW9zfV58++v735aIMeUWe7aJQcTHnJSaJlCMjENYD5sCPFVFzNx2hN5CA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none Received: from CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) by CH3PR10MB7434.namprd10.prod.outlook.com (2603:10b6:610:15b::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6064.17; Tue, 31 Jan 2023 14:11:48 +0000 Received: from CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::c96c:cb50:dea2:2cd2]) by CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::c96c:cb50:dea2:2cd2%5]) with mapi id 15.20.6064.021; Tue, 31 Jan 2023 14:11:48 +0000 To: rguenther@suse.de Cc: gcc-patches@gcc.gnu.org, siddhesh@gotplt.org, keescook@chromium.org, Qing Zhao Subject: [PATCH 1/2] Handle component_ref to a structre/union field including flexible array member [PR101832] Date: Tue, 31 Jan 2023 14:11:39 +0000 Message-Id: <20230131141140.3610133-2-qing.zhao@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230131141140.3610133-1-qing.zhao@oracle.com> References: <20230131141140.3610133-1-qing.zhao@oracle.com> X-ClientProxiedBy: SA1PR02CA0013.namprd02.prod.outlook.com (2603:10b6:806:2cf::11) To CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR10MB4344:EE_|CH3PR10MB7434:EE_ X-MS-Office365-Filtering-Correlation-Id: 4b2d80ce-7cb8-424a-3870-08db03951766 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: aUmHSVvj+Ho4EO3dDU0UlUmC/FhE/N3ZYe6GxFYrrjmBYFEGnzEaMYJoXXWthElpK8ZhQeVd6aZVpWaQzUNrsCpfcwuxKfxVdFheug3F3cmiKFbVfS1ylnr2V7yLtjqaM+siGW9q1vTaRd2F+Zr8lBFVBSMJveN30MrH2Q1rPqAQl9M5I6fEeXxkGLFp93UNux/g5bnUuXj4f49l46LZ0GQAIEkSp8BC6BuaDa7PUzcgdENPX0U6vvyuNpR7WNWVLKuG0ZfsewyRAgLbBWO+CwDKLYeFZLsBjJmL+cX+63Z5TVO/ulYpkvDjIlJMPUoqtrCIp/daUddhfK+W4wReWX6g6bZSN5V0K+a6D4KVYOjUSI5lC4JPJ9UsaKerERnoaP4zJq8uesik8ZS0vxf8VVHI80QY/BoBY1Sn4Jibq5UbSeObJoRcxc99gzFozJlYZ8p03/KxP9Hhpl5XPu9Zjb6Pzex0uEDgpLm+VGq0mHtGec0RZ3zIMd/0hsNFGe5F/X5lrRrXX3AIL8kQsEYpiP+fUjbvQFV1s9gKrjK8Wd0J2nkIPJI7VE0ypDOsnZezLalZKpYZiVUamXdOQ+awCpBhQEaU9M2UeT+Oi0qnD5V5i7ZAAGRK5lhrkgvtyrhtU0pNb4vJnNoGTEjG8/SpMWHGzrYaB5jYd6JoHRMde2w= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR10MB4344.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230025)(136003)(366004)(346002)(396003)(376002)(39860400002)(451199018)(8936002)(316002)(5660300002)(41300700001)(66946007)(66556008)(66476007)(6916009)(84970400001)(8676002)(30864003)(44832011)(2906002)(4326008)(478600001)(6486002)(26005)(186003)(1076003)(107886003)(6666004)(6506007)(36756003)(2616005)(6512007)(83380400001)(38100700002)(86362001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: luibw3LlRIudUw0q2MJG1iWAAZeES69juzIU8hulNP65SDwsysE3K4kT3mBPOy2NIYVVprufpE9OWFbBYxU/mJKozUddGbP2HGv3VTl022/HpuxJjNTIo8IueVzc/LSSV/OzRrYJSTE/r8NkNeJ5hhdZhgU4UB4zLN9ETOY0zb7q+fubxUS/Got2gGeuwL2KwNt2uQyUR0+8JpZoy8rRfBh6KvnVPkAT0AFfv9YOLt3P1OUSQdJsRML6LOmJ6+TnSRYprtfgX6Di5ZtsHeBOnZKXrNStIXvjLqY+AG4x8x/xHbmOAMgur4kRf7Ngq1DXZGoOBJQ2ekWKdGzsEoObz8Jg0s1vmPZVA2McNn7q00dB+UY4yNleTjrglMMb5/r1eVZ4UfSrIf6OOXm/uIi/uDbvcUh4I622yjBe5HKQJWHx7LrXh2pjcz/2mrugtzqxXxlHm69r5JHt9jJ+5GAxugt2OFto0mZYlXlREloQU23rClj4O2Ev9QvKDmMHJ6B6dmjDCKqBiSZto962RA0nWNcICma+mQWoWTMNdi2OCrCl2hhh0jz7UzCT7V08FjECFXrxN11Vn8qC+5FFq5hrNobpFTgH68PUnMLi2/0aFwqNTtOKZpVeny+qHTeA8rQiemrZndICk+T+OaVD/khVRcx2gv+pC71utNHb82ypLcNXz2/0sUotokSqooejwrWtoKtc7pL+txq451bx85tDv2iZ2uyFvNFjxr7gddutN5/OsylRZVLLqGlUJiYgOIYG/EBSrr/okb1STfD7BLluM0SjxNw+3wyVr6fohLZNT1A6dUcAsZIg/5Ow2ZmLXQUHTemFq2c4vYaqIPfyhKK0JmxItZNjpA42ESd02jTO4no03y9bi10a846sTtaAYg2t1KK6lhI5JQnIcherndvKavUxqnzNqv6MRPXOvcBJ+T0Lbvk49qYp5M2lEBSyXGZ/sN6mVqR7h4TGXZU5PMUdOMnOSwEakTOTsoiT6/k/HJ+vOgG+cxynQuYSXUgsqjd31XKMN0hqKvX+mGSuofDfqSEsjXq0iYXDryxAvHHGAiMP4pj8InMX98TFgEad66VRazYYyQBPCnTbb6wQ1DtzzsVDg3RLTga1sWpZpCKxkieOVSMOYW/pggYQfta0QgGcwwziKxm5I8MmzAF/rfpRR7s4a8gk3DAwZX1LAeYpFA85+5wXIHuslseSRbkHWFAcnmUdnWF1r59uU1wAkR5J9s2kBXXd0AUoOwlqo6WgGecnBIljnQ6FzB3uF6wdlOXbNWIX0aNuzPnFHETBcI3kScn0HxUWqcy5P84Tu/HqL4TYhtma0aYfvzBdyj1uop/gx/gdOt3qr9d0EFJgRf0EVrffoKOLyVw5Ytsdaz4QyWlJ3KcS0RD04oBuhTniUxIm3KI4LuIcPKhPGd9u0noWg4CvmmpKGc7JTYJMTskYHBBKmWZylzIfD3KWuzlF8FpGRtst6+JMlWIFNbt0gICOJNkadBR7B1q9RtKvgDiy12MuatInWhgvdZphNomJvE2tHZkFYkTp+TfuuCYxUyA97F0rrbtFOyhNSykUgqgWA8k9/oHEypsqAC0717Octn6e X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: sxYYuf2pN39A8Omu+CcioejYppF9VhNJDLumGGOrzYxZR5ohugZSWD/gMPeM/a0aFNPvuq0yjjOUHfye6NBeJ0zklm/dpvQzgUel6vL6lyPH70g945GwjtaGjGMRyXGSOQkDgGhWFueBW9J6nCgwdbEK0rNLAiaJvs4ukxgcpJWOGkrgipCoh8lOCSPyj2ejwtuxL6IduOdOMDx8x/UCzkzxbdNTD3m/sZNCRroqqHMZDMoo82ziaoxEQvx7zB/qY0fhpDN4JNclmp5miNhRrxqApl7853wx5sHjsFhQ9xYO7pBTm0qqgmEbyCSwZK37ZjmZeExiLFvcx+QHhOZVmWAptuV1eWe9eRPjnTruzt4x6nEcEmuCY7S6rADzmM5/B76NGphWsjXUyjFBWNbuCqEYScuc5rsLDwmDAH7JWfeieHl+7Wc7gm901ubAPTV6e1i9QWM9aAHAEu3rk0+CoPAfNLrWdIRnqTkTm43fCPbuxkerigPtNU33dF65TPW06mkOui9vMXk8M6rWDaCNdcFKg5HDoaECOM3FKG6wos/Nv9uM+pw7Fo7vj7ozf2rxJ1+pJFvuH8Gztb8N6o4oDmA12tNkIqk+vxpDfyFU3v70vsD1r3ODRs7M0Q1k6vsuYuysqFp9MNxv0TEH1X/Z6mFSs/KjXOu4iKf9ZO/5NyNVb8AOF2pvIWKajYwEjkgA2AjNC4996Wib4zG+kJ5fKkKkPhdzETXcbuFTJV5IlnEaP/AP2x6q1crSLJj0wUGAkNnRGpdTZa+dKG+Bh5VClBZ+r2cgKnn242T+OBhuts5B4QMkgtJSuDHSCSAXN/On0ovqAWxMNhEP13a1LsliDw== X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4b2d80ce-7cb8-424a-3870-08db03951766 X-MS-Exchange-CrossTenant-AuthSource: CH2PR10MB4344.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Jan 2023 14:11:48.2361 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Apx1YhHd3sksX+hlbXnWVnE7oBzTI6+9z++Is2pLdPX6FHbVmdvuBABkxbZ4lTMP3IQRULSMi/jnd8Qz43njHg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR10MB7434 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-31_08,2023-01-31_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 adultscore=0 malwarescore=0 spamscore=0 phishscore=0 mlxlogscore=999 suspectscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301310127 X-Proofpoint-GUID: SiDlIyAgopg06YWqwr5AOIoHdnYmJyha X-Proofpoint-ORIG-GUID: SiDlIyAgopg06YWqwr5AOIoHdnYmJyha Received-SPF: pass client-ip=205.220.165.32; envelope-from=qing.zhao@oracle.com; helo=mx0a-00069f02.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_NONE, 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: Qing Zhao via Gcc-patches From: Qing Zhao Reply-To: Qing Zhao Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" GCC extension accepts the case when a struct with a flexible array member is embedded into another struct (possibly recursively). __builtin_object_size should treat such struct as flexible size per -fstrict-flex-arrays. PR tree-optimization/101832 gcc/ChangeLog: PR tree-optimization/101832 * tree-object-size.cc (flexible_size_type_p): New function. (addr_object_size): Handle structure/union type when it has flexible size. gcc/testsuite/ChangeLog: PR tree-optimization/101832 * gcc.dg/builtin-object-size-pr101832-2.c: New test. * gcc.dg/builtin-object-size-pr101832-3.c: New test. * gcc.dg/builtin-object-size-pr101832-4.c: New test. * gcc.dg/builtin-object-size-pr101832.c: New test. --- .../gcc.dg/builtin-object-size-pr101832-2.c | 135 ++++++++++++++++++ .../gcc.dg/builtin-object-size-pr101832-3.c | 135 ++++++++++++++++++ .../gcc.dg/builtin-object-size-pr101832-4.c | 135 ++++++++++++++++++ .../gcc.dg/builtin-object-size-pr101832.c | 119 +++++++++++++++ gcc/tree-object-size.cc | 115 +++++++++++---- 5 files changed, 611 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c new file mode 100644 index 00000000000..f38babc5415 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c @@ -0,0 +1,135 @@ +/* PR 101832: + GCC extension accepts the case when a struct with a flexible array member + is embedded into another struct (possibly recursively). + __builtin_object_size will treat such struct as flexible size per + -fstrict-flex-arrays. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=1" } */ + +#include + +unsigned n_fails = 0; + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else {\ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + n_fails++; \ + } \ +} while (0); + +struct A { + int n; + char data[];/* Content following header */ +}; + +struct B { + int m; + struct A a; +}; + +struct C { + int q; + struct B b; +}; + +struct A0 { + int n; + char data[0];/* Content following header */ +}; + +struct B0 { + int m; + struct A0 a; +}; + +struct C0 { + int q; + struct B0 b; +}; + +struct A1 { + int n; + char data[1];/* Content following header */ +}; + +struct B1 { + int m; + struct A1 a; +}; + +struct C1 { + int q; + struct B1 b; +}; + +struct An { + int n; + char data[8];/* Content following header */ +}; + +struct Bn { + int m; + struct An a; +}; + +struct Cn { + int q; + struct Bn b; +}; + +volatile void *magic1, *magic2; + +int main(int argc, char *argv[]) +{ + struct B *outer; + struct C *outest; + + /* Make sure optimization can't find some other object size. */ + outer = (void *)magic1; + outest = (void *)magic2; + + expect(__builtin_object_size(&outer->a, 1), -1); + expect(__builtin_object_size(&outest->b, 1), -1); + expect(__builtin_object_size(&outest->b.a, 1), -1); + + struct B0 *outer0; + struct C0 *outest0; + + /* Make sure optimization can't find some other object size. */ + outer0 = (void *)magic1; + outest0 = (void *)magic2; + + expect(__builtin_object_size(&outer0->a, 1), -1); + expect(__builtin_object_size(&outest0->b, 1), -1); + expect(__builtin_object_size(&outest0->b.a, 1), -1); + + struct B1 *outer1; + struct C1 *outest1; + + /* Make sure optimization can't find some other object size. */ + outer1 = (void *)magic1; + outest1 = (void *)magic2; + + expect(__builtin_object_size(&outer1->a, 1), -1); + expect(__builtin_object_size(&outest1->b, 1), -1); + expect(__builtin_object_size(&outest1->b.a, 1), -1); + + struct Bn *outern; + struct Cn *outestn; + + /* Make sure optimization can't find some other object size. */ + outern = (void *)magic1; + outestn = (void *)magic2; + + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); + + if (n_fails > 0) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c new file mode 100644 index 00000000000..aaae99b8d67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c @@ -0,0 +1,135 @@ +/* PR 101832: + GCC extension accepts the case when a struct with a flexible array member + is embedded into another struct (possibly recursively). + __builtin_object_size will treat such struct as flexible size per + -fstrict-flex-arrays. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=2" } */ + +#include + +unsigned n_fails = 0; + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else {\ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + n_fails++; \ + } \ +} while (0); + +struct A { + int n; + char data[];/* Content following header */ +}; + +struct B { + int m; + struct A a; +}; + +struct C { + int q; + struct B b; +}; + +struct A0 { + int n; + char data[0];/* Content following header */ +}; + +struct B0 { + int m; + struct A0 a; +}; + +struct C0 { + int q; + struct B0 b; +}; + +struct A1 { + int n; + char data[1];/* Content following header */ +}; + +struct B1 { + int m; + struct A1 a; +}; + +struct C1 { + int q; + struct B1 b; +}; + +struct An { + int n; + char data[8];/* Content following header */ +}; + +struct Bn { + int m; + struct An a; +}; + +struct Cn { + int q; + struct Bn b; +}; + +volatile void *magic1, *magic2; + +int main(int argc, char *argv[]) +{ + struct B *outer; + struct C *outest; + + /* Make sure optimization can't find some other object size. */ + outer = (void *)magic1; + outest = (void *)magic2; + + expect(__builtin_object_size(&outer->a, 1), -1); + expect(__builtin_object_size(&outest->b, 1), -1); + expect(__builtin_object_size(&outest->b.a, 1), -1); + + struct B0 *outer0; + struct C0 *outest0; + + /* Make sure optimization can't find some other object size. */ + outer0 = (void *)magic1; + outest0 = (void *)magic2; + + expect(__builtin_object_size(&outer0->a, 1), -1); + expect(__builtin_object_size(&outest0->b, 1), -1); + expect(__builtin_object_size(&outest0->b.a, 1), -1); + + struct B1 *outer1; + struct C1 *outest1; + + /* Make sure optimization can't find some other object size. */ + outer1 = (void *)magic1; + outest1 = (void *)magic2; + + expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a)); + expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b)); + expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a)); + + struct Bn *outern; + struct Cn *outestn; + + /* Make sure optimization can't find some other object size. */ + outern = (void *)magic1; + outestn = (void *)magic2; + + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); + + if (n_fails > 0) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c new file mode 100644 index 00000000000..424264e2acd --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c @@ -0,0 +1,135 @@ +/* PR 101832: + GCC extension accepts the case when a struct with a flexible array member + is embedded into another struct (possibly recursively). + __builtin_object_size will treat such struct as flexible size per + -fstrict-flex-arrays. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=3" } */ + +#include + +unsigned n_fails = 0; + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else {\ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + n_fails++; \ + } \ +} while (0); + +struct A { + int n; + char data[];/* Content following header */ +}; + +struct B { + int m; + struct A a; +}; + +struct C { + int q; + struct B b; +}; + +struct A0 { + int n; + char data[0];/* Content following header */ +}; + +struct B0 { + int m; + struct A0 a; +}; + +struct C0 { + int q; + struct B0 b; +}; + +struct A1 { + int n; + char data[1];/* Content following header */ +}; + +struct B1 { + int m; + struct A1 a; +}; + +struct C1 { + int q; + struct B1 b; +}; + +struct An { + int n; + char data[8];/* Content following header */ +}; + +struct Bn { + int m; + struct An a; +}; + +struct Cn { + int q; + struct Bn b; +}; + +volatile void *magic1, *magic2; + +int main(int argc, char *argv[]) +{ + struct B *outer; + struct C *outest; + + /* Make sure optimization can't find some other object size. */ + outer = (void *)magic1; + outest = (void *)magic2; + + expect(__builtin_object_size(&outer->a, 1), -1); + expect(__builtin_object_size(&outest->b, 1), -1); + expect(__builtin_object_size(&outest->b.a, 1), -1); + + struct B0 *outer0; + struct C0 *outest0; + + /* Make sure optimization can't find some other object size. */ + outer0 = (void *)magic1; + outest0 = (void *)magic2; + + expect(__builtin_object_size(&outer0->a, 1), sizeof(outer0->a)); + expect(__builtin_object_size(&outest0->b, 1), sizeof(outest0->b)); + expect(__builtin_object_size(&outest0->b.a, 1), sizeof(outest0->b.a)); + + struct B1 *outer1; + struct C1 *outest1; + + /* Make sure optimization can't find some other object size. */ + outer1 = (void *)magic1; + outest1 = (void *)magic2; + + expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a)); + expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b)); + expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a)); + + struct Bn *outern; + struct Cn *outestn; + + /* Make sure optimization can't find some other object size. */ + outern = (void *)magic1; + outestn = (void *)magic2; + + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); + + if (n_fails > 0) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c new file mode 100644 index 00000000000..8ed6980edf0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c @@ -0,0 +1,119 @@ +/* PR 101832: + GCC extension accepts the case when a struct with a flexible array member + is embedded into another struct (possibly recursively). + __builtin_object_size will treat such struct as flexible size per + -fstrict-flex-arrays. */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#include + +unsigned n_fails = 0; + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else {\ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + n_fails++; \ + } \ +} while (0); + +struct A { + int n; + char data[];/* Content following header */ +}; + +struct B { + int m; + struct A a; +}; + +struct C { + int q; + struct B b; +}; + +struct A0 { + int n; + char data[0];/* Content following header */ +}; + +struct B0 { + int m; + struct A0 a; +}; + +struct C0 { + int q; + struct B0 b; +}; + +struct A1 { + int n; + char data[1];/* Content following header */ +}; + +struct B1 { + int m; + struct A1 a; +}; + +struct C1 { + int q; + struct B1 b; +}; + +struct An { + int n; + char data[8];/* Content following header */ +}; + +struct Bn { + int m; + struct An a; +}; + +struct Cn { + int q; + struct Bn b; +}; + +volatile void *magic1, *magic2; + +int main(int argc, char *argv[]) +{ + struct B *outer = (void *)magic1; + struct C *outest = (void *)magic2; + + expect(__builtin_object_size(&outer->a, 1), -1); + expect(__builtin_object_size(&outest->b, 1), -1); + expect(__builtin_object_size(&outest->b.a, 1), -1); + + struct B0 *outer0 = (void *)magic1; + struct C0 *outest0 = (void *)magic2; + + expect(__builtin_object_size(&outer0->a, 1), -1); + expect(__builtin_object_size(&outest0->b, 1), -1); + expect(__builtin_object_size(&outest0->b.a, 1), -1); + + struct B1 *outer1 = (void *)magic1; + struct C1 *outest1 = (void *)magic2; + + expect(__builtin_object_size(&outer1->a, 1), -1); + expect(__builtin_object_size(&outest1->b, 1), -1); + expect(__builtin_object_size(&outest1->b.a, 1), -1); + + struct Bn *outern = (void *)magic1; + struct Cn *outestn = (void *)magic2; + + expect(__builtin_object_size(&outern->a, 1), -1); + expect(__builtin_object_size(&outestn->b, 1), -1); + expect(__builtin_object_size(&outestn->b.a, 1), -1); + + if (n_fails > 0) + __builtin_abort (); + + return 0; +} diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index 9a936a91983..56b78ca2a8c 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -500,6 +500,42 @@ decl_init_size (tree decl, bool min) return size; } +/* Determine whether TYPE is a structure with a flexible array member + per -fstrict-flex-array or a union containing such a structure + (possibly recursively). */ +static bool +flexible_size_type_p (const_tree type) +{ + tree x = NULL_TREE; + tree last = NULL_TREE; + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) + if (TREE_CODE (x) == FIELD_DECL) + last = x; + if (last == NULL_TREE) + return false; + if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE + && !DECL_NOT_FLEXARRAY (last)) + return true; + else if (TREE_CODE (TREE_TYPE (last)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (last)) == UNION_TYPE) + return flexible_size_type_p (TREE_TYPE (last)); + return false; + case UNION_TYPE: + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) + { + if (TREE_CODE (x) == FIELD_DECL + && flexible_array_type_p (TREE_TYPE (x))) + return true; + } + return false; + default: + return false; + } +} + /* 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). */ @@ -633,45 +669,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, v = NULL_TREE; break; case COMPONENT_REF: - if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) + /* When the ref is not to an array, a record or a union, it + will not have flexible size, compute the object size + directly. */ + if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) + && (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE) + && (TREE_CODE (TREE_TYPE (v)) != UNION_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) + /* if the record or union does not have flexible size + compute the object size directly. */ + if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (v)) == UNION_TYPE) { - /* compute object size only if v is not a - flexible array member. */ - if (!is_flexible_array_mem_ref) + if (!flexible_size_type_p (TREE_TYPE (v))) { v = NULL_TREE; break; } - v = TREE_OPERAND (v, 0); + else + 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; + { + /* Now the ref is to an array type. */ + 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;