This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] Avoid aliasing problems tickled by gcc-3.4.4


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]