This implements a new attribute Standard'Library_Level (Standard is the only allowed prefix), which returns a Boolean value which is True if the attribute is evaluated at the library level (e.g. with a package declaration), and false if evaluated elsewhere (e.g. within a subprogram body). In the case of generics, the value indicates the placement of the instantiation, not the template, and indeed the use of this attribute within a generic is the intended common application as shown in this example:
1. generic 2. package LLTestP is 3. pragma Compile_Time_Warning 4. (not Standard'Library_Level, 5. "LLTest should be instantiated at library level"); 6. end; 1. with LLTestP; 2. package LLTestP1 is 3. package P is new LLTestP; 4. P1L : constant Boolean := Standard'Library_Level; 5. end; 1. with LLTestP; 2. with LLTestP1; use LLTestP1; 3. with Text_IO; use Text_IO; 4. procedure LLTest is 5. package P1 is new LLTestP; | >>> warning: in instantiation at lltestp.ads:4 >>> warning: LLTest should be instantiated at library level 6. begin 7. Put_Line (Boolean'Image (Standard'Library_Level)); 8. Put_Line (Boolean'Image (P1L)); 9. end; When run, LLTest outputs: FALSE TRUE Tested on x86_64-pc-linux-gnu, committed on trunk 2013-10-14 Robert Dewar <de...@adacore.com> * exp_attr.adb (Expand_N_Attribute_Reference): Add error entry for Library_Level attribute (which should not survive to expansion) * gnat_rm.texi: Document attribute Library_Level * sem_attr.adb (Analyze_Attribute, case Library_Level): Implement this new attribute (Set_Boolean_Result): Replaces Set_Result (Check_Standard_Prefix): Document that Check_E0 is called (Check_System_Prefix): New procedure * snames.ads-tmpl: Add entry for Library_Level attribute
Index: gnat_rm.texi =================================================================== --- gnat_rm.texi (revision 203527) +++ gnat_rm.texi (working copy) @@ -337,6 +337,7 @@ * Attribute Integer_Value:: * Attribute Invalid_Value:: * Attribute Large:: +* Attribute Library_Level:: * Attribute Loop_Entry:: * Attribute Machine_Size:: * Attribute Mantissa:: @@ -7842,6 +7843,7 @@ * Attribute Integer_Value:: * Attribute Invalid_Value:: * Attribute Large:: +* Attribute Library_Level:: * Attribute Loop_Entry:: * Attribute Machine_Size:: * Attribute Mantissa:: @@ -8341,6 +8343,31 @@ the Ada 83 reference manual for an exact description of the semantics of this attribute. +@node Attribute Library_Level +@unnumberedsec Attribute Library_Level +@findex Library_Level +@noindent +@noindent +@code{Standard'Library_Level} (@code{Standard} is the only allowed +prefix) returns a Boolean value which is True if the attribute is +evaluated at the library level (e.g. with a package declaration), +and false if evaluated elsewhere (e.g. within a subprogram body). +In the case of generics, the value indicates the placement of +the instantiation, not the template, and indeed the use of this +attribute within a generic is the intended common application +as shown in this example: + +@smallexample @c ada +generic + ... +package Gen is + pragma Compile_Time_Error + (not Standard'Library_Level, + "Gen can only be instantiated at library level"); + ... +end Gen; +@end smallexample + @node Attribute Loop_Entry @unnumberedsec Attribute Loop_Entry @findex Loop_Entry Index: exp_attr.adb =================================================================== --- exp_attr.adb (revision 203521) +++ exp_attr.adb (working copy) @@ -6485,6 +6485,7 @@ Attribute_Has_Tagged_Values | Attribute_Large | Attribute_Last_Valid | + Attribute_Library_Level | Attribute_Lock_Free | Attribute_Machine_Emax | Attribute_Machine_Emin | Index: sem_attr.adb =================================================================== --- sem_attr.adb (revision 203521) +++ sem_attr.adb (working copy) @@ -189,6 +189,11 @@ -- where therefore the prefix of the attribute does not match the enclosing -- scope. + procedure Set_Boolean_Result (N : Node_Id; B : Boolean); + -- Rewrites node N with an occurrence of either Standard_False or + -- Standard_True, depending on the value of the parameter B. The + -- result is marked as a static expression. + ----------------------- -- Analyze_Attribute -- ----------------------- @@ -339,13 +344,17 @@ -- Verify that prefix of attribute N is a scalar type procedure Check_Standard_Prefix; - -- Verify that prefix of attribute N is package Standard + -- Verify that prefix of attribute N is package Standard. Also checks + -- that there are no arguments. procedure Check_Stream_Attribute (Nam : TSS_Name_Type); -- Validity checking for stream attribute. Nam is the TSS name of the -- corresponding possible defined attribute function (e.g. for the -- Read attribute, Nam will be TSS_Stream_Read). + procedure Check_System_Prefix; + -- Verify that prefix of attribute N is package System + procedure Check_PolyORB_Attribute; -- Validity checking for PolyORB/DSA attribute @@ -1972,6 +1981,17 @@ Check_Not_CPP_Type; end Check_Stream_Attribute; + ------------------------- + -- Check_System_Prefix -- + ------------------------- + + procedure Check_System_Prefix is + begin + if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then + Error_Attr ("only allowed prefix for % attribute is System", P); + end if; + end Check_System_Prefix; + ----------------------- -- Check_Task_Prefix -- ----------------------- @@ -3663,6 +3683,21 @@ Check_Array_Type; Set_Etype (N, Universal_Integer); + ------------------- + -- Library_Level -- + ------------------- + + when Attribute_Library_Level => + Check_E0; + Check_Standard_Prefix; + + if not Inside_A_Generic then + Set_Boolean_Result (N, + Nearest_Dynamic_Scope (Current_Scope) = Standard_Standard); + end if; + + Set_Etype (N, Standard_Boolean); + --------------- -- Lock_Free -- --------------- @@ -4965,36 +5000,11 @@ U : Node_Id; Unam : Unit_Name_Type; - procedure Set_Result (B : Boolean); - -- Replace restriction node by static constant False or True, - -- depending on the value of B. - - ---------------- - -- Set_Result -- - ---------------- - - procedure Set_Result (B : Boolean) is - begin - if B then - Rewrite (N, New_Occurrence_Of (Standard_True, Loc)); - else - Rewrite (N, New_Occurrence_Of (Standard_False, Loc)); - end if; - - Set_Is_Static_Expression (N); - end Set_Result; - - -- Start of processing for Restriction_Set - begin Check_E1; Analyze (P); + Check_System_Prefix; - if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then - Set_Result (False); - Error_Attr_P ("prefix of % attribute must be System"); - end if; - -- No_Dependence case if Nkind (E1) = N_Parameter_Association then @@ -5002,7 +5012,7 @@ U := Explicit_Actual_Parameter (E1); if not OK_No_Dependence_Unit_Name (U) then - Set_Result (False); + Set_Boolean_Result (N, False); Error_Attr; end if; @@ -5013,14 +5023,14 @@ if Designate_Same_Unit (U, No_Dependences.Table (J).Unit) and then No_Dependences.Table (J).Warn = False then - Set_Result (True); + Set_Boolean_Result (N, True); return; end if; end loop; -- If not in the No_Dependence table, result is False - Set_Result (False); + Set_Boolean_Result (N, False); -- In this case, we must ensure that the binder will reject any -- other unit in the partition that sets No_Dependence for this @@ -5043,29 +5053,29 @@ else if Nkind (E1) /= N_Identifier then - Set_Result (False); + Set_Boolean_Result (N, False); Error_Attr ("attribute % requires restriction identifier", E1); else R := Get_Restriction_Id (Process_Restriction_Synonyms (E1)); if R = Not_A_Restriction_Id then - Set_Result (False); + Set_Boolean_Result (N, False); Error_Msg_Node_1 := E1; Error_Attr ("invalid restriction identifier &", E1); elsif R not in Partition_Boolean_Restrictions then - Set_Result (False); + Set_Boolean_Result (N, False); Error_Msg_Node_1 := E1; Error_Attr ("& is not a boolean partition-wide restriction", E1); end if; if Restriction_Active (R) then - Set_Result (True); + Set_Boolean_Result (N, True); else Check_Restriction (R, N); - Set_Result (False); + Set_Boolean_Result (N, False); end if; end if; end if; @@ -5596,11 +5606,8 @@ begin Check_E1; Analyze (P); + Check_System_Prefix; - if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then - Error_Attr_P ("prefix of % attribute must be System"); - end if; - Generate_Reference (RTE (RE_Address), P); Analyze_And_Resolve (E1, Any_Integer); Set_Etype (N, RTE (RE_Address)); @@ -6809,8 +6816,8 @@ return; end if; - -- Cases where P is not an object. Cannot do anything if P is - -- not the name of an entity. + -- Cases where P is not an object. Cannot do anything if P is not the + -- name of an entity. elsif not Is_Entity_Name (P) then Check_Expressions; @@ -6908,10 +6915,9 @@ -- We can fold 'Alignment applied to a type if the alignment is known -- (as happens for an alignment from an attribute definition clause). - -- At this stage, this can happen only for types (e.g. record - -- types) for which the size is always non-static. We exclude - -- generic types from consideration (since they have bogus - -- sizes set within templates). + -- At this stage, this can happen only for types (e.g. record types) for + -- which the size is always non-static. We exclude generic types from + -- consideration (since they have bogus sizes set within templates). elsif Id = Attribute_Alignment and then Is_Type (P_Entity) @@ -9118,6 +9124,7 @@ Attribute_First_Bit | Attribute_Input | Attribute_Last_Bit | + Attribute_Library_Level | Attribute_Maximum_Alignment | Attribute_Old | Attribute_Output | @@ -10421,6 +10428,23 @@ Eval_Attribute (N); end Resolve_Attribute; + ------------------------ + -- Set_Boolean_Result -- + ------------------------ + + procedure Set_Boolean_Result (N : Node_Id; B : Boolean) is + Loc : constant Source_Ptr := Sloc (N); + + begin + if B then + Rewrite (N, New_Occurrence_Of (Standard_True, Loc)); + else + Rewrite (N, New_Occurrence_Of (Standard_False, Loc)); + end if; + + Set_Is_Static_Expression (N); + end Set_Boolean_Result; + -------------------------------- -- Stream_Attribute_Available -- -------------------------------- Index: snames.ads-tmpl =================================================================== --- snames.ads-tmpl (revision 203525) +++ snames.ads-tmpl (working copy) @@ -807,20 +807,15 @@ -- Names of recognized attributes. The entries with the comment "Ada 83" -- are attributes that are defined in Ada 83, but not in Ada 95. These - -- attributes are implemented in both Ada 83 and Ada 95 modes in GNAT. + -- attributes are implemented in all Ada modes in GNAT. -- The entries marked GNAT are attributes that are defined by GNAT and - -- implemented in both Ada 83 and Ada 95 modes. Full descriptions of these - -- implementation dependent attributes may be found in the appropriate - -- section in Sem_Attr. + -- implemented in all Ada modes. Full descriptions of these implementation + -- dependent attributes may be found in the appropriate Sem_Attr section. -- The entries marked VMS are recognized only in OpenVMS implementations -- of GNAT, and are treated as illegal in all other contexts. - -- The entries marked HiLite are attributes that are defined by Hi-Lite - -- and implemented in GNAT operating under formal verification mode. The - -- entries are treated as illegal in all other contexts. - First_Attribute_Name : constant Name_Id := N + $; Name_Abort_Signal : constant Name_Id := N + $; -- GNAT Name_Access : constant Name_Id := N + $; @@ -881,8 +876,9 @@ Name_Last_Valid : constant Name_Id := N + $; -- Ada 12 Name_Leading_Part : constant Name_Id := N + $; Name_Length : constant Name_Id := N + $; + Name_Library_Level : constant Name_Id := N + $; -- GNAT Name_Lock_Free : constant Name_Id := N + $; -- GNAT - Name_Loop_Entry : constant Name_Id := N + $; -- HiLite + Name_Loop_Entry : constant Name_Id := N + $; -- GNAT Name_Machine_Emax : constant Name_Id := N + $; Name_Machine_Emin : constant Name_Id := N + $; Name_Machine_Mantissa : constant Name_Id := N + $; @@ -1498,6 +1494,7 @@ Attribute_Last_Valid, Attribute_Leading_Part, Attribute_Length, + Attribute_Library_Level, Attribute_Lock_Free, Attribute_Loop_Entry, Attribute_Machine_Emax,