We raise bogus Constraint_Error for the Max_Size_In_Storage_Elements attribute 
applied to unconstrained array types and types derived from them.  This very 
likely was introduced when sizetype was changed to unsigned.

Tested on x86_64-suse-linux, applied on the mainline.


2015-05-28  Eric Botcazou  <ebotca...@adacore.com>

        * gcc-interface/utils.c (max_size) <tcc_binary>: Add special code to
        deal with the subtraction of a "negative" value in an unsigned type.


2015-05-28  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/discr43.adb: New test.


-- 
Eric Botcazou
Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c	(revision 223835)
+++ gcc-interface/utils.c	(working copy)
@@ -3443,9 +3443,23 @@ max_size (tree exp, bool max_p)
 	if ((code == MINUS_EXPR || code == PLUS_EXPR)
 	    && TREE_CODE (lhs) == INTEGER_CST
 	    && TREE_OVERFLOW (lhs)
-	    && !TREE_CONSTANT (rhs))
+	    && TREE_CODE (rhs) != INTEGER_CST)
 	  return lhs;
 
+	/* If we are going to subtract a "negative" value in an unsigned type,
+	   do the operation as an addition of the negated value, in order to
+	   avoid creating a spurious overflow below.  */
+	if (code == MINUS_EXPR
+	    && TYPE_UNSIGNED (type)
+	    && TREE_CODE (rhs) == INTEGER_CST
+	    && !TREE_OVERFLOW (rhs)
+	    && tree_int_cst_sign_bit (rhs) != 0)
+	  {
+	    rhs = fold_build1 (NEGATE_EXPR, type, rhs);
+	    code = PLUS_EXPR;
+	  }
+
+	/* We need to detect overflows so we call size_binop here.  */
 	return size_binop (code, lhs, rhs);
       }
 
-- { dg-do compile }

with Text_IO; use Text_IO;

procedure Discr43 is

  type Arr is array (Short_Integer range <>) of Boolean;

  type Rec (LB : Short_Integer; UB : Short_Integer) is record
    A : Arr (LB .. UB);
  end record;

begin
  Put_Line ("Arr'Max_Size =" & Arr'Max_Size_In_Storage_Elements'Img);
  Put_Line ("Rec'Max_Size =" & Rec'Max_Size_In_Storage_Elements'Img);
end;

Reply via email to