1  /* { dg-do run } */
       2  /* { dg-options "-O2 -fwrapv" } */
       3  
       4  /* PR tree-optimization/21029
       5  
       6     f() used to get optimized to an infinite loop by tree-vrp, because
       7     j is assumed to be non-negative.  Even though the conversion from
       8     unsigned to signed has unspecified results if the expression value
       9     is not representable in the signed type, the compiler itself (e.g.,
      10     the Ada front end) depends on wrap-around behavior.  */
      11  
      12  unsigned int f(void) {
      13    unsigned char i = 123;
      14    signed char j;
      15  
      16    do
      17      if ((j = (signed char) i) < 0)
      18        break;
      19      else
      20        i++;
      21    while (1);
      22  
      23    return i;
      24  }
      25  
      26  /* Now let's torture it a bit further.  Narrowing conversions need
      27     similar treatment.  */
      28  
      29  unsigned int f1 (void) {
      30    unsigned short i = 123;
      31    signed char j;
      32  
      33    do
      34      if ((j = (signed char) i) < 0)
      35        break;
      36      else
      37        i++;
      38    while (1);
      39  
      40    return i;
      41  }
      42  
      43  /* And so do widening conversions.  */
      44  
      45  unsigned int f2 (void) {
      46    unsigned char i = 123;
      47    signed short j;
      48  
      49    do
      50      if ((j = (signed short) (signed char) i) < 0)
      51        break;
      52      else
      53        i++;
      54    while (1);
      55  
      56    return i;
      57  }
      58  
      59  /* Check same-sign truncations with an increment that turns into
      60     decrements.  */
      61  
      62  unsigned int f3 (void) {
      63    signed short i = 5;
      64    signed char j;
      65  
      66    do
      67      if ((j = (signed char) i) < 0)
      68        break;
      69      else
      70        i += 255;
      71    while (1);
      72  
      73    return i;
      74  }
      75  
      76  /* Check that the truncation above doesn't confuse the result of the
      77     test after a widening conversion.  */
      78  
      79  unsigned int f4 (void) {
      80    signed short i = -123;
      81    signed int j;
      82  
      83    do
      84      if ((j = (signed int) (signed char) i) > 0)
      85        break;
      86      else
      87        i += 255;
      88    while (1);
      89  
      90    return i;
      91  }
      92  
      93  /* Even if we omit the widening truncation, the narrowing truncation
      94     is implementation-defined.  */
      95  
      96  unsigned int f5 (void) {
      97    signed long i = -123;
      98    signed char j;
      99  
     100    do
     101      if ((j = (signed char) i) > 0)
     102        break;
     103      else
     104        i += 255;
     105    while (1);
     106  
     107    return i;
     108  }
     109  
     110  int main (void) {
     111    f ();
     112    f1 ();
     113    f2 ();
     114    f3 ();
     115    f4 ();
     116    f5 ();
     117    return 0;
     118  }