From patchwork Thu Mar 15 08:39:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 146850 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A9AF0B6EEA for ; Thu, 15 Mar 2012 19:39:57 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1332405598; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=DTAB9l5jHyPWr+Bdi1IQ MKgOq7U=; b=cToHE6idXw1OQhtSo6HXsh5l4w49hZ/N8UlYfWkngBsodxgrcIkM v9CotCl43Oubvg5OnUPFlB4/B9R5rdqxnz5jKmgN1JnW6V8jG66powuIHnkV2nfN bImz1BOh92AGZI5oB+Uampe79sv8gzGFm6KA/fOD1xl8UK6lu3wB6ag= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type:Content-Disposition:User-Agent:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=xJ3Yrg/DYzbeCqzsfuoss12xIxeHK1rU+bHH8FEhQOgoIu6HDoAvTI5yKpF4ZK /+uDSvap3SdgvQXRmWiDUezX0qeekpZoxmVvPgo6ussB7rEef1WrLR4QLqSNMORz Y0giePyfZ4/98bU8LvIRtiMx4ppXivwUz2OL+p8GJ5iBQ=; Received: (qmail 8992 invoked by alias); 15 Mar 2012 08:39:46 -0000 Received: (qmail 8633 invoked by uid 22791); 15 Mar 2012 08:39:43 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, SUBJ_OBFU_PUNCT_FEW X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 15 Mar 2012 08:39:26 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 5DC821C657C; Thu, 15 Mar 2012 04:39:25 -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 2jhBtsbFhFDv; Thu, 15 Mar 2012 04:39:25 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [205.232.38.4]) by rock.gnat.com (Postfix) with ESMTP id 2AE8E1C656C; Thu, 15 Mar 2012 04:39:25 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id 22B8E92BF6; Thu, 15 Mar 2012 04:39:25 -0400 (EDT) Date: Thu, 15 Mar 2012 04:39:25 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Robert Dewar Subject: [Ada] Implement Ada 2012 attributes First_Valid and Last_Valid Message-ID: <20120315083925.GA11890@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) 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 This patch implements the new attributes First_Valid and Last_Valid. These apply to static discrete types with at least one valid value. The static discrete type may have a static predicate (which is the case where these attributes are useful). They return the lowest and highest values for which valid values (that is values that satisfy any static predicate) exist. The following shows error detection in action (compiled with -gnat12 -gnatj60 -gnatld7) 1. procedure FLValidError (P : Integer) is 2. subtype R1 is integer range 1 .. 0; 3. subtype R2 is integer range 1 .. 10 4. with Dynamic_Predicate => R2 > P; 5. subtype R3 is integer range 1 .. 10 6. with Static_Predicate => R3 > 12; 7. subtype R4 is integer range 1 .. P; 8. 9. Val : Integer; 10. 11. begin 12. Val := Float'First_Valid; -- Not discrete | >>> prefix of "First_Valid" attribute must be discrete type 13. Val := Float'Last_Valid; -- Not discrete | >>> prefix of "Last_Valid" attribute must be discrete type 14. Val := R1'First_Valid; -- No values | >>> prefix of "First_Valid" attribute must be subtype with at least one value 15. Val := R1'Last_Valid; -- No values | >>> prefix of "Last_Valid" attribute must be subtype with at least one value 16. Val := R2'First_Valid; -- Dynamic predicate | >>> prefix of "First_Valid" attribute may not have dynamic predicate 17. Val := R2'Last_Valid; -- Dynamic_Predicate | >>> prefix of "Last_Valid" attribute may not have dynamic predicate 18. Val := R3'First_Valid; -- No values | >>> prefix of "First_Valid" attribute must be subtype with at least one value 19. Val := R3'Last_Valid; -- No values | >>> prefix of "Last_Valid" attribute must be subtype with at least one value 20. Val := R4'First_Valid; -- Non-static subtype | >>> prefix of "First_Valid" attribute must be a static subtype 21. Val := R4'Last_Valid; -- Non-static subtype | >>> prefix of "Last_Valid" attribute must be a static subtype 22. end FLValidError; The following compiles and executes quietly 1. procedure FLRange is 2. subtype R1 is Integer range 1 .. 10; 3. subtype R2 is Integer range 1 .. 10 4. with Static_Predicate => R2 < 2 or R2 > 9; 5. subtype R3 is Integer range 1 .. 10 6. with Static_Predicate => R3 < 3 or R3 > 8; 7. subtype R4 is Integer range 1 .. 10 8. with Static_Predicate => R4 >= 3 and R4 <= 9; 9. 10. procedure Fail is 11. begin 12. raise Program_Error; 13. end Fail; 14. 15. begin 16. if R1'First_Valid /= 1 or else R1'Last_Valid /= 10 then 17. Fail; 18. end if; 19. 20. if R2'First_Valid /= 1 or else R2'Last_Valid /= 10 then 21. Fail; 22. end if; 23. 24. if R3'First_Valid /= 1 or else R3'Last_Valid /= 10 then 25. Fail; 26. end if; 27. 28. if R4'First_Valid /= 3 or else R4'Last_Valid /= 9 then 29. Fail; 30. end if; 31. end FLRange; Tested on x86_64-pc-linux-gnu, committed on trunk 2012-03-15 Robert Dewar * exp_attr.adb (Expand_N_Attribute_Reference): Add handling of First_Valid/Last_Valid. * sem_attr.adb (Check_First_Last_Valid): New procedure (Analyze_Attribute): Add handling of First_Valid and Last_Valid (Eval_Attribute): ditto. * snames.ads-tmpl: Add entries for First_Valid and Last_Valid. Index: exp_attr.adb =================================================================== --- exp_attr.adb (revision 185390) +++ exp_attr.adb (working copy) @@ -5701,10 +5701,12 @@ Attribute_Enabled | Attribute_Epsilon | Attribute_Fast_Math | + Attribute_First_Valid | Attribute_Has_Access_Values | Attribute_Has_Discriminants | Attribute_Has_Tagged_Values | Attribute_Large | + Attribute_Last_Valid | Attribute_Machine_Emax | Attribute_Machine_Emin | Attribute_Machine_Mantissa | Index: sem_attr.adb =================================================================== --- sem_attr.adb (revision 185390) +++ sem_attr.adb (working copy) @@ -217,10 +217,14 @@ -- allowed with a type that has predicates. If the type is a generic -- actual, then the message is a warning, and we generate code to raise -- program error with an appropriate reason. No error message is given - -- for internally generated uses of the attributes. - -- The legality rule only applies to scalar types, even though the - -- current AI mentions all subtypes. + -- for internally generated uses of the attributes. This legality rule + -- only applies to scalar types. + procedure Check_Ada_2012_Attribute; + -- Check that we are in Ada 2012 mode for an Ada 2012 attribute, and + -- issue appropriate messages if not (and return to caller even in + -- the error case). + procedure Check_Array_Or_Scalar_Type; -- Common procedure used by First, Last, Range attribute to check -- that the prefix is a constrained array or scalar type, or a name @@ -270,6 +274,9 @@ -- reference when analyzing an inlined body will lose a proper warning -- on a useless with_clause. + procedure Check_First_Last_Valid; + -- Perform all checks for First_Valid and Last_Valid attributes + procedure Check_Fixed_Point_Type; -- Verify that prefix of attribute N is a fixed type @@ -862,6 +869,21 @@ end if; end Bad_Attribute_For_Predicate; + ------------------------------ + -- Check_Ada_2012_Attribute -- + ------------------------------ + + procedure Check_Ada_2012_Attribute is + begin + if Ada_Version < Ada_2012 then + Error_Msg_Name_1 := Aname; + Error_Msg_N + ("attribute % is an Ada 2012 feature", N); + Error_Msg_N + ("\unit must be compiled with -gnat2012 switch", N); + end if; + end Check_Ada_2012_Attribute; + -------------------------------- -- Check_Array_Or_Scalar_Type -- -------------------------------- @@ -1245,6 +1267,37 @@ end Check_Enum_Image; ---------------------------- + -- Check_First_Last_Valid -- + ---------------------------- + + procedure Check_First_Last_Valid is + begin + Check_Ada_2012_Attribute; + Check_Discrete_Type; + + if not Is_Static_Subtype (P_Type) then + Error_Attr_P ("prefix of % attribute must be a static subtype"); + end if; + + if Has_Predicates (P_Type) + and then No (Static_Predicate (P_Type)) + then + Error_Attr_P + ("prefix of % attribute may not have dynamic predicate"); + end if; + + if Expr_Value (Type_Low_Bound (P_Type)) > + Expr_Value (Type_High_Bound (P_Type)) + or else (Has_Predicates (P_Type) + and then Is_Empty_List (Static_Predicate (P_Type))) + then + Error_Attr_P + ("prefix of % attribute must be subtype with " + & "at least one value"); + end if; + end Check_First_Last_Valid; + + ---------------------------- -- Check_Fixed_Point_Type -- ---------------------------- @@ -3241,6 +3294,14 @@ Set_Etype (N, Universal_Integer); ----------------- + -- First_Valid -- + ----------------- + + when Attribute_First_Valid => + Check_First_Last_Valid; + Set_Etype (N, P_Type); + + ----------------- -- Fixed_Value -- ----------------- @@ -3456,6 +3517,14 @@ Check_Component; Set_Etype (N, Universal_Integer); + ---------------- + -- Last_Valid -- + ---------------- + + when Attribute_Last_Valid => + Check_First_Last_Valid; + Set_Etype (N, P_Type); + ------------------ -- Leading_Part -- ------------------ @@ -3928,12 +3997,7 @@ ---------------------- when Attribute_Overlaps_Storage => - if Ada_Version < Ada_2012 then - Error_Msg_N - ("attribute Overlaps_Storage is an Ada 2012 feature", N); - Error_Msg_N - ("\unit must be compiled with -gnat2012 switch", N); - end if; + Check_Ada_2012_Attribute; Check_E1; -- Both arguments must be objects of any type @@ -4425,13 +4489,7 @@ ------------------ when Attribute_Same_Storage => - if Ada_Version < Ada_2012 then - Error_Msg_N - ("attribute Same_Storage is an Ada 2012 feature", N); - Error_Msg_N - ("\unit must be compiled with -gnat2012 switch", N); - end if; - + Check_Ada_2012_Attribute; Check_E1; -- The arguments must be objects of any type @@ -5388,10 +5446,11 @@ -- Used for First, Last and Length attributes applied to an array or -- array subtype. Sets the variables Lo_Bound and Hi_Bound to the low -- and high bound expressions for the index referenced by the attribute - -- designator (i.e. the first index if no expression is present, and - -- the N'th index if the value N is present as an expression). Also - -- used for First and Last of scalar types. Static is reset to False - -- if the type or index type is not statically constrained. + -- designator (i.e. the first index if no expression is present, and the + -- N'th index if the value N is present as an expression). Also used for + -- First and Last of scalar types and for First_Valid and Last_Valid. + -- Static is reset to False if the type or index type is not statically + -- constrained. function Statically_Denotes_Entity (N : Node_Id) return Boolean; -- Verify that the prefix of a potentially static array attribute @@ -6460,6 +6519,31 @@ end First_Attr; ----------------- + -- First_Valid -- + ----------------- + + when Attribute_First_Valid => First_Valid : + begin + if Has_Predicates (P_Type) + and then Present (Static_Predicate (P_Type)) + then + declare + FirstN : constant Node_Id := First (Static_Predicate (P_Type)); + begin + if Nkind (FirstN) = N_Range then + Fold_Uint (N, Expr_Value (Low_Bound (FirstN)), Static); + else + Fold_Uint (N, Expr_Value (FirstN), Static); + end if; + end; + + else + Set_Bounds; + Fold_Uint (N, Expr_Value (Lo_Bound), Static); + end if; + end First_Valid; + + ----------------- -- Fixed_Value -- ----------------- @@ -6634,7 +6718,7 @@ -- Last -- ---------- - when Attribute_Last => Last : + when Attribute_Last => Last_Attr : begin Set_Bounds; @@ -6658,8 +6742,33 @@ else Check_Concurrent_Discriminant (Hi_Bound); end if; - end Last; + end Last_Attr; + ---------------- + -- Last_Valid -- + ---------------- + + when Attribute_Last_Valid => Last_Valid : + begin + if Has_Predicates (P_Type) + and then Present (Static_Predicate (P_Type)) + then + declare + LastN : constant Node_Id := Last (Static_Predicate (P_Type)); + begin + if Nkind (LastN) = N_Range then + Fold_Uint (N, Expr_Value (High_Bound (LastN)), Static); + else + Fold_Uint (N, Expr_Value (LastN), Static); + end if; + end; + + else + Set_Bounds; + Fold_Uint (N, Expr_Value (Hi_Bound), Static); + end if; + end Last_Valid; + ------------------ -- Leading_Part -- ------------------ @@ -8568,14 +8677,13 @@ if Ada_Version >= Ada_2005 and then (Is_Local_Anonymous_Access (Btyp) - -- Handle cases where Btyp is the - -- anonymous access type of an Ada 2012 - -- stand-alone object. + -- Handle cases where Btyp is the anonymous access + -- type of an Ada 2012 stand-alone object. or else Nkind (Associated_Node_For_Itype (Btyp)) = N_Object_Declaration) - and then Object_Access_Level (P) - > Deepest_Type_Access_Level (Btyp) + and then + Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp) and then Attr_Id = Attribute_Access then -- In an instance, this is a runtime check, but one we Index: snames.ads-tmpl =================================================================== --- snames.ads-tmpl (revision 185390) +++ snames.ads-tmpl (working copy) @@ -770,6 +770,7 @@ Name_Fast_Math : constant Name_Id := N + $; -- GNAT Name_First : constant Name_Id := N + $; Name_First_Bit : constant Name_Id := N + $; + Name_First_Valid : constant Name_Id := N + $; -- Ada 12 Name_Fixed_Value : constant Name_Id := N + $; -- GNAT Name_Fore : constant Name_Id := N + $; Name_Has_Access_Values : constant Name_Id := N + $; -- GNAT @@ -784,6 +785,7 @@ Name_Large : constant Name_Id := N + $; -- Ada 83 Name_Last : constant Name_Id := N + $; Name_Last_Bit : constant Name_Id := N + $; + Name_Last_Valid : constant Name_Id := N + $; -- Ada 12 Name_Leading_Part : constant Name_Id := N + $; Name_Length : constant Name_Id := N + $; Name_Machine_Emax : constant Name_Id := N + $; @@ -1332,6 +1334,7 @@ Attribute_Fast_Math, Attribute_First, Attribute_First_Bit, + Attribute_First_Valid, Attribute_Fixed_Value, Attribute_Fore, Attribute_Has_Access_Values, @@ -1346,6 +1349,7 @@ Attribute_Large, Attribute_Last, Attribute_Last_Bit, + Attribute_Last_Valid, Attribute_Leading_Part, Attribute_Length, Attribute_Machine_Emax,