[RFA] Avoid aliasing problems tickled by gcc-3.4.4

Jeff Johnston jjohnstn@redhat.com
Thu Jun 16 19:21:00 GMT 2005


Christopher Faylor wrote:
> ping?
>

Sorry about the delay.  Patch checked in.

> 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.
>>

The changes are fine.  They are according to the gcc postings on strict 
aliasing and type-punning.

>>Meta-topic: Should "-Wstrict-aliasing" be turned on by default for newlib builds?
>>

It might be prudent to make it work cleanly for gcc4 before doing this.

>>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