[RFA] Avoid aliasing problems tickled by gcc-3.4.4
Christopher Faylor
me@cgf.cx
Thu Jun 16 16:49:00 GMT 2005
ping?
cgf
On Sat, Jun 11, 2005 at 03:23:01PM -0400, Christopher Faylor wrote:
>[Reply-To set]
>We've recently upgraded gcc to 3.4.4 on Cygwin and found what appear to
>be a few aliasing problems in newlib source. The patch below fixes this
>with the use of unions to reference long double values rather than by
>coercing a long double pointer to some other type of pointer.
>
>The change to vfprintf.c fixed one observed problem in cygwin. I made
>the change to ldtoa.c because -Wstrict-aliasing uncovered problems in
>that file.
>
>There might be another, more elegant way to do this. If so, I'd be happy
>to entertain suggestions. If not, I think these changes make sense.
>
>Meta-topic: Should "-Wstrict-aliasing" be turned on by default for newlib builds?
>
>cgf
>
>2005-06-11 Christopher Faylor <cgf@timesys.com>
>
> * libc/stdio/vfprintf.c (cvt): Don't rely on pointer aliasing to
> determine characteristics of long double. Use a union instead.
> * ldtoa.c (_ldtoa_r): Ditto.
> (_ldcheck): Ditto.
> (_strtold): Ditto.
> (union uconv): New union.
>
>Index: libc/stdio/vfprintf.c
>===================================================================
>RCS file: /cvs/uberbaum/newlib/libc/stdio/vfprintf.c,v
>retrieving revision 1.39
>diff -u -p -r1.39 vfprintf.c
>--- libc/stdio/vfprintf.c 21 Mar 2005 22:34:35 -0000 1.39
>+++ libc/stdio/vfprintf.c 11 Jun 2005 19:11:22 -0000
>@@ -1260,7 +1260,11 @@ _DEFUN(cvt, (data, value, ndigits, flags
> #ifdef _NO_LONGDBL
> union double_union tmp;
> #else
>- struct ldieee *ldptr;
>+ union
>+ {
>+ struct ldieee ieee;
>+ _LONG_DOUBLE val;
>+ } ld;
> #endif
>
> if (ch == 'f') {
>@@ -1287,8 +1291,8 @@ _DEFUN(cvt, (data, value, ndigits, flags
>
> digits = _dtoa_r (data, value, mode, ndigits, decpt, &dsgn, &rve);
> #else /* !_NO_LONGDBL */
>- ldptr = (struct ldieee *)&value;
>- if (ldptr->sign) { /* this will check for < 0 and -0.0 */
>+ ld.val = value;
>+ if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
> value = -value;
> *sign = '-';
> } else
>Index: libc/stdlib/ldtoa.c
>===================================================================
>RCS file: /cvs/uberbaum/newlib/libc/stdlib/ldtoa.c,v
>retrieving revision 1.9
>diff -u -p -r1.9 ldtoa.c
>--- libc/stdlib/ldtoa.c 20 Oct 2003 18:46:37 -0000 1.9
>+++ libc/stdlib/ldtoa.c 11 Jun 2005 19:11:23 -0000
>@@ -80,6 +80,12 @@ static void einfin(register short unsign
> static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp);
> static void etoasc(short unsigned int *x, char *string, int ndigs, int outformat, LDPARMS *ldp);
>
>+union uconv
>+{
>+ unsigned short pe;
>+ long double d;
>+};
>+
> #if LDBL_MANT_DIG == 24
> static void e24toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
> #elif LDBL_MANT_DIG == 53
>@@ -2712,6 +2718,8 @@ LDPARMS rnd;
> LDPARMS *ldp = &rnd;
> char *outstr;
> char outbuf[NDEC + MAX_EXP_DIGITS + 10];
>+union uconv du;
>+du.d = d;
>
> orig_ndigits = ndigits;
> rnd.rlast = -1;
>@@ -2729,13 +2737,13 @@ if (_REENT_MP_RESULT(ptr))
> }
>
> #if LDBL_MANT_DIG == 24
>-e24toe( (unsigned short *)&d, e, ldp );
>+e24toe( &du.pe, e, ldp );
> #elif LDBL_MANT_DIG == 53
>-e53toe( (unsigned short *)&d, e, ldp );
>+e53toe( &du.pe, e, ldp );
> #elif LDBL_MANT_DIG == 64
>-e64toe( (unsigned short *)&d, e, ldp );
>+e64toe( &du.pe, e, ldp );
> #else
>-e113toe( (unsigned short *)&d, e, ldp );
>+e113toe( &du.pe, e, ldp );
> #endif
>
> if( eisneg(e) )
>@@ -2864,14 +2872,16 @@ LDPARMS *ldp = &rnd;
> rnd.rlast = -1;
> rnd.rndprc = NBITS;
>
>+union uconv du;
>+du.d = *d;
> #if LDBL_MANT_DIG == 24
>-e24toe( (unsigned short *)d, e, ldp );
>+e24toe( &du.pe, e, ldp );
> #elif LDBL_MANT_DIG == 53
>-e53toe( (unsigned short *)d, e, ldp );
>+e53toe( &du.pe, e, ldp );
> #elif LDBL_MANT_DIG == 64
>-e64toe( (unsigned short *)d, e, ldp );
>+e64toe( &du.pe, e, ldp );
> #else
>-e113toe( (unsigned short *)d, e, ldp );
>+e113toe( &du.pe, e, ldp );
> #endif
>
> if( (e[NE-1] & 0x7fff) == 0x7fff )
>@@ -3220,7 +3230,7 @@ ldp->outexpon = expon;
>
> long double _strtold (char *s, char **se)
> {
>- long double x;
>+ union uconv x;
> LDPARMS rnd;
> LDPARMS *ldp = &rnd;
> int lenldstr;
>@@ -3228,10 +3238,10 @@ long double _strtold (char *s, char **se
> rnd.rlast = -1;
> rnd.rndprc = NBITS;
>
>- lenldstr = asctoeg( s, (unsigned short *)&x, LDBL_MANT_DIG, ldp );
>+ lenldstr = asctoeg( s, &x.pe, LDBL_MANT_DIG, ldp );
> if (se)
> *se = s + lenldstr;
>- return x;
>+ return x.d;
> }
>
> #define REASONABLE_LEN 200
More information about the Newlib
mailing list