Alexei Sheplyakov wrote:
I'm not sure if CLN code is safe to compile with plain -O2.
With CXXFLAGS="-m64 -O2 -Wall -march=k8 -finline-limit=2000" I get tons of warnings like
../../include/cln/number.h: In constructor 'cln::cl_number::cl_number(float)': ../../include/cln/number.h:238: warning: type-punning to incomplete type might break strict-aliasing rules ../../include/cln/number.h: In member function 'cln::cl_number& cln::cl_number::operator=(float)': ../../include/cln/number.h:238: warning: type-punning to incomplete type might break strict-aliasing rules ../../include/cln/number.h: In constructor 'cln::cl_number::cl_number(double)': ../../include/cln/number.h:239: warning: type-punning to incomplete type might break strict-aliasing rules
Just for the record, I use g++-4.1 (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21).
Attached is a proposed patch that removes most of the warnings. They cause two additional instructions to be added to the functions cl_float_to_FF_pointer and cl_double_to_DF_pointer, but this is worth the gain of being able to compile cln with -O2 with modern gcc. Richy, ok to apply? Jörg Arndt wrote:
(2) no warnings!, I suggest to use -W -Wall -Wconversion -Wsign-promo -Wsign-compare -Wunused \ -Wshadow -Wundef
While I agree that -Wall is generally useful, and -W is sometimes useful, the others spew too many warnings on perfectly valid code, IMO. Your mileage might vary, of course. Bruno diff -c -3 -r1.202 ChangeLog *** cln/ChangeLog 19 Jan 2008 20:50:30 -0000 1.202 --- cln/ChangeLog 21 Jan 2008 09:39:05 -0000 *************** *** 1,3 **** --- 1,30 ---- + 2007-01-20 Bruno Haible <bruno@clisp.org> + + Avoid some gcc warnings. + * autoconf/floatparam.c (flipped_double): Use a union instead of a + type-punning cast. + * include/cln/number.h (union ffloatjanus, union dfloatjanus): Remove + declarations. + (cl_float_to_FF_pointer, cl_double_to_DF_pointer): Change argument + type. + (CL_DEFINE_FLOAT_CONSTRUCTOR, CL_DEFINE_DOUBLE_CONSTRUCTOR): Update. + * src/float/dfloat/cl_FF.h (cl_float_to_FF_pointer): Change argument + type. + (cl_float_to_FF): Remove function. + * src/float/ffloat/conv/cl_FF_from_float.cc (FAST_FLOAT): Define. + (cl_float_to_FF_pointer): Change argument type. + * src/float/dfloat/cl_DF.h (cl_double_to_DF_pointer): Change argument + type. + (cl_double_to_DF): Remove function. + * src/float/dfloat/conv/cl_DF_from_double.cc (FAST_DOUBLE): Define. + (cl_double_to_DF_pointer): Change argument type. + * src/float/lfloat/cl_LF_impl.h (LF_decode): Mark the mantlen_zuweisung + assignment as possibly unused. + * src/base/cl_low.h (mulu32): Mark the hi_zuweisung assignment as + possibly unused. + * src/float/transcendental/cl_LF_zeta_int.cc (compute_zeta_cvz2): + Remove unused local variable. + 2007-01-19 Richard B. Kreckel <kreckel@ginac.de> * Version 1.2.0 released. diff -c -3 -r1.3 floatparam.c *** cln/autoconf/floatparam.c 19 Dec 2006 14:50:43 -0000 1.3 --- cln/autoconf/floatparam.c 21 Jan 2008 09:39:05 -0000 *************** *** 92,99 **** static void flipped_double (void) { typedef struct { unsigned lo, hi; } dfloat; ! double x = 2; ! dfloat test = *(dfloat*)&x; if (test.lo==0 && test.hi!=0) { printf("#define double_wordorder_bigendian_p 0\n"); } else if (test.lo!=0 && test.hi==0) { --- 92,100 ---- static void flipped_double (void) { typedef struct { unsigned lo, hi; } dfloat; ! union { dfloat eksplicit; double machine_double; } x; ! x.machine_double = 2; ! dfloat test = x.eksplicit; if (test.lo==0 && test.hi!=0) { printf("#define double_wordorder_bigendian_p 0\n"); } else if (test.lo!=0 && test.hi==0) { diff -c -3 -r1.6 number.h *** cln/include/cln/number.h 11 Dec 2006 17:31:06 -0000 1.6 --- cln/include/cln/number.h 21 Jan 2008 09:39:06 -0000 *************** *** 146,179 **** // Constructors and assignment operators from C numeric types. // from `float': ! union ffloatjanus; ! extern cl_private_thing cl_float_to_FF_pointer (const union ffloatjanus& val); #define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_) \ inline _class_ :: _class_ (const float x) \ { \ ! pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \ } \ inline _class_& _class_::operator= (const float x) \ { \ cl_dec_refcount(*this); \ ! pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \ return *this; \ } // from `double': ! union dfloatjanus; ! extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const union dfloatjanus& val); #define CL_DEFINE_DOUBLE_CONSTRUCTOR(_class_) \ inline _class_::_class_ (const double x) \ { \ ! pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \ } \ inline _class_& _class_::operator= (const double x) \ { \ cl_dec_refcount(*this); \ ! pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \ return *this; \ } --- 146,177 ---- // Constructors and assignment operators from C numeric types. // from `float': ! extern cl_private_thing cl_float_to_FF_pointer (const float val); #define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_) \ inline _class_ :: _class_ (const float x) \ { \ ! pointer = cl_float_to_FF_pointer(x); \ } \ inline _class_& _class_::operator= (const float x) \ { \ cl_dec_refcount(*this); \ ! pointer = cl_float_to_FF_pointer(x); \ return *this; \ } // from `double': ! extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const double val); #define CL_DEFINE_DOUBLE_CONSTRUCTOR(_class_) \ inline _class_::_class_ (const double x) \ { \ ! pointer = cl_double_to_DF_pointer(x); \ } \ inline _class_& _class_::operator= (const double x) \ { \ cl_dec_refcount(*this); \ ! pointer = cl_double_to_DF_pointer(x); \ return *this; \ } diff -c -3 -r1.14 cl_low.h *** cln/src/base/cl_low.h 9 Oct 2007 22:26:28 -0000 1.14 --- cln/src/base/cl_low.h 21 Jan 2008 09:39:06 -0000 *************** *** 165,171 **** var union { double f; uint32 i[2]; uint16 s[4]; } __fi; \ __fi.f = (double)(sint32)(_x)*(double)(sint32)(_y) \ + (double)(4503599627370496.0L); /* + 2^52, zum Normalisieren */\ ! hi_zuweisung __fi.s[1]; /* mittlere 16 Bit herausholen, (benutzt CL_CPU_BIG_ENDIAN_P !) */\ lo_zuweisung __fi.i[1]; /* untere 32 Bit herausholen (benutzt CL_CPU_BIG_ENDIAN_P !) */\ } #else --- 165,171 ---- var union { double f; uint32 i[2]; uint16 s[4]; } __fi; \ __fi.f = (double)(sint32)(_x)*(double)(sint32)(_y) \ + (double)(4503599627370496.0L); /* + 2^52, zum Normalisieren */\ ! unused (hi_zuweisung __fi.s[1]); /* mittlere 16 Bit herausholen, (benutzt CL_CPU_BIG_ENDIAN_P !) */\ lo_zuweisung __fi.i[1]; /* untere 32 Bit herausholen (benutzt CL_CPU_BIG_ENDIAN_P !) */\ } #else *************** *** 205,217 **** extern "C" uint32 mulu32_high; // -> High-Teil #if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! ({ var uint32 _x = (x); \ ! var uint32 _y = (y); \ ! var uint32 _hi; \ ! var uint32 _lo; \ __asm__("mulul %3,%0:%1" : "=d" (_hi), "=d"(_lo) : "1" (_x), "dm" (_y) ); \ ! hi_zuweisung _hi; \ ! lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__m68k__) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ --- 205,217 ---- extern "C" uint32 mulu32_high; // -> High-Teil #if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! ({ var uint32 _x = (x); \ ! var uint32 _y = (y); \ ! var uint32 _hi; \ ! var uint32 _lo; \ __asm__("mulul %3,%0:%1" : "=d" (_hi), "=d"(_lo) : "1" (_x), "dm" (_y) ); \ ! unused (hi_zuweisung _hi); \ ! lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__m68k__) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ *************** *** 231,237 **** _hi += high16(_mid); _mid = highlow32_0(low16(_mid)); \ _lo += _mid; if (_lo < _mid) { _hi += 1; } /* 64-Bit-Addition */\ } \ ! hi_zuweisung _hi; \ lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) --- 231,237 ---- _hi += high16(_mid); _mid = highlow32_0(low16(_mid)); \ _lo += _mid; if (_lo < _mid) { _hi += 1; } /* 64-Bit-Addition */\ } \ ! unused (hi_zuweisung _hi); \ lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) *************** *** 241,260 **** : "=r" (_prod) \ : "r" ((uint32)(x)), "r" ((uint32)(y)) \ ); \ ! hi_zuweisung (uint32)(_prod>>32); \ lo_zuweisung (uint32)(_prod); \ }) #elif defined(__GNUC__) && defined(__sparc__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ {var register uint32 _hi __asm__("%g1"); \ ! hi_zuweisung _hi; \ }}) #elif defined(__GNUC__) && defined(__arm__) && 0 // see comment cl_asm_arm.cc #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ {var register uint32 _hi __asm__("%r1"/*"%a2"*/); \ ! hi_zuweisung _hi; \ }}) #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ --- 241,260 ---- : "=r" (_prod) \ : "r" ((uint32)(x)), "r" ((uint32)(y)) \ ); \ ! unused (hi_zuweisung (uint32)(_prod>>32)); \ lo_zuweisung (uint32)(_prod); \ }) #elif defined(__GNUC__) && defined(__sparc__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ {var register uint32 _hi __asm__("%g1"); \ ! unused (hi_zuweisung _hi); \ }}) #elif defined(__GNUC__) && defined(__arm__) && 0 // see comment cl_asm_arm.cc #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ {var register uint32 _hi __asm__("%r1"/*"%a2"*/); \ ! unused (hi_zuweisung _hi); \ }}) #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ *************** *** 264,270 **** : "=d" /* %edx */ (_hi), "=a" /* %eax */ (_lo) \ : "g" ((uint32)(x)), "1" /* %eax */ ((uint32)(y)) \ ); \ ! hi_zuweisung _hi; lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__mips__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ --- 264,270 ---- : "=d" /* %edx */ (_hi), "=a" /* %eax */ (_lo) \ : "g" ((uint32)(x)), "1" /* %eax */ ((uint32)(y)) \ ); \ ! unused (hi_zuweisung _hi); lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(__mips__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ *************** *** 274,300 **** : "=r" (_hi), "=r" (_lo) \ : "r" ((uint32)(x)), "r" ((uint32)(y)) \ ); \ ! hi_zuweisung _hi; lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(HAVE_LONGLONG) && !defined(__arm__) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ var register uint64 _prod = (uint64)(uint32)(x) * (uint64)(uint32)(y); \ ! hi_zuweisung (uint32)(_prod>>32); \ lo_zuweisung (uint32)(_prod); \ }) #elif defined(WATCOM) && defined(__i386__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! { var register uint32 _hi; \ ! var register uint32 _lo; \ ! _lo = mulu32_(x,y), _hi = mulu32_high_(); \ ! hi_zuweisung _hi; lo_zuweisung _lo; \ } extern "C" uint32 mulu32_high_ (void); #pragma aux mulu32_ = 0xF7 0xE2 /* mull %edx */ parm [eax] [edx] value [eax] modify [eax edx]; #pragma aux mulu32_high_ = /* */ value [edx] modify []; #else #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! { lo_zuweisung mulu32_(x,y); hi_zuweisung mulu32_high; } #if (defined(__m68k__) || defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || (defined(__i386__) && !defined(WATCOM) && !defined(MICROSOFT)) || defined(__x86_64__) || defined(__mips__) || defined(__hppa__)) && !defined(NO_ASM) // mulu32_ extern in Assembler #if defined(__sparc__) || defined(__sparc64__) --- 274,300 ---- : "=r" (_hi), "=r" (_lo) \ : "r" ((uint32)(x)), "r" ((uint32)(y)) \ ); \ ! unused (hi_zuweisung _hi); lo_zuweisung _lo; \ }) #elif defined(__GNUC__) && defined(HAVE_LONGLONG) && !defined(__arm__) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ({ var register uint64 _prod = (uint64)(uint32)(x) * (uint64)(uint32)(y); \ ! unused (hi_zuweisung (uint32)(_prod>>32)); \ lo_zuweisung (uint32)(_prod); \ }) #elif defined(WATCOM) && defined(__i386__) && !defined(NO_ASM) #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! { var register uint32 _hi; \ ! var register uint32 _lo; \ ! _lo = mulu32_(x,y), _hi = mulu32_high_(); \ ! unused (hi_zuweisung _hi); lo_zuweisung _lo; \ } extern "C" uint32 mulu32_high_ (void); #pragma aux mulu32_ = 0xF7 0xE2 /* mull %edx */ parm [eax] [edx] value [eax] modify [eax edx]; #pragma aux mulu32_high_ = /* */ value [edx] modify []; #else #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ ! { lo_zuweisung mulu32_(x,y); unused (hi_zuweisung mulu32_high); } #if (defined(__m68k__) || defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || (defined(__i386__) && !defined(WATCOM) && !defined(MICROSOFT)) || defined(__x86_64__) || defined(__mips__) || defined(__hppa__)) && !defined(NO_ASM) // mulu32_ extern in Assembler #if defined(__sparc__) || defined(__sparc64__) diff -c -3 -r1.5 cl_DF.h *** cln/src/float/dfloat/cl_DF.h 15 Sep 2007 21:34:16 -0000 1.5 --- cln/src/float/dfloat/cl_DF.h 21 Jan 2008 09:39:06 -0000 *************** *** 309,318 **** // e=2047, m=0: vorzeichenbehaftete Infinity // e=2047, m/=0: NaN ! // cl_double_to_DF(val) wandelt ein IEEE-Double-Float val in ein Double-Float um. ! extern cl_heap_dfloat* cl_double_to_DF_pointer (const dfloatjanus& val); ! inline const cl_DF cl_double_to_DF (const dfloatjanus& val) ! { return cl_double_to_DF_pointer(val); } // cl_DF_to_double(obj,&val); // wandelt ein Double-Float obj in ein IEEE-Double-Float val um. --- 309,316 ---- // e=2047, m=0: vorzeichenbehaftete Infinity // e=2047, m/=0: NaN ! // cl_double_to_DF_pointer(val) wandelt ein IEEE-Double-Float val in ein Double-Float um. ! extern cl_heap_dfloat* cl_double_to_DF_pointer (const double val); // cl_DF_to_double(obj,&val); // wandelt ein Double-Float obj in ein IEEE-Double-Float val um. diff -c -3 -r1.4 cl_DF_from_double.cc *** cln/src/float/dfloat/conv/cl_DF_from_double.cc 15 Sep 2007 21:34:16 -0000 1.4 --- cln/src/float/dfloat/conv/cl_DF_from_double.cc 21 Jan 2008 09:39:06 -0000 *************** *** 1,4 **** ! // cl_double_to_FF(). // General includes. #include "cl_sysdep.h" --- 1,7 ---- ! // cl_double_to_DF_pointer(). ! ! // Ensure that union dfloatjanus has a 'double' alternative. ! #define FAST_DOUBLE // General includes. #include "cl_sysdep.h" *************** *** 11,18 **** namespace cln { ! cl_heap_dfloat* cl_double_to_DF_pointer (const dfloatjanus& val_) { var dfloat val = val_.eksplicit; #if (cl_word_size==64) var uintL exp = (val >> DF_mant_len) & (bit(DF_exp_len)-1); // e --- 14,23 ---- namespace cln { ! cl_heap_dfloat* cl_double_to_DF_pointer (const double x) { + var union dfloatjanus val_; + val_.machine_double = x; var dfloat val = val_.eksplicit; #if (cl_word_size==64) var uintL exp = (val >> DF_mant_len) & (bit(DF_exp_len)-1); // e diff -c -3 -r1.4 cl_FF.h *** cln/src/float/ffloat/cl_FF.h 15 Sep 2007 21:34:16 -0000 1.4 --- cln/src/float/ffloat/cl_FF.h 21 Jan 2008 09:39:06 -0000 *************** *** 237,246 **** // e=255, m=0: vorzeichenbehaftete Infinity // e=255, m/=0: NaN ! // cl_float_to_FF(val) wandelt ein IEEE-Single-Float val in ein Single-Float um. ! extern cl_private_thing cl_float_to_FF_pointer (const ffloatjanus& val); ! inline const cl_FF cl_float_to_FF (const ffloatjanus& val) ! { return cl_float_to_FF_pointer(val); } // cl_FF_to_float(obj,&val); // wandelt ein Single-Float obj in ein IEEE-Single-Float val um. --- 237,244 ---- // e=255, m=0: vorzeichenbehaftete Infinity // e=255, m/=0: NaN ! // cl_float_to_FF_pointer(val) wandelt ein IEEE-Single-Float val in ein Single-Float um. ! extern cl_private_thing cl_float_to_FF_pointer (const float val); // cl_FF_to_float(obj,&val); // wandelt ein Single-Float obj in ein IEEE-Single-Float val um. diff -c -3 -r1.4 cl_FF_from_float.cc *** cln/src/float/ffloat/conv/cl_FF_from_float.cc 15 Sep 2007 21:34:16 -0000 1.4 --- cln/src/float/ffloat/conv/cl_FF_from_float.cc 21 Jan 2008 09:39:06 -0000 *************** *** 1,4 **** ! // cl_float_to_FF(). // General includes. #include "cl_sysdep.h" --- 1,7 ---- ! // cl_float_to_FF_pointer(). ! ! // Ensure that union ffloatjanus has a 'float' alternative. ! #define FAST_FLOAT // General includes. #include "cl_sysdep.h" *************** *** 10,17 **** // Implementation. ! cl_private_thing cl_float_to_FF_pointer (const ffloatjanus& val_) { var ffloat val = val_.eksplicit; var uintL exp = (val >> FF_mant_len) & (bit(FF_exp_len)-1); // e if (exp == 0) // e=0 ? --- 13,22 ---- // Implementation. ! cl_private_thing cl_float_to_FF_pointer (const float x) { + var union ffloatjanus val_; + val_.machine_float = x; var ffloat val = val_.eksplicit; var uintL exp = (val >> FF_mant_len) & (bit(FF_exp_len)-1); // e if (exp == 0) // e=0 ? diff -c -3 -r1.4 cl_LF_impl.h *** cln/src/float/lfloat/cl_LF_impl.h 15 Sep 2007 21:34:16 -0000 1.4 --- cln/src/float/lfloat/cl_LF_impl.h 21 Jan 2008 09:39:06 -0000 *************** *** 68,74 **** { var Lfloat _x = TheLfloat(obj); \ var uintE uexp = _x->expo; \ if (uexp==0) \ ! { mantlen_zuweisung _x->len; zero_statement } /* e=0 -> Zahl 0.0 */\ else \ { exp_zuweisung (sintE)(uexp - LF_exp_mid); /* Exponent */ \ sign_zuweisung _x->sign; /* Vorzeichen */\ --- 68,74 ---- { var Lfloat _x = TheLfloat(obj); \ var uintE uexp = _x->expo; \ if (uexp==0) \ ! { unused (mantlen_zuweisung _x->len); zero_statement } /* e=0 -> Zahl 0.0 */\ else \ { exp_zuweisung (sintE)(uexp - LF_exp_mid); /* Exponent */ \ sign_zuweisung _x->sign; /* Vorzeichen */\ diff -c -3 -r1.8 cl_LF_zeta_int.cc *** cln/src/float/transcendental/cl_LF_zeta_int.cc 11 Jan 2008 16:50:15 -0000 1.8 --- cln/src/float/transcendental/cl_LF_zeta_int.cc 21 Jan 2008 09:39:07 -0000 *************** *** 94,100 **** // evaluated using the binary splitting algorithm with truncation. var uintC actuallen = len+2; // 2 guard digits var uintC N = (uintC)(0.39321985*intDsize*actuallen)+1; - var uintC n; struct rational_series_stream : cl_pqd_series_stream { uintC n; int s; --- 94,99 ----