This patch allows the use of static expressions, including most
importantly literals that accomodate the full range of positive
values for the Address, up to 2**a-1, where a is the size of
address values (most typically 32 or 64).

The following is compiled on a 32-bit machine:

     1. with System; use System;
     2. package BadAddr is
     3.    Bar : Integer;
     4.    for Bar'Address use   -- OK on 64 bits, ERROR on 32 bits
     5.      System'To_Address (16#ffff_ffff_ffff_1000#);
                                |
        >>> address value out of range for "To_Address" attribute

     6.
     7.    Bar1 : Integer;
     8.    for Bar1'Address use  -- OK on 64 bits, OK on 32 bits
     9.      System'To_Address (16#FFFF_FFFF#);
    10.
    11.    Bar2 : Integer;
    12.    for Bar2'Address use  -- ERROR on 64 bits, ERROR on 32 bits
    13.      System'To_Address (16#1_0000_0000_0000_0000#);
                                |
        >>> address value out of range for "To_Address" attribute

    14.
    15.    Bar3_Addr : Integer := 22;
    16.    Bar3 : Integer;
    17.    for Bar3'Address use  -- OK on 64 bits, OK on 32 bits
    18.      System'To_Address (Bar3_Addr);
    19.
    20.    Bar4 : Integer;
    21.    for Bar4'Address use  -- OK on 64 bits, OK on 32 bits
    22.      System'To_Address (-1);
    23.
    24.    Bar5 : Integer;
    25.    for Bar5'Address use     -- OK on 64 bits, error on 32 bits
    26.      System'To_Address (-(2**32));
                                |
        >>> address value out of range for "To_Address" attribute

    27.
    28.    Bar6 : Integer;
    29.    for Bar5'Address use     -- OK on 64 bits, error on 32 bits
    30.      System'To_Address (-(2**64));
                                |
        >>> address value out of range for "To_Address" attribute

    31.
    32. end BadAddr;

On a 64-bit machine, the errors on line 5 and line 26 do not appear.

Tested on x86_64-pc-linux-gnu, committed on trunk

2013-10-10  Robert Dewar  <de...@adacore.com>

        * cstand.adb (Standard_Unsigned_64): New internal type.
        * gnat_rm.texi: Update documentation on To_Address.
        * sem_attr.adb (Analyze_Attribute, case To_Address): Fix
        problem with out of range static values given as literals or
        named numbers.
        * stand.ads (Standard_Unsigned_64): New internal type.
        * stand.adb: Minor reformatting.

Index: gnat_rm.texi
===================================================================
--- gnat_rm.texi        (revision 203343)
+++ gnat_rm.texi        (working copy)
@@ -8665,12 +8665,15 @@
 @code{System.Storage_Elements.To_Address} except that
 it is a static attribute.  This means that if its argument is
 a static expression, then the result of the attribute is a
-static expression.  The result is that such an expression can be
+static expression.  This means that such an expression can be
 used in contexts (e.g.@: preelaborable packages) which require a
 static expression and where the function call could not be used
 (since the function call is always non-static, even if its
-argument is static). The argument must be in the range 0 .. 2**m-1,
-where m is the memory size (typically 32 or 64).
+argument is static). The argument must be in the range
+-(2**(m-1) .. 2**m-1, where m is the memory size
+(typically 32 or 64). Negative values are intepreted in a
+modular manner (e.g. -1 means the same as 16#FFFF_FFFF# on
+a 32 bits machine).
 
 @node Attribute Type_Class
 @unnumberedsec Attribute Type_Class
Index: sem_attr.adb
===================================================================
--- sem_attr.adb        (revision 203342)
+++ sem_attr.adb        (working copy)
@@ -5439,7 +5439,10 @@
       -- To_Address --
       ----------------
 
-      when Attribute_To_Address =>
+      when Attribute_To_Address => To_Address : declare
+         Val : Uint;
+
+      begin
          Check_E1;
          Analyze (P);
 
@@ -5451,6 +5454,31 @@
          Analyze_And_Resolve (E1, Any_Integer);
          Set_Etype (N, RTE (RE_Address));
 
+         --  Static expression case, check range and set appropriate type
+
+         if Is_OK_Static_Expression (E1) then
+            Val := Expr_Value (E1);
+
+            if Val < -(2 ** UI_From_Int (Standard'Address_Size - 1))
+                 or else
+               Val > 2 ** UI_From_Int (Standard'Address_Size) - 1
+            then
+               Error_Attr ("address value out of range for % attribute", E1);
+            end if;
+
+            --  Set type to universal integer if negative
+
+            if Val < 0 then
+               Set_Etype (E1, Universal_Integer);
+
+            --  Otherwise set type to Unsigned_64 to accomodate max values
+
+            else
+               Set_Etype (E1, Standard_Unsigned_64);
+            end if;
+         end if;
+      end To_Address;
+
       ------------
       -- To_Any --
       ------------
Index: cstand.adb
===================================================================
--- cstand.adb  (revision 203342)
+++ cstand.adb  (working copy)
@@ -1305,6 +1305,9 @@
       Set_Scope (Standard_Integer_64, Standard_Standard);
       Build_Signed_Integer_Type (Standard_Integer_64, 64);
 
+      --  Standard_Unsigned is not user visible, but is used internally. It
+      --  is an unsigned type with the same length as Standard.Integer.
+
       Standard_Unsigned := New_Standard_Entity;
       Decl := New_Node (N_Full_Type_Declaration, Stloc);
       Set_Defining_Identifier (Decl, Standard_Unsigned);
@@ -1329,6 +1332,32 @@
       Set_Etype (High_Bound (R_Node), Standard_Unsigned);
       Set_Scalar_Range (Standard_Unsigned, R_Node);
 
+      --  Standard_Unsigned_64 is not user visible, but is used internally. It
+      --  is an unsigned type mod 2**64, 64-bits unsigned, size is 64.
+
+      Standard_Unsigned_64 := New_Standard_Entity;
+      Decl := New_Node (N_Full_Type_Declaration, Stloc);
+      Set_Defining_Identifier (Decl, Standard_Unsigned_64);
+      Make_Name (Standard_Unsigned_64, "unsigned_64");
+
+      Set_Ekind             (Standard_Unsigned_64, E_Modular_Integer_Type);
+      Set_Scope             (Standard_Unsigned_64, Standard_Standard);
+      Set_Etype             (Standard_Unsigned_64, Standard_Unsigned_64);
+      Init_Size             (Standard_Unsigned_64, 64);
+      Set_Elem_Alignment    (Standard_Unsigned_64);
+      Set_Modulus           (Standard_Unsigned_64, Uint_2 ** 64);
+      Set_Is_Unsigned_Type  (Standard_Unsigned_64);
+      Set_Size_Known_At_Compile_Time
+                            (Standard_Unsigned_64);
+      Set_Is_Known_Valid    (Standard_Unsigned_64, True);
+
+      R_Node := New_Node (N_Range, Stloc);
+      Set_Low_Bound  (R_Node, Make_Integer (Uint_0));
+      Set_High_Bound (R_Node, Make_Integer (Uint_2 ** 64 - 1));
+      Set_Etype (Low_Bound (R_Node), Standard_Unsigned_64);
+      Set_Etype (High_Bound (R_Node), Standard_Unsigned_64);
+      Set_Scalar_Range (Standard_Unsigned_64, R_Node);
+
       --  Note: universal integer and universal real are constructed as fully
       --  formed signed numeric types, with parameters corresponding to the
       --  longest runtime types (Long_Long_Integer and Long_Long_Float). This
Index: stand.adb
===================================================================
--- stand.adb   (revision 203342)
+++ stand.adb   (working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---   Copyright (C) 1992,1993,1994,1995,2009  Free Software Foundation, Inc. --
+--          Copyright (C) 1992-2013,  Free Software Foundation, Inc.        --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -76,7 +76,6 @@
       Tree_Read_Int (Int (Standard_Op_Shift_Left));
       Tree_Read_Int (Int (Standard_Op_Shift_Right));
       Tree_Read_Int (Int (Standard_Op_Shift_Right_Arithmetic));
-
    end Tree_Read;
 
    ----------------
@@ -121,7 +120,6 @@
       Tree_Write_Int (Int (Standard_Op_Shift_Left));
       Tree_Write_Int (Int (Standard_Op_Shift_Right));
       Tree_Write_Int (Int (Standard_Op_Shift_Right_Arithmetic));
-
    end Tree_Write;
 
 end Stand;
Index: stand.ads
===================================================================
--- stand.ads   (revision 203342)
+++ stand.ads   (working copy)
@@ -451,13 +451,15 @@
    Standard_Integer_16 : Entity_Id;
    Standard_Integer_32 : Entity_Id;
    Standard_Integer_64 : Entity_Id;
-   --  These are signed integer types with the indicated sizes, They are used
-   --  for the underlying implementation types for fixed-point and enumeration
-   --  types.
+   --  These are signed integer types with the indicated sizes. Used for the
+   --  underlying implementation types for fixed-point and enumeration types.
 
    Standard_Unsigned : Entity_Id;
    --  An unsigned type of the same size as Standard_Integer
 
+   Standard_Unsigned_64 : Entity_Id;
+   --  An unsigned type, mod 2 ** 64, size of 64 bits.
+
    Abort_Signal : Entity_Id;
    --  Entity for abort signal exception
 

Reply via email to