From patchwork Tue Aug 20 09:51:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre-Marie de Rodat X-Patchwork-Id: 1149986 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-507346-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=adacore.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="w9FQZA0u"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CR0x5Nfvz9s4Y for ; Tue, 20 Aug 2019 19:52:33 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=xLABvMDU4z3BdhLU2lqz542+dwvG+9YsILgc4vwCGkq4K+9xYu Bc0Co1jSM5HdmKPFG68lCaZBxo7vaf6fajE2P7VkneRnYgp8XFEvvaJXtLcF93mZ xHlMk2EYGG2VmRbY1esfwONWZz/hVvED3ZdbgZ7Hg5f+TvnuobRGGxvfk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=12m9xRd/pL03QCZG9vMOfpjpzyU=; b=w9FQZA0urzkr+7p1yqfy 5t1oFa6EFTIsSUP6euxJhHMlQWGPHVEy06qqh3rCtvXp5XaCT88p0VLGqTvXSE2W ew9jH/lTqG/IeYAL9NCPuz4zY4rIMWBOl4O+GGUI1U2c44ZhfvWmHKz0Z6io2twB CQcw381gb9Ny3kzxIHLGtnY= Received: (qmail 121547 invoked by alias); 20 Aug 2019 09:51:27 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 121414 invoked by uid 89); 20 Aug 2019 09:51:27 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=entity_id, Entity_Id, sk:N_Subty, sk:n_subty X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Aug 2019 09:51:24 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id F0892560C2; Tue, 20 Aug 2019 05:51:22 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id Jk0pM04ZMxXa; Tue, 20 Aug 2019 05:51:22 -0400 (EDT) Received: from tron.gnat.com (tron.gnat.com [IPv6:2620:20:4000:0:46a8:42ff:fe0e:e294]) by rock.gnat.com (Postfix) with ESMTP id DF3F1560BF; Tue, 20 Aug 2019 05:51:22 -0400 (EDT) Received: by tron.gnat.com (Postfix, from userid 4862) id DB1FA63E; Tue, 20 Aug 2019 05:51:22 -0400 (EDT) Date: Tue, 20 Aug 2019 05:51:22 -0400 From: Pierre-Marie de Rodat To: gcc-patches@gcc.gnu.org Cc: Bob Duff Subject: [Ada] Warn on Unchecked_Conversion to zero-sized array Message-ID: <20190820095122.GA75458@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes The compiler usually warns on Unchecked_Conversion between types with mismatched sizes. This warning is now extended to the case where the target type is a zero-sized array. Tested on x86_64-pc-linux-gnu, committed on trunk 2019-08-20 Bob Duff gcc/ada/ * sem_ch13.adb (Is_Null_Array): New function, used to detect the null array case; used to warn about uncheckedly converting to a zero-sized array. It is unfortunate that we can't just check the size, and warn on all cases of converting from a nonzero-sized type to a zero-sized one. That's because "0" means two different things: "size is zero" and "size is unknown". Until we fix that design flaw, we need this more targeted fix. gcc/testsuite/ * gnat.dg/unchecked_convert14.adb: New testcase. --- gcc/ada/sem_ch13.adb +++ gcc/ada/sem_ch13.adb @@ -14625,6 +14625,39 @@ package body Sem_Ch13 is ------------------------------------ procedure Validate_Unchecked_Conversions is + function Is_Null_Array (T : Entity_Id) return Boolean; + -- We want to warn in the case of converting to a wrong-sized array of + -- bytes, including the zero-size case. This returns True in that case, + -- which is necessary because a size of 0 is used to indicate both an + -- unknown size and a size of 0. It's OK for this to return True in + -- other zero-size cases, but we don't go out of our way; for example, + -- we don't bother with multidimensional arrays. + + function Is_Null_Array (T : Entity_Id) return Boolean is + begin + if Is_Array_Type (T) and then Is_Constrained (T) then + declare + Index : constant Node_Id := First_Index (T); + R : Node_Id; -- N_Range + begin + case Nkind (Index) is + when N_Range => + R := Index; + when N_Subtype_Indication => + R := Range_Expression (Constraint (Index)); + when N_Identifier | N_Expanded_Name => + R := Scalar_Range (Entity (Index)); + when others => + raise Program_Error; + end case; + + return Is_Null_Range (Low_Bound (R), High_Bound (R)); + end; + end if; + + return False; + end Is_Null_Array; + begin for N in Unchecked_Conversions.First .. Unchecked_Conversions.Last loop declare @@ -14641,28 +14674,28 @@ package body Sem_Ch13 is begin -- Skip if function marked as warnings off - if Warnings_Off (Act_Unit) then + if Warnings_Off (Act_Unit) or else Serious_Errors_Detected > 0 then goto Continue; end if; - -- This validation check, which warns if we have unequal sizes for - -- unchecked conversion, and thus potentially implementation - -- dependent semantics, is one of the few occasions on which we - -- use the official RM size instead of Esize. See description in - -- Einfo "Handling of Type'Size Values" for details. - - if Serious_Errors_Detected = 0 - and then Known_Static_RM_Size (Source) - and then Known_Static_RM_Size (Target) + -- Don't do the check if warnings off for either type, note the + -- deliberate use of OR here instead of OR ELSE to get the flag + -- Warnings_Off_Used set for both types if appropriate. - -- Don't do the check if warnings off for either type, note the - -- deliberate use of OR here instead of OR ELSE to get the flag - -- Warnings_Off_Used set for both types if appropriate. + if Has_Warnings_Off (Source) or Has_Warnings_Off (Target) then + goto Continue; + end if; - and then not (Has_Warnings_Off (Source) - or - Has_Warnings_Off (Target)) + if (Known_Static_RM_Size (Source) + and then Known_Static_RM_Size (Target)) + or else Is_Null_Array (Target) then + -- This validation check, which warns if we have unequal sizes + -- for unchecked conversion, and thus implementation dependent + -- semantics, is one of the few occasions on which we use the + -- official RM size instead of Esize. See description in Einfo + -- "Handling of Type'Size Values" for details. + Source_Siz := RM_Size (Source); Target_Siz := RM_Size (Target); --- /dev/null new file mode 100644 +++ gcc/testsuite/gnat.dg/unchecked_convert14.adb @@ -0,0 +1,30 @@ +-- { dg-do compile } + +with Ada.Unchecked_Conversion; +with System.Storage_Elements; use System.Storage_Elements; + +procedure Unchecked_Convert14 is + + type R is record + I : Integer; + C : Character; + end record; + + subtype Buffer is Storage_Array (1 .. 0); + + function As_Buffer is new Ada.Unchecked_Conversion -- { dg-warning "types for unchecked conversion have different sizes" } + (Source => R, Target => Buffer); + + type Buffer_1 is array (Storage_Offset range 1 .. 1) of Storage_Element; + + function As_Buffer_1 is new Ada.Unchecked_Conversion -- { dg-warning "types for unchecked conversion have different sizes" } + (Source => R, Target => Buffer_1); + + B : Buffer; + B_1 : Buffer_1; + My_R : R := (1, 'x'); + +begin + B := As_Buffer (My_R); + B_1 := As_Buffer_1 (My_R); +end Unchecked_Convert14;