re PR ada/24880 (infinite loop on conversion of integer type with size clause)
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 13 May 2008 08:46:18 +0000 (08:46 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 13 May 2008 08:46:18 +0000 (08:46 +0000)
PR ada/24880
PR ada/26635
* utils.c (convert) <INTEGER_TYPE>: When converting an additive
expression to an integral type with lower precision, use NOP_EXPR
directly in a couple of special cases.

From-SVN: r135257

gcc/ada/ChangeLog
gcc/ada/utils.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/conv_integer.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/discr7.adb [new file with mode: 0644]

index 5330ee5308379775b5257cfafc24f3e810f140d6..cffae3bc3a71c5ceaf2cd4898489a038a6ba387d 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-13  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR ada/24880
+       PR ada/26635
+       * utils.c (convert) <INTEGER_TYPE>: When converting an additive
+       expression to an integral type with lower precision, use NOP_EXPR
+       directly in a couple of special cases.
+
 2008-05-12  Samuel Tardieu  <sam@rfc1149.net>
             Ed Schonberg <schonberg@adacore.com>
 
index 202818db345ca2a43b7ea58ea9a416621cb1c116..b4b38941ddbc1b17d63e84e572e7cb435e3aa9b9 100644 (file)
@@ -3627,7 +3627,7 @@ convert (tree type, tree expr)
   if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype))
     return convert_to_fat_pointer (type, expr);
 
-  /* If we're converting between two aggregate types that are mere
+  /* If we are converting between two aggregate types that are mere
      variants, just make a VIEW_CONVERT_EXPR.  */
   else if (code == ecode
           && AGGREGATE_TYPE_P (type)
@@ -3662,6 +3662,30 @@ convert (tree type, tree expr)
       /* ... fall through ... */
 
     case ENUMERAL_TYPE:
+      /* If we are converting an additive expression to an integer type
+        with lower precision, be wary of the optimization that can be
+        applied by convert_to_integer.  There are 2 problematic cases:
+          - if the first operand was originally of a biased type,
+            because we could be recursively called to convert it
+            to an intermediate type and thus rematerialize the
+            additive operator endlessly,
+          - if the expression contains a placeholder, because an
+            intermediate conversion that changes the sign could
+            be inserted and thus introduce an artificial overflow
+            at compile time when the placeholder is substituted.  */
+      if (code == INTEGER_TYPE
+         && ecode == INTEGER_TYPE
+         && TYPE_PRECISION (type) < TYPE_PRECISION (etype)
+         && (TREE_CODE (expr) == PLUS_EXPR || TREE_CODE (expr) == MINUS_EXPR))
+       {
+         tree op0 = get_unwidened (TREE_OPERAND (expr, 0), type);
+
+         if ((TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+              && TYPE_BIASED_REPRESENTATION_P (TREE_TYPE (op0)))
+             || CONTAINS_PLACEHOLDER_P (expr))
+           return build1 (NOP_EXPR, type, expr);
+       }
+
       return fold (convert_to_integer (type, expr));
 
     case POINTER_TYPE:
index 1586f486f501ebcdbd5124e229f8373d9259a71f..e870fb4bac3b41019fa0bb381904e754a34a5e80 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-13  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/discr7.adb: New test
+       * gnat.dg/conv_integer.adb: Likewise.
+
 2008-05-12  Janis Johnson  <janis187@us.ibm.com>
 
        * gcc.c-torture/compile/pr11832.c: XFAIL for mips and powerpc-linux,
diff --git a/gcc/testsuite/gnat.dg/conv_integer.adb b/gcc/testsuite/gnat.dg/conv_integer.adb
new file mode 100644 (file)
index 0000000..7693da0
--- /dev/null
@@ -0,0 +1,12 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+procedure Conv_Integer is
+   S : constant := Integer'Size;
+   type Regoff_T is range -1 .. 2 ** (S-1);
+   for Regoff_T'Size use S;
+   B : Integer;
+   C : Regoff_T;
+begin
+   B := Integer (C);
+end;
diff --git a/gcc/testsuite/gnat.dg/discr7.adb b/gcc/testsuite/gnat.dg/discr7.adb
new file mode 100644 (file)
index 0000000..3bb61cb
--- /dev/null
@@ -0,0 +1,27 @@
+-- { dg-do compile }
+
+procedure Discr7 is
+
+  subtype Index is Natural range 0..5;
+  type BitString is array(Index range <>) of Boolean;
+  pragma Pack(BitString);
+
+  function Id (I : Integer) return Integer is
+  begin
+    return I;
+  end;
+
+  type E(D : Index) is record
+    C : BitString(1..D);
+  end record;
+
+  subtype E0 is E(Id(0));
+
+  function F return E0 is
+  begin
+    return E'(D=>0, C=>(1..0=>FALSE));
+  end;
+
+begin
+  null;
+end;