1  /* { dg-do run } */
       2  /* { dg-skip-if "PR68356 no math-errno on darwin" { "*-*-darwin*" } } */
       3  /* { dg-add-options ieee } */
       4  /* { dg-require-effective-target fenv_exceptions } */
       5  /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */
       6  
       7  #include <fenv.h>
       8  #include <math.h>
       9  #include <errno.h>
      10  
      11  extern void abort (void) __attribute__ ((noreturn));
      12  
      13  #define LARGE_NEG_MAYBE_ERANGE 0x01
      14  #define LARGE_NEG_ERANGE       0x02
      15  #define LARGE_POS_ERANGE       0x04
      16  #define LARGE_NEG_EDOM         0x08
      17  #define LARGE_POS_EDOM         0x10
      18  
      19  #define LARGE_ERANGE (LARGE_NEG_ERANGE | LARGE_POS_ERANGE)
      20  #define LARGE_EDOM (LARGE_NEG_EDOM | LARGE_POS_EDOM)
      21  #define POWER_ERANGE (LARGE_NEG_MAYBE_ERANGE | LARGE_POS_ERANGE)
      22  
      23  #define TEST(CALL, FLAGS) (CALL, tester (FLAGS))
      24  
      25  volatile double d;
      26  volatile int i;
      27  
      28  static void (*tester) (int);
      29  
      30  void
      31  check_quiet_nan (int flags __attribute__ ((unused)))
      32  {
      33    if (fetestexcept (FE_ALL_EXCEPT))
      34      abort ();
      35    if (errno)
      36      abort ();
      37  }
      38  
      39  void
      40  check_large_neg (int flags)
      41  {
      42    if (flags & LARGE_NEG_MAYBE_ERANGE)
      43      return;
      44    int expected_errno = (flags & LARGE_NEG_ERANGE ? ERANGE
      45  			: flags & LARGE_NEG_EDOM ? EDOM
      46  			: 0);
      47    if (expected_errno != errno)
      48      abort ();
      49    errno = 0;
      50  }
      51  
      52  void
      53  check_large_pos (int flags)
      54  {
      55    int expected_errno = (flags & LARGE_POS_ERANGE ? ERANGE
      56  			: flags & LARGE_POS_EDOM ? EDOM
      57  			: 0);
      58    if (expected_errno != errno)
      59      abort ();
      60    errno = 0;
      61  }
      62  
      63  void
      64  test (void)
      65  {
      66    TEST (acos (d), LARGE_EDOM);
      67    TEST (asin (d), LARGE_EDOM);
      68    TEST (acosh (d), LARGE_NEG_EDOM);
      69    TEST (atanh (d), LARGE_EDOM);
      70    TEST (cosh (d), LARGE_ERANGE);
      71    TEST (sinh (d), LARGE_ERANGE);
      72    TEST (log (d), LARGE_NEG_EDOM);
      73  #if defined (__sun__) && defined (__unix__)
      74    /* Disabled due to a bug in Solaris libm.  */
      75    if (0)
      76  #endif
      77      TEST (log2 (d), LARGE_NEG_EDOM);
      78    TEST (log10 (d), LARGE_NEG_EDOM);
      79  #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 22))
      80    /* Disabled due to glibc PR 6792, fixed in glibc 2.22.  */
      81    if (0)
      82  #endif
      83      TEST (log1p (d), LARGE_NEG_EDOM);
      84    TEST (exp (d), POWER_ERANGE);
      85  #if (defined (__sun__) || defined(__hppa__)) && defined (__unix__)
      86    /* Disabled due to a bug in Solaris libm.  HP PA-RISC libm doesn't support
      87       ERANGE for exp2.  */
      88    if (0)
      89  #endif
      90      {
      91        TEST (exp2 (d), POWER_ERANGE);
      92  #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 11))
      93        /* Disabled due to glibc PR 6788, fixed in glibc 2.11.  */
      94        if (0)
      95  #endif
      96  	TEST (expm1 (d), POWER_ERANGE);
      97      }
      98    TEST (sqrt (d), LARGE_NEG_EDOM);
      99    TEST (pow (100.0, d), POWER_ERANGE);
     100    TEST (pow (i, d), POWER_ERANGE);
     101  }
     102  
     103  int
     104  main (void)
     105  {
     106    errno = 0;
     107    i = 100;
     108    d = __builtin_nan ("");
     109    tester = check_quiet_nan;
     110    feclearexcept (FE_ALL_EXCEPT);
     111    test ();
     112  
     113    d = -1.0e80;
     114    tester = check_large_neg;
     115    errno = 0;
     116    test ();
     117  
     118    d = 1.0e80;
     119    tester = check_large_pos;
     120    errno = 0;
     121    test ();
     122  
     123    return 0;
     124  }