Patchwork [Ada] Fixes/improvements to size check for enum rep clause

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 4, 2010, 1:59 p.m.
Message ID <20101004135954.GA18749@adacore.com>
Download mbox | patch
Permalink /patch/66676/
State New
Headers show

Comments

Arnaud Charlet - Oct. 4, 2010, 1:59 p.m.
This patch fixes a bug, and improves an error message for the handling
of the check that the values in an enumeration representation clause
are consistent with a previously given size clause.

The improvement has to do with the error message given when
a literal value is too large for a previously given size clause.
This message now gives the size and the value involoved, as shown
in this example:

     1. package BadSizeRep is
     2.    type Signal1 is (OFF, STANDBY, ON);
     3.    for Signal1'Size use 5;
     4.    for Signal1 use (OFF     => 16#00000#,
     5.                     STANDBY => 16#01010#,
     6.                     ON      => 16#11011#);
                                       |
        >>> previously given size (5) is too small for this
            value (69649)

     7.    type Signal2 is (OFF, STANDBY, ON);
     8.    for Signal2 use (OFF     => 16#00000#,
     9.                     STANDBY => 16#01010#,
    10.                     ON      => 16#11011#);
    11.    for Signal2'Size use 5;
                                |
        >>> size for "Signal2" too small, minimum allowed
            is 17

    12. end BadSizeRep;

Second the bug, the code was testing Esize instead of RM_Size
meaning that the error shown in this example was not caught:

     1. package badenumcheck is
     2.     type a is (b, c);
     3.     for a'size use 3;
     4.     for a use (1, 9);
                          |
        >>> previously given size (3) is too small for this
            value (9)

     5. end badenumcheck;

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

2010-10-04  Robert Dewar  <dewar@adacore.com>

	* sem_ch13.adb (Analyze_Enumeration_Representation_Clause): Set
	Enumeration_Rep_Expr to point to the literal, not the identifier.
	(Analyze_Enumeration_Representation_Clause): Improve error message for
	size too small for enum rep value
	(Analyze_Enumeration_Representation_Clause): Fix size test to use proper
	size (RM_Size, not Esize).

Patch

Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb	(revision 164906)
+++ sem_ch13.adb	(working copy)
@@ -2098,10 +2098,16 @@  package body Sem_Ch13 is
       Val      : Uint;
       Err      : Boolean := False;
 
-      Lo  : constant Uint := Expr_Value (Type_Low_Bound (Universal_Integer));
-      Hi  : constant Uint := Expr_Value (Type_High_Bound (Universal_Integer));
+      Lo : constant Uint := Expr_Value (Type_Low_Bound (Universal_Integer));
+      Hi : constant Uint := Expr_Value (Type_High_Bound (Universal_Integer));
+      --  Allowed range of universal integer (= allowed range of enum lit vals)
+
       Min : Uint;
       Max : Uint;
+      --  Minimum and maximum values of entries
+
+      Max_Node : Node_Id;
+      --  Pointer to node for literal providing max value
 
    begin
       if Ignore_Rep_Clauses then
@@ -2260,7 +2266,7 @@  package body Sem_Ch13 is
                         Err := True;
                      end if;
 
-                     Set_Enumeration_Rep_Expr (Elit, Choice);
+                     Set_Enumeration_Rep_Expr (Elit, Expression (Assoc));
 
                      Expr := Expression (Assoc);
                      Val := Static_Integer (Expr);
@@ -2306,15 +2312,16 @@  package body Sem_Ch13 is
                   if Max /= No_Uint and then Val <= Max then
                      Error_Msg_NE
                        ("enumeration value for& not ordered!",
-                                       Enumeration_Rep_Expr (Elit), Elit);
+                        Enumeration_Rep_Expr (Elit), Elit);
                   end if;
 
+                  Max_Node := Enumeration_Rep_Expr (Elit);
                   Max := Val;
                end if;
 
-               --  If there is at least one literal whose representation
-               --  is not equal to the Pos value, then note that this
-               --  enumeration type has a non-standard representation.
+               --  If there is at least one literal whose representation is not
+               --  equal to the Pos value, then note that this enumeration type
+               --  has a non-standard representation.
 
                if Val /= Enumeration_Pos (Elit) then
                   Set_Has_Non_Standard_Rep (Base_Type (Enumtype));
@@ -2331,15 +2338,28 @@  package body Sem_Ch13 is
 
          begin
             if Has_Size_Clause (Enumtype) then
-               if Esize (Enumtype) >= Minsize then
+
+               --  All OK, if size is OK now
+
+               if RM_Size (Enumtype) >= Minsize then
                   null;
 
                else
+                  --  Try if we can get by with biasing
+
                   Minsize :=
                     UI_From_Int (Minimum_Size (Enumtype, Biased => True));
 
-                  if Esize (Enumtype) < Minsize then
-                     Error_Msg_N ("previously given size is too small", N);
+                  --  Error message if even biasing does not work
+
+                  if RM_Size (Enumtype) < Minsize then
+                     Error_Msg_Uint_1 := RM_Size (Enumtype);
+                     Error_Msg_Uint_2 := Max;
+                     Error_Msg_N
+                       ("previously given size (^) is too small "
+                        & "for this value (^)", Max_Node);
+
+                  --  If biasing worked, indicate that we now have biased rep
 
                   else
                      Set_Has_Biased_Representation (Enumtype);