* gcc-interface/utils.c (max_size) <tcc_binary>: Add special code to
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 May 2015 15:45:08 +0000 (15:45 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 May 2015 15:45:08 +0000 (15:45 +0000)
deal with the subtraction of a "negative" value in an unsigned type.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223837 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/gcc-interface/utils.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/discr43.adb [new file with mode: 0644]

index 8ebf666..61ec1df 100644 (file)
@@ -1,5 +1,10 @@
 2015-05-28  Eric Botcazou  <ebotcazou@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  <ebotcazou@adacore.com>
+
        * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>: Do
        not error out on a return type which has a size that overflows if the
        return is done by invisible reference.
index 7615d2d..0871c3c 100644 (file)
@@ -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);
       }
 
index 282a3be..f986488 100644 (file)
@@ -1,5 +1,9 @@
 2015-05-28  Eric Botcazou  <ebotcazou@adacore.com>
 
+       * gnat.dg/discr43.adb: New test.
+
+2015-05-28  Eric Botcazou  <ebotcazou@adacore.com>
+
        * gnat.dg/varsize_temp.adb: Rename into...
        * gnat.dg/varsize1.adb: ...this.
        * gnat.dg/varsize_copy.ad[sb]: Rename into...
diff --git a/gcc/testsuite/gnat.dg/discr43.adb b/gcc/testsuite/gnat.dg/discr43.adb
new file mode 100644 (file)
index 0000000..e0d4390
--- /dev/null
@@ -0,0 +1,16 @@
+-- { 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;