https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94586
--- Comment #14 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Wed, Apr 15, 2020 at 03:28:29PM +0000, dave.anglin at bell dot net wrote:
>
> On 2020-04-15 11:02 a.m., sgk at troutmask dot apl.washington.edu wrote:
> >
> > #if defined(HAVE_GFC_REAL_16)
> > # if defined(HAVE_GFC_REAL_10)
> > # define GFC_REAL_16_IS_FLOAT128
> > # if !defined(HAVE_FLOAT128)
> > # error "Where has __float128 gone?"
> > # endif
> > # else
> > # define GFC_REAL_16_IS_LONG_DOUBLE
> > # endif
> > #endif
> >
> > So, hpux does not have REAL(10) and has REAL(16). This is doing
> > what it is designed to do based on the assumption that a target
> > like hpux with REAL(16) will define the long double functions
> > with the 'l' suffix. It seems the the fix for hpux is to change
> > the test to something like
> >
> > # if defined(HAVE_GFC_REAL_10) || defined(__HPUX__)
> >
> > using, of course, whatever the relevant macro. This will then
> > select the 'q' suffix.
>
> I tried the above approach yesterday but it led to a couple of undefined
> symbols in libgfortran that
> caused a new test fail. Possibly, the above might be a better overall
> approach
It likely is the start of an approach, but it seems hpux is conflating
long double and __float128, where it flips between an 'l' and 'q' suffix.
gfortran simply assumes a correspondence with C types and C99 naming
conventions (e.g., sinf, sin, and sinl). If a target has REAL(4), REAL(8),
REAL(10), and REAL(16) the correspondence is float, double, long double,
and __float128, respectively. If a target has REAL(4), REAL(8), and REAL(16),
then the correspondence is float, double, and long double. There is no
__float128, and by extension, no functions with a 'q' suffix. The long
double math function will end in 'l'.
> but this is what I ended
> up doing last night:
>
> diff --git a/libgfortran/intrinsics/trigd.c b/libgfortran/intrinsics/trigd.c
> index 81699069545..970c60952ee 100644
> --- a/libgfortran/intrinsics/trigd.c
> +++ b/libgfortran/intrinsics/trigd.c
> @@ -27,6 +27,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.
> If
> not, see
>
> #include <math.h>
>
> +#if (_POSIX_VERSION < 200112L)
> +#define fmaf(a,b,c) ((a)*(b)+(c))
> +#define fma(a,b,c) ((a)*(b)+(c))
> +#endif
>
> /*
> For real x, let {x}_P or x_P be the closest representible number in the
> @@ -169,7 +173,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.
> If not, see
> #define COSD cosd_r16
> #define TAND tand_r16
>
> -#ifdef GFC_REAL_16_IS_FLOAT128 /* libquadmath. */
> +#if defined(GFC_REAL_16_IS_FLOAT128) || !defined(HAVE_COSL) /* libquadmath.
> */
> #define SUFFIX(x) x ## q
> #else
> #define SUFFIX(x) x ## l
>
> This fixed build of trigd.c. I think I need to do something similar to fix
> dec_math.f90:
>
> FAIL: gfortran.dg/dec_math.f90 -O0 (test for excess errors)
> Excess errors:
> /usr/ccs/bin/ld: Unsatisfied symbols:
> tanl (first referenced in /var/tmp//ccLGIJFM.o) (code)
> asinl (first referenced in /var/tmp//ccLGIJFM.o) (code)
> sinl (first referenced in /var/tmp//ccLGIJFM.o) (code)
> acosl (first referenced in /var/tmp//ccLGIJFM.o) (code)
> atanl (first referenced in /var/tmp//ccLGIJFM.o) (code)
> atan2l (first referenced in /var/tmp//ccLGIJFM.o) (code)
> cosl (first referenced in /var/tmp//ccLGIJFM.o) (code)
>
> It's the only new fail.
What does -fdump-tree-original show for
function foo(x)
real(16) foo, x
foo = cos(x)
end function foo