+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>
 
 
   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)
       /* ... 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:
 
--- /dev/null
+-- { 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;