From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by sourceware.org (Postfix) with ESMTPS id BB8983858D33 for ; Fri, 29 Mar 2024 16:07:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BB8983858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=oracle.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BB8983858D33 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=205.220.165.32 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1711728442; cv=pass; b=VymevCnsc1+S6mbK9XJ+69KCJf1IJomWifeum0WOWy/fcvkNBeCN5ItBkIsAQWrLy/LtMPUR4YTZFaCZ14juJj0HpO8B/KB9f26Uk7yk/CZhtuAJC7ej3dMVNMWiUZfvdtkYgmVxn0ZPP0ztOEP+5CqKnAISpF9qGdwCLMRdDac= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1711728442; c=relaxed/simple; bh=lrQevKfhRHV9LT737YVBPfXCt53N8vOPHWCkR4pftZQ=; h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-Id: MIME-Version; b=tBkfw4WGZE6VFQMLRmPotzcNGgOhStterFRHKpQS4AmuoyEFMi3UsoXnNtT7kyW/4p9d3jXz0nmicw8JYJLJhkwFW1BKRLRmLKv6q6jQ+WD9rUqV/uOGs7goTcuPDoRJFRWnFTyGX2qjlVH3jTXkXWXn0nz4NgL3gbgJWbSuQUg= ARC-Authentication-Results: i=2; server2.sourceware.org Received: from pps.filterd (m0246617.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 42TFOCYu029976; Fri, 29 Mar 2024 16:07:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-transfer-encoding : content-type : mime-version; s=corp-2023-11-20; bh=xXL0aERSQxMmUk4GwDTeR9QBripPAyFOkiAQ+ZnYLIQ=; b=PBQ1oo8DZ/Hg+hfsYFmDRhoFkwly4A2SSxLawkomsZb43xYadTiOeP7cVhXU2wJ3N0l3 7xvd5wKQp2RYVzPwRaGJB63Fgo5BULAiJD8Jkki08PEvVC6RiHsNDVRfWWtOs3BO7mx0 8mfhe3vzEst63Rnwxw0J5lCdvbVVlKmuPtpf98+WXLnkBL/L1dVAi32uAazWYcK6nNIl FUu2gNhaTIQMIIoxNELnU26XB/iOIcj0X+bvNnqLs2T80ujA0UMyHW7PMg3hfZ+YDQTN fIxafLAffyhauWSuzN+I6F8lxloA3aGWwoXFfpHPfHFkJ7iCbbUblczl0dKpzQMluF52 iQ== Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.appoci.oracle.com [138.1.114.2]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3x2s9h2e54-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 29 Mar 2024 16:07:15 +0000 Received: from pps.filterd (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 42TEbjHR012800; Fri, 29 Mar 2024 16:07:14 GMT Received: from nam04-bn8-obe.outbound.protection.outlook.com (mail-bn8nam04lp2041.outbound.protection.outlook.com [104.47.74.41]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3x1nhbd67k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 29 Mar 2024 16:07:14 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=G9m52xJFGCslfDWiKqiYQGUvWORceMnbTPoC4CNdyyHa97DzHXCcs9BIwAvjc5SZJlf7dU5fYCoDyU4JW8pz3qPcSuF1MlWBGZaDcfcgvaLsQAWmmstFrtX8U8z3avWishrM4KXaP8UhKnRKZtvQp74uopTKbhVpf6apv5NA01+bOoqM16UfyMxHhT/swGm4SW+W7Tw+jTuII/TV/GTXqpbNV4VbYQOXy70uJTzvrOmZcFQzESPLQPIGytj68KhMB5AzM2+cxH9PEtQB+kWuC+ofPwj0FhjgZGgwUcM7LTNIOkZqgVCSBhwr/Pf8lRAFTTnWQLwFL5U3PmsiA8pJ1Q== 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=xXL0aERSQxMmUk4GwDTeR9QBripPAyFOkiAQ+ZnYLIQ=; b=odEVpY7wU46BuQUEzu2YaAJqInuy0YkMa6E+4ZrOdwLZvafUlQ/xPC3iI8PbziV0DG3b8LCF2Ofb/E2B37DTPr76JFXd7ZravUIudqTNcp5alEoAmXkEMsFfANR1fqSukDJ1/ZKad/fE1+g2M+ngwqe7k7vo0m48gujhYMq/6owYWyQCVfaaRTmLK55I5cO2oV0nE8JLSUhP6voxAovqcfuxaL1UCSzQqaWVhDjmShsoUUetBC08hduuM+AC/ijuxMtLVTIxsOIYDvhyRCxvI2pUjyvmeUsiH0qf1ABsOBCE5QXCMLIl4mTa/W2qX6Dv3LPad+Ot2b6dIdx77pp8vw== 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.onmicrosoft.com; s=selector2-oracle-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xXL0aERSQxMmUk4GwDTeR9QBripPAyFOkiAQ+ZnYLIQ=; b=aL/dV67gDt6b8nWN6BDb660Q2bTG/eruX6cErfPpQ+VMN5m6Q1jQkRiYBOI3EiOMnW8I8EH1cNGpQtl9DgSgHBwhz+yvXfeFyhbq9OtGXxyfOylQucAzy7zF9ZV4zCgei77w6hzRmn15Rl+8p9gzYtwsUwCNvWfwOrGkpFAbFnw= Received: from CY8PR10MB6538.namprd10.prod.outlook.com (2603:10b6:930:5a::17) by SJ0PR10MB4638.namprd10.prod.outlook.com (2603:10b6:a03:2d8::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7409.31; Fri, 29 Mar 2024 16:07:11 +0000 Received: from CY8PR10MB6538.namprd10.prod.outlook.com ([fe80::2dae:7852:9563:b4bc]) by CY8PR10MB6538.namprd10.prod.outlook.com ([fe80::2dae:7852:9563:b4bc%6]) with mapi id 15.20.7409.039; Fri, 29 Mar 2024 16:07:11 +0000 From: Qing Zhao To: josmyers@redhat.com, richard.guenther@gmail.com, siddhesh@gotplt.org, uecker@tugraz.at Cc: keescook@chromium.org, isanbard@gmail.com, gcc-patches@gcc.gnu.org, Qing Zhao Subject: [PATCH v8 1/5] Provide counted_by attribute to flexible array member field (PR108896) Date: Fri, 29 Mar 2024 16:06:59 +0000 Message-Id: <20240329160703.4012941-2-qing.zhao@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20240329160703.4012941-1-qing.zhao@oracle.com> References: <20240329160703.4012941-1-qing.zhao@oracle.com> Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: SJ0PR03CA0192.namprd03.prod.outlook.com (2603:10b6:a03:2ef::17) To CY8PR10MB6538.namprd10.prod.outlook.com (2603:10b6:930:5a::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY8PR10MB6538:EE_|SJ0PR10MB4638:EE_ X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: pzPdZpIjOoX/rXpqHXZ5z0m5B94PSMUYcptF7EY1YOENs37gM/CLKyLsw0FZfT7g6Y1/Ulnm28yS0kdI0vFxffh9HZGXgjSxs00nYQj/N9CaPkL+cmCyhhgtrWsSoYCj483op9Hg6NMwSCb51E6FqeBaZLFa+04fJv8ez5/3GbKM/zKp2YNOERj/GdIj8ubYZv/lgRkYWGuLDpjNjP5b2A1fto+oigHzBko3UY9gEd6ieLO1p5ngum9FHH2JUEUoQTdG5Cp2ORCkOSVOwEAluHy5G3BfnQVc/PnjihuGpG9EoQ9HP3CLDn28gO55PKxkqqMj9t0QX6LQpn3s86Bp7cEnMaDlxRmjARgHEJJnTFmn0km6gtdmMAZeXKajKzWn1NVBeBbqW2DL/gBECVsmHiHyrQWHItt9jnUFn/ymIG084yATJAPlrknth7amWBVSp788jU2Ak6c0fVfcHGcCjxm06UbPIaZGLvKD/J04nRHdEnOoPzzkS04Sswi4G5tdNNMYco955aex3zE8Thc+EoisxkqC0aKwMRn7L959ENpI2abBn0DWiLhMEc3pPVnQVIak3q7zBgaMbglZYeK4EIPQeZWds/hIcrCW5HxWEvfOfGDOGY8974O1SJRMh9fq X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CY8PR10MB6538.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(376005)(1800799015)(366007);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?DWmBgMHNdDXpN7lBPsAAM5W3FMkBEfnkJWtlTXCBJZyhhvqXfYRkPYJnu85f?= =?us-ascii?Q?GB0Px6AF2RkB/JhQTT4l6pzMSBMCXcQSElHKck0u9nMFegPLZn6GSz2FaTaw?= =?us-ascii?Q?/ZYS4QdllpCZ7TThyeTsEyHkJqhRwElO1U6mQEC0NEryEWqnsRy0Rt/SwUQq?= =?us-ascii?Q?z1pqPCI39JMN33wxByQVOYxx8HAuYgrexvcfCAxSdqgaOgxlslbs6sQZysmW?= =?us-ascii?Q?BssFAawr2Ui8gkzxvXWThYyNqO4LRPsAwCPGc9WvOK1pnywaSjRrdrh3CiJm?= =?us-ascii?Q?2IE/e0vQ6A5yS/prR+ETnsMHbeqGg4JC9S60FqlxltQ7rGufpOpEFe3ZxR3y?= =?us-ascii?Q?5WHkPnW9lTrDITMx5MkX79HE4rwofF5XRHXNQun5FnB/nPVv2AFmBHMFXb+3?= =?us-ascii?Q?XD7QUmlRSS5FArlJkAdIDOvFhT4FiL0P6bACvOqW8vIZcs1QsK2pbG9b23Bx?= =?us-ascii?Q?EzpG2FRQgA4/p63uq4Dr+oCkKjB71vwImM9YWG3KbABOmHGidYRzCg3ZHnSd?= =?us-ascii?Q?WXb/+o4sqrt7FsuQMK+HIUOgDWrRT21ofFkzJchrX7obV58gQBIfFZt/k8sJ?= =?us-ascii?Q?egAUd4xXdRIRJHJKVw24jeY8evPqyOKwZIuq/xizQ2PK7gx4rI+LQuGvNe5f?= =?us-ascii?Q?sDFYtom+S/tsivhRBfE6W+v8l4NYgY507xMJ8aVFb40Qq1QVYnPnAEdNwTuZ?= =?us-ascii?Q?UbvUH1RCY4/pojJ4KxM9+5JmK3Jvv3cFkEJjdrSMycSpGjlk3+nSxZ/syuFA?= =?us-ascii?Q?2Sw4UfK/aMtH2cs1tZorHHTwCnnxJeodnlccOHHw+djyco7APiPMPGsfalqR?= =?us-ascii?Q?jg5Ci4tZiUwx93JN5wnufrvTPTQkJdOAg8viNZgfZWHYNPBiN88g0eSKYjbO?= =?us-ascii?Q?DYnfTRkuE3WZMSfSOD5W7WL2zLGLC9W1QIrF1icJpt9aSrmOsB/zililAfpq?= =?us-ascii?Q?XFj6tvicD/2DvwqsmhZKY9+sDa6GlnkW4DlrMc+3GGVMuRq5bjQ7p7Bqq4hX?= =?us-ascii?Q?s2hz6z5yU3p/W+CI8BKUhUb37xSseHXIXnfNeHNgNloJ1G+XwaQGdp8iQkYw?= =?us-ascii?Q?9W/hhDDjI25pxVcwllqwfhKJeb66l7LHJ8ISP0n3En9fa43DmNwrSh5UDhCr?= =?us-ascii?Q?afLkdbDDPJFQTuijXZb3MeW1ISthi8i+R0YoHWU3qx74Jg/6VByDwuH1+Qq3?= =?us-ascii?Q?V29tha0qnyzAgBUc07V0RALRnNgtAl2zw/lmfrWqcW2i02c0I7qcIDByUONV?= =?us-ascii?Q?6gnznh9ONkMpZuvoZtJYLlZGFfJZDP73YMx46c2LP51m3QG23zyKIYGmFyK6?= =?us-ascii?Q?I/eapFKHeM6qgx80I+Bbkohqn+avgdEcTRe4t7tsEvFiFVlXFuI4d4KOuT0l?= =?us-ascii?Q?2/3Y9hBQazlGODFORUkF8iIMvP+wCZ0sBjWimfeZ9rYGOvTvMcPzk4EHdzDb?= =?us-ascii?Q?ZKclXHrDC1GKyJYc5IYVCj88MEm/sqM50ckQIUen7/w/V5MrLgMdaDVV7ZrH?= =?us-ascii?Q?z2EhFe7kJdCcnDpHmTR1khr+uD2tHXtziqDc1TqcwsBvLl8A/KAO+w2Fwu7T?= =?us-ascii?Q?0mDfH4b9+16JKz7GO8QjjDEDEBw3Q3JHj806Hi3b?= X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: UtqtyiIT599xUT4RDXy1dsN4rROYA7NTXMIPeufoU/XDeulYiU72WQDuOsegHhqlU2rHHCZFc3TzzNUO+WX6dR8pyrtWH45a77zdG8gtsXIUMYQ3WNuCtDnUiQ5CRtVJh/cJlC5gGF2wdmWF4lGXijSNq7gequTCX+qRJljncz09AhTQTy9WL1fB9XhtUkgECq4jwlZCK6kaeEJmPFEkRZEd+oqq5RRXk1hobX/8muPa0+0qno1p/eYKdJo9TF7IKkATjp07bxAeqpiWpoSDZDDEgXRNH1P42FlTyYxOCUgMu1xt3nS3sS9iIn6lPxp0UxASXqsPaaviiCMzOxcTWfB1YDT6NXGGn+q8TH5D+o0HuWmARWJeLHyilH+EG+Ts9nDPM8n4KthUg00ZjWJXYYm6D9HUy1JG3MgahxS8R1BO0Vjq0Tct7b2ckfsUu6UD8qnHib9qxQjCL8hoiA2A346os15SUY1dn0Ov2kYitJpzYCo/13JKduUf/KFtFR0fUnmnnwLXSk6zaiXoDesAhYA2iahuZlq70p5eNTB/T/uvkN3Bf4pQmDhSg9Gkc6SlW0ldIixeQ0/4WUMW4D/6ucz1SE6jiXP6CrBUbNleKGI= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 53e54581-dc00-4142-4fab-08dc500a4aa3 X-MS-Exchange-CrossTenant-AuthSource: CY8PR10MB6538.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Mar 2024 16:07:11.3524 (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: CLKOV15mjJACVsNbINbbxMI3W4S+4biyWLR2ey+qpf+/fztzFrMalyo2ggjTWUHmDCxZj9X6UGfQdQx3NIwYuA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR10MB4638 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-03-29_13,2024-03-28_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 bulkscore=0 mlxlogscore=999 suspectscore=0 adultscore=0 mlxscore=0 spamscore=0 malwarescore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2403210000 definitions=main-2403290142 X-Proofpoint-GUID: WUdOtpl0FW4jnOSR8zrA2QShKnlihi8q X-Proofpoint-ORIG-GUID: WUdOtpl0FW4jnOSR8zrA2QShKnlihi8q X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,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 List-Id: 'counted_by (COUNT)' The 'counted_by' attribute may be attached to the C99 flexible array member of a structure. It indicates that the number of the elements of the array is given by the field "COUNT" in the same structure as the flexible array member. GCC may use this information to improve detection of object size information for such structures and provide better results in compile-time diagnostics and runtime features like the array bound sanitizer and the '__builtin_dynamic_object_size'. For instance, the following code: struct P { size_t count; char other; char array[] __attribute__ ((counted_by (count))); } *p; specifies that the 'array' is a flexible array member whose number of elements is given by the field 'count' in the same structure. The field that represents the number of the elements should have an integer type. Otherwise, the compiler reports an error and ignores the attribute. When the field that represents the number of the elements is assigned a negative integer value, the compiler treats the value as zero. An explicit 'counted_by' annotation defines a relationship between two objects, 'p->array' and 'p->count', and there are the following requirementthat on the relationship between this pair: * 'p->count' must be initialized before the first reference to 'p->array'; * 'p->array' has _at least_ 'p->count' number of elements available all the time. This relationship must hold even after any of these related objects are updated during the program. It's the user's responsibility to make sure the above requirements to be kept all the time. Otherwise the compiler reports warnings, at the same time, the results of the array bound sanitizer and the '__builtin_dynamic_object_size' is undefined. One important feature of the attribute is, a reference to the flexible array member field uses the latest value assigned to the field that represents the number of the elements before that reference. For example, p->count = val1; p->array[20] = 0; // ref1 to p->array p->count = val2; p->array[30] = 0; // ref2 to p->array in the above, 'ref1' uses 'val1' as the number of the elements in 'p->array', and 'ref2' uses 'val2' as the number of elements in 'p->array'. gcc/c-family/ChangeLog: PR C/108896 * c-attribs.cc (handle_counted_by_attribute): New function. (attribute_takes_identifier_p): Add counted_by attribute to the list. * c-common.cc (c_flexible_array_member_type_p): ...To this. * c-common.h (c_flexible_array_member_type_p): New prototype. gcc/c/ChangeLog: PR C/108896 * c-decl.cc (flexible_array_member_type_p): Renamed and moved to... (add_flexible_array_elts_to_size): Use renamed function. (is_flexible_array_member_p): Use renamed function. (verify_counted_by_attribute): New function. (finish_struct): Use renamed function and verify counted_by attribute. * c-tree.h (lookup_field): New prototype. * c-typeck.cc (lookup_field): Expose as extern function. gcc/ChangeLog: PR C/108896 * doc/extend.texi: Document attribute counted_by. gcc/testsuite/ChangeLog: PR C/108896 * gcc.dg/flex-array-counted-by.c: New test. * gcc.dg/flex-array-counted-by-7.c: New test. --- gcc/c-family/c-attribs.cc | 68 +++++++++++++++- gcc/c-family/c-common.cc | 13 ++++ gcc/c-family/c-common.h | 1 + gcc/c/c-decl.cc | 78 +++++++++++++++---- gcc/c/c-tree.h | 1 + gcc/c/c-typeck.cc | 3 +- gcc/doc/extend.texi | 68 ++++++++++++++++ .../gcc.dg/flex-array-counted-by-7.c | 8 ++ gcc/testsuite/gcc.dg/flex-array-counted-by.c | 62 +++++++++++++++ 9 files changed, 282 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by-7.c create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by.c diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 40a0cf90295d..39e5824ee7a5 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -105,6 +105,8 @@ static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_strict_flex_array_attribute (tree *, tree, tree, int, bool *); +static tree handle_counted_by_attribute (tree *, tree, tree, + int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -412,6 +414,8 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_warn_if_not_aligned_attribute, NULL }, { "strict_flex_array", 1, 1, true, false, false, false, handle_strict_flex_array_attribute, NULL }, + { "counted_by", 1, 1, true, false, false, false, + handle_counted_by_attribute, NULL }, { "weak", 0, 0, true, false, false, false, handle_weak_attribute, NULL }, { "noplt", 0, 0, true, false, false, false, @@ -659,7 +663,8 @@ attribute_takes_identifier_p (const_tree attr_id) else if (!strcmp ("mode", spec->name) || !strcmp ("format", spec->name) || !strcmp ("cleanup", spec->name) - || !strcmp ("access", spec->name)) + || !strcmp ("access", spec->name) + || !strcmp ("counted_by", spec->name)) return true; else return targetm.attribute_takes_identifier_p (attr_id); @@ -2806,6 +2811,67 @@ handle_strict_flex_array_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "counted_by" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_counted_by_attribute (tree *node, tree name, + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree argval = TREE_VALUE (args); + tree old_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES (decl)); + + /* This attribute only applies to field decls of a structure. */ + if (TREE_CODE (decl) != FIELD_DECL) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute is not allowed for a non-field" + " declaration %q+D", name, decl); + *no_add_attrs = true; + } + /* This attribute only applies to field with array type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute is not allowed for a non-array field", + name); + *no_add_attrs = true; + } + /* This attribute only applies to a C99 flexible array member type. */ + else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute is not allowed for a non-flexible" + " array member field", name); + *no_add_attrs = true; + } + /* The argument should be an identifier. */ + else if (TREE_CODE (argval) != IDENTIFIER_NODE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "% argument is not an identifier"); + *no_add_attrs = true; + } + /* Issue error when there is a counted_by attribute with a different + field as the argument for the same flexible array member field. */ + else if (old_counted_by != NULL_TREE) + { + tree old_fieldname = TREE_VALUE (TREE_VALUE (old_counted_by)); + if (strcmp (IDENTIFIER_POINTER (old_fieldname), + IDENTIFIER_POINTER (argval)) != 0) + { + error_at (DECL_SOURCE_LOCATION (decl), + "% argument %qE conflicts with" + " previous declaration %qE", argval, old_fieldname); + *no_add_attrs = true; + } + } + + return NULL_TREE; +} + /* Handle a "weak" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index e15eff698dfd..bc53a5292f37 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -9909,6 +9909,19 @@ c_common_finalize_early_debug (void) (*debug_hooks->early_global_decl) (cnode->decl); } +/* Determine whether TYPE is an ISO C99 flexible array member type "[]". */ +bool +c_flexible_array_member_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + + return false; +} + /* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the values of attribute strict_flex_array and the flag_strict_flex_arrays. */ unsigned int diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 2d5f53998855..3e0eed0548b0 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -904,6 +904,7 @@ extern tree fold_for_warn (tree); extern tree c_common_get_narrower (tree, int *); extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *); extern void c_common_finalize_early_debug (void); +extern bool c_flexible_array_member_type_p (const_tree); extern unsigned int c_strict_flex_array_level_of (tree); extern bool c_option_is_from_cpp_diagnostics (int); extern tree c_hardbool_type_attr_1 (tree, tree *, tree *); diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index fe20bc21c926..3dc21e5ee9ce 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5301,19 +5301,6 @@ set_array_declarator_inner (struct c_declarator *decl, return decl; } -/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */ -static bool -flexible_array_member_type_p (const_tree type) -{ - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) == NULL_TREE - && TYPE_DOMAIN (type) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) - return true; - - return false; -} - /* Determine whether TYPE is a one-element array type "[1]". */ static bool one_element_array_type_p (const_tree type) @@ -5350,7 +5337,7 @@ add_flexible_array_elts_to_size (tree decl, tree init) elt = CONSTRUCTOR_ELTS (init)->last ().value; type = TREE_TYPE (elt); - if (flexible_array_member_type_p (type)) + if (c_flexible_array_member_type_p (type)) { complete_array_type (&type, elt, false); DECL_SIZE (decl) @@ -9317,7 +9304,7 @@ is_flexible_array_member_p (bool is_last_field, bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x)); bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x)); - bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x)); + bool is_flexible_array = c_flexible_array_member_type_p (TREE_TYPE (x)); unsigned int strict_flex_array_level = c_strict_flex_array_level_of (x); @@ -9347,6 +9334,53 @@ is_flexible_array_member_p (bool is_last_field, return false; } +/* Verify the argument of the counted_by attribute of the flexible array + member FIELD_DECL is a valid field of the containing structure, + STRUCT_TYPE, Report error and remove this attribute when it's not. */ +static void +verify_counted_by_attribute (tree struct_type, tree field_decl) +{ + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); + + if (!attr_counted_by) + return; + + /* If there is an counted_by attribute attached to the field, + verify it. */ + + tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); + + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ + + tree counted_by_field = lookup_field (struct_type, fieldname); + + /* Error when the field is not found in the containing structure. */ + if (!counted_by_field) + error_at (DECL_SOURCE_LOCATION (field_decl), + "argument %qE to the %qE attribute is not a field declaration" + " in the same structure as %qD", fieldname, + (get_attribute_name (attr_counted_by)), + field_decl); + + else + /* Error when the field is not with an integer type. */ + { + while (TREE_CHAIN (counted_by_field)) + counted_by_field = TREE_CHAIN (counted_by_field); + tree real_field = TREE_VALUE (counted_by_field); + + if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) + error_at (DECL_SOURCE_LOCATION (field_decl), + "argument %qE to the %qE attribute is not a field declaration" + " with an integer type", fieldname, + (get_attribute_name (attr_counted_by))); + + } + + return; +} /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. @@ -9408,6 +9442,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, until now.) */ bool saw_named_field = false; + tree counted_by_fam_field = NULL_TREE; for (x = fieldlist; x; x = DECL_CHAIN (x)) { /* Whether this field is the last field of the structure or union. @@ -9468,7 +9503,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, DECL_PACKED (x) = 1; /* Detect flexible array member in an invalid context. */ - if (flexible_array_member_type_p (TREE_TYPE (x))) + if (c_flexible_array_member_type_p (TREE_TYPE (x))) { if (TREE_CODE (t) == UNION_TYPE) { @@ -9489,6 +9524,12 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, "members"); TREE_TYPE (x) = error_mark_node; } + + /* If there is a counted_by attribute attached to this field, + record it here and do more verification later after the + whole structure is complete. */ + if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) + counted_by_fam_field = x; } if (pedantic && TREE_CODE (t) == RECORD_TYPE @@ -9503,7 +9544,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, when x is an array and is the last field. */ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE) TYPE_INCLUDES_FLEXARRAY (t) - = is_last_field && flexible_array_member_type_p (TREE_TYPE (x)); + = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x)); /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t when x is an union or record and is the last field. */ else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) @@ -9758,6 +9799,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, struct_parse_info->struct_types.safe_push (t); } + if (counted_by_fam_field) + verify_counted_by_attribute (t, counted_by_fam_field); + return t; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 1fba9c8dae76..c7c23edc4840 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -776,6 +776,7 @@ extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr, extern tree decl_constant_value_1 (tree, bool); extern void mark_exp_read (tree); extern tree composite_type (tree, tree); +extern tree lookup_field (tree, tree); extern tree build_component_ref (location_t, tree, tree, location_t, location_t); extern tree build_array_ref (location_t, tree, tree); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index ddeab1e2a8a1..cead0a055068 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -101,7 +101,6 @@ static bool function_types_compatible_p (const_tree, const_tree, struct comptypes_data *); static bool type_lists_compatible_p (const_tree, const_tree, struct comptypes_data *); -static tree lookup_field (tree, tree); static int convert_arguments (location_t, vec, tree, vec *, vec *, tree, tree); @@ -2375,7 +2374,7 @@ default_conversion (tree exp) the component is embedded within (nested) anonymous structures or unions, the list steps down the chain to the component. */ -static tree +tree lookup_field (tree type, tree component) { tree field; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2b8ba1949bf1..2def553961ce 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7753,6 +7753,74 @@ align them on any target. The @code{aligned} attribute can also be used for functions (@pxref{Common Function Attributes}.) +@cindex @code{counted_by} variable attribute +@item counted_by (@var{count}) +The @code{counted_by} attribute may be attached to the C99 flexible array +member of a structure. It indicates that the number of the elements of the +array is given by the field "@var{count}" in the same structure as the +flexible array member. +GCC may use this information to improve detection of object size information +for such structures and provide better results in compile-time diagnostics +and runtime features like the array bound sanitizer and +the @code{__builtin_dynamic_object_size}. + +For instance, the following code: + +@smallexample +struct P @{ + size_t count; + char other; + char array[] __attribute__ ((counted_by (count))); +@} *p; +@end smallexample + +@noindent +specifies that the @code{array} is a flexible array member whose number of +elements is given by the field @code{count} in the same structure. + +The field that represents the number of the elements should have an +integer type. Otherwise, the compiler reports an error and ignores +the attribute. + +When the field that represents the number of the elements is assigned a +negative integer value, the compiler treats the value as zero. + +An explicit @code{counted_by} annotation defines a relationship between +two objects, @code{p->array} and @code{p->count}, and there are the +following requirementthat on the relationship between this pair: + +@itemize @bullet +@item +@code{p->count} must be initialized before the first reference to +@code{p->array}; + +@item +@code{p->array} has @emph{at least} @code{p->count} number of elements +available all the time. This relationship must hold even after any of +these related objects are updated during the program. +@end itemize + +It's the user's responsibility to make sure the above requirements to +be kept all the time. Otherwise the compiler reports warnings, +at the same time, the results of the array bound sanitizer and the +@code{__builtin_dynamic_object_size} is undefined. + +One important feature of the attribute is, a reference to the flexible +array member field uses the latest value assigned to the field that +represents the number of the elements before that reference. For example, + +@smallexample + p->count = val1; + p->array[20] = 0; // ref1 to p->array + p->count = val2; + p->array[30] = 0; // ref2 to p->array +@end smallexample + +@noindent +in the above, @code{ref1} uses @code{val1} as the number of the elements in +@code{p->array}, and @code{ref2} uses @code{val2} as the number of elements +in @code{p->array}. + @cindex @code{alloc_size} variable attribute @item alloc_size (@var{position}) @itemx alloc_size (@var{position-1}, @var{position-2}) diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-7.c b/gcc/testsuite/gcc.dg/flex-array-counted-by-7.c new file mode 100644 index 000000000000..fcb6f1b79690 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-7.c @@ -0,0 +1,8 @@ +/* Testing the correct usage of attribute counted_by: _BitInt */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-O2 -std=c23" } */ + +struct trailing_array { + _BitInt(24) count; + int array[] __attribute ((counted_by (count))); +}; diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c b/gcc/testsuite/gcc.dg/flex-array-counted-by.c new file mode 100644 index 000000000000..e8b54c2de1c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by.c @@ -0,0 +1,62 @@ +/* Testing the correct usage of attribute counted_by. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#include + +int size; +int x __attribute ((counted_by (size))); /* { dg-error "attribute is not allowed for a non-field declaration" } */ + +struct trailing { + int count; + int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array field" } */ +}; + +struct trailing_1 { + int count; + int array_1[0] __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-flexible array member field" } */ +}; + +int count; +struct trailing_array_2 { + int count; + int array_2[] __attribute ((counted_by ("count"))); /* { dg-error "argument is not an identifier" } */ +}; + +struct trailing_array_3 { + int other; + int array_3[] __attribute ((counted_by (L"count"))); /* { dg-error "argument is not an identifier" } */ +}; + +struct trailing_array_4 { + int other; + int array_4[] __attribute ((counted_by (count))); /* { dg-error "attribute is not a field declaration in the same structure as" } */ +}; + +int count; +struct trailing_array_5 { + float count; + int array_5[] __attribute ((counted_by (count))); /* { dg-error "attribute is not a field declaration with an integer type" } */ +}; + +struct trailing_array_6 { + int count; + int array_6[] __attribute ((counted_by (count))) __attribute ((counted_by (count))); +}; + +struct trailing_array_7 { + int count1; + int count2; + int array_7[] __attribute ((counted_by (count1))) __attribute ((counted_by (count2))); /* { dg-error "conflicts with previous declaration" } */ +}; + +struct trailing_array_8 { + _Bool count; + int array_8[] __attribute ((counted_by (count))); +}; + +enum week {Mon, Tue, Wed}; +struct trailing_array_9 { + enum week days; + int array_9[] __attribute ((counted_by (days))); +}; -- 2.31.1