Attached is a patch that addresses most of Dodji Seketeli's comments. Explanations for the rest are inline.
On 10/14/2013 03:04 AM, Dodji Seketeli wrote: > Thank you Joshua for following up on this. Please find below some > comments of mine that mostly belong to the nitpicking department. You are welcome, and thank you for looking at it and commenting on it. > Joshua J Cogliati <jrinc...@yahoo.com> writes: > > [...] > >> A split out patch to make the floating conversions explicit is attached >> at the PR 53001 page, but is not included in this patch. > > It'd be nice to sent that split out patch here too, as it's a > pre-requisite for this to pass bootstrap w/o warning. Otherwise I am > afraid that patch isn't likely to get reviewed. It is not a prerequisite of the attached patch warn_float_patch_simple_trunk.diff. It becomes a pre-requisite if -Wfloat-conversion is enabled with -Wextra. I did attached fixup_float_conversions.diff that makes the changes needed in gcc. > [...] > >> == Testcases == >> >> This patch has passes the existing -Wconversion testcases. It modifies >> Wconversion-real.c, Wconversion-real-integer.c and pr35635.c to be more >> specific > > If the patch passes existing tests, I'd be inclined to leave them > tests alone and add new ones that are specific to what this patch > changes. You can even start from a copy of the tests you've modified > above and trim them down so that only exercise the new code paths > you've added; and of course add more cases top of these, if you can. > But I won't fight hard for this if the other maintainers think it's OK > this way. :-) Hm. For gcc/testsuite/c-c++-common/Wconversion-real.c all the tests in it are float-conversion by the patch's definition. For gcc/testsuite/gcc.dg/Wconversion-real-integer.c it already had a mixture of conversion and overflow, so it is now a mixture conversion, float-conversion and overflow. Maybe gcc/testsuite/gcc.dg/pr35635.c should stay the same. I don't think new tests are needed since the existing ones can just be switched; otherwise the testcases would be redundant. I certainly can change the patch if needed. > [...] > >> == Changelog == > > [...] > >> * gcc/c-family/c-common.c Switching unsafe_conversion_p to >> return an enumeration with more detail, and conversion_warning >> to use this information. > > The correct format for this ChangeLog entry would be: > > <tab>* gcc/c-family/c-common.c (unsafe_conversion_p): > <insert-your-comment-here>. > > Please modify the rest of the ChangeLog entries to comply with this. > Sorry if this seems nit-picky but I guess we need to keep all the > ChangeLog entries coherent. Here we go again: Splitting out a -Wfloat-conversion from -Wconversion for conversions that lower floating point number precision or conversion from floating point numbers to integers * gcc/c-family/c-common.c Switching unsafe_conversion_p to return an enumeration with more detail, and conversion_warning to use this information. * gcc/c-family/c-common.h Adding conversion_safety enumeration and switching return type of unsafe_conversion_p * gcc/c-family/c.opt Adding new warning float-conversion and enabling it -Wconversion * gcc/doc/invoke.texi Adding documentation about -Wfloat-conversion * gcc/testsuite/c-c++-common/Wconversion-real.c Switching tests to use float-conversion * gcc/testsuite/gcc.dg/Wconversion-real-integer.c Switching tests to use float-conversion * gcc/testsuite/gcc.dg/pr35635.c Switching tests to use float-conversion > > [...] > >> +++ gcc/c-family/c-common.c (working copy) >> @@ -2517,10 +2517,10 @@ shorten_binary_op (tree result_type, tre >> Function allows conversions between types of different signedness and >> does not return true in that case. Function can produce signedness >> warnings if PRODUCE_WARNS is true. */ >> -bool >> +enum conversion_safety >> unsafe_conversion_p (tree type, tree expr, bool produce_warns) >> { > > As you are modifying the return type of this function, I think you > should update the comment of the function too, especially the part > that talks about the return values. Changed. <snip> > > You don't need the curly brackets here, so please move them. > Changed. <snip> > >> +++ gcc/c-family/c-common.h (working copy) > > [...] > > >> +/* These variables are possible types of unsafe conversions. > > I would say "These enumerators", rather than "These variables". Changed. <snip> > > Other than these nits, the patch looks nice to me. > > Thank you for working on this. >
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 203112) +++ gcc/c-family/c-common.c (working copy) @@ -2507,7 +2507,7 @@ shorten_binary_op (tree result_type, tre } /* Checks if expression EXPR of real/integer type cannot be converted - to the real/integer type TYPE. Function returns true when: + to the real/integer type TYPE. Function returns non-zero when: * EXPR is a constant which cannot be exactly converted to TYPE * EXPR is not a constant and size of EXPR's type > than size of TYPE, for EXPR type and TYPE being both integers or both real. @@ -2515,12 +2515,12 @@ shorten_binary_op (tree result_type, tre * EXPR is not a constant of integer type which cannot be exactly converted to real type. Function allows conversions between types of different signedness and - does not return true in that case. Function can produce signedness - warnings if PRODUCE_WARNS is true. */ -bool + can return SAFE_CONVERSION (zero) in that case. Function can produce + signedness warnings if PRODUCE_WARNS is true. */ +enum conversion_safety unsafe_conversion_p (tree type, tree expr, bool produce_warns) { - bool give_warning = false; + enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); @@ -2532,7 +2532,7 @@ unsafe_conversion_p (tree type, tree exp && TREE_CODE (type) == INTEGER_TYPE) { if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type))) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for an integer constant that does not fit into integer type. */ else if (TREE_CODE (expr_type) == INTEGER_TYPE @@ -2553,7 +2553,7 @@ unsafe_conversion_p (tree type, tree exp " constant value to negative integer"); } else - give_warning = true; + give_warning = UNSAFE_OTHER; } else if (TREE_CODE (type) == REAL_TYPE) { @@ -2562,7 +2562,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for a real constant that does not fit into a smaller real type. */ @@ -2571,7 +2571,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = TREE_REAL_CST (expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } } } @@ -2580,7 +2580,7 @@ unsafe_conversion_p (tree type, tree exp /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) - give_warning = true; + give_warning = UNSAFE_REAL; else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE) @@ -2618,7 +2618,7 @@ unsafe_conversion_p (tree type, tree exp && int_fits_type_p (op1, c_common_signed_type (type)) && int_fits_type_p (op1, c_common_unsigned_type (type)))) - return false; + return SAFE_CONVERSION; /* If constant is unsigned and fits in the target type, then the result will also fit. */ else if ((TREE_CODE (op0) == INTEGER_CST @@ -2627,12 +2627,12 @@ unsafe_conversion_p (tree type, tree exp || (TREE_CODE (op1) == INTEGER_CST && unsigned1 && int_fits_type_p (op1, type))) - return false; + return SAFE_CONVERSION; } } /* Warn for integer types converted to smaller integer types. */ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_OTHER; /* When they are the same width but different signedness, then the value may change. */ @@ -2668,14 +2668,14 @@ unsafe_conversion_p (tree type, tree exp if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) - give_warning = true; + give_warning = UNSAFE_OTHER; } /* Warn for real types converted to smaller real types. */ else if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_REAL; } return give_warning; @@ -2689,8 +2689,9 @@ conversion_warning (tree type, tree expr { tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); + enum conversion_safety conversion_kind; - if (!warn_conversion && !warn_sign_conversion) + if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) return; switch (TREE_CODE (expr)) @@ -2717,7 +2718,12 @@ conversion_warning (tree type, tree expr case REAL_CST: case INTEGER_CST: - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if(conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT alters %qT constant value", + type, expr_type); + else if(conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT alters %qT constant value", type, expr_type); @@ -2736,7 +2742,12 @@ conversion_warning (tree type, tree expr } default: /* 'expr' is not a constant. */ - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if(conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT from %qT may alter its value", + type, expr_type); + else if(conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT from %qT may alter its value", type, expr_type); Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 203112) +++ gcc/c-family/c-common.h (working copy) @@ -685,6 +685,16 @@ struct visibility_flags unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */ }; +/* These enumerators are possible types of unsafe conversions. + SAFE_CONVERSION The conversion is safe + UNSAFE_OTHER Another type of conversion with problems + UNSAFE_SIGN Conversion between signed and unsigned integers + which are all warned about immediately, so this is unused + UNSAFE_REAL Conversions that reduce the precision of reals + including conversions from reals to integers + */ +enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL }; + /* Global visibility options. */ extern struct visibility_flags visibility_options; @@ -738,7 +748,7 @@ extern tree c_common_signed_type (tree); extern tree c_common_signed_or_unsigned_type (int, tree); extern void c_common_init_ts (void); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); -extern bool unsafe_conversion_p (tree, tree, bool); +extern enum conversion_safety unsafe_conversion_p (tree, tree, bool); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *); extern tree decl_constant_value_for_optimization (tree); Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 203112) +++ gcc/c-family/c.opt (working copy) @@ -387,6 +387,10 @@ Werror-implicit-function-declaration C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead +Wfloat-conversion +C ObjC C++ ObjC++ Var(warn_float_conversion) LangEnabledBy(C ObjC C++ ObjC++,Wconversion) +Warn for implicit type conversions that cause loss of floating point precision + Wfloat-equal C ObjC C++ ObjC++ Var(warn_float_equal) Warning Warn if testing floating point numbers for equality Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 203112) +++ gcc/doc/invoke.texi (working copy) @@ -263,7 +263,8 @@ Objective-C and Objective-C++ Dialects}. -Wpointer-arith -Wno-pointer-to-int-cast @gol -Wredundant-decls -Wno-return-local-addr @gol -Wreturn-type -Wsequence-point -Wshadow @gol --Wsign-compare -Wsign-conversion -Wsizeof-pointer-memaccess @gol +-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol +-Wsizeof-pointer-memaccess @gol -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol @@ -4570,6 +4571,14 @@ value, like assigning a signed integer e integer variable. An explicit cast silences the warning. In C, this option is enabled also by @option{-Wconversion}. +@item -Wfloat-conversion +@opindex Wfloat-conversion +@opindex Wno-float-conversion +Warn for implicit conversions that reduce the precision of a real value. +This includes conversions from real to integer, and from higher precision +real to lower precision real values. This option is also enabled by +@option{-Wconversion}. + @item -Wsizeof-pointer-memaccess @opindex Wsizeof-pointer-memaccess @opindex Wno-sizeof-pointer-memaccess Index: gcc/testsuite/c-c++-common/Wconversion-real.c =================================================================== --- gcc/testsuite/c-c++-common/Wconversion-real.c (revision 203112) +++ gcc/testsuite/c-c++-common/Wconversion-real.c (working copy) @@ -2,8 +2,8 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats" { "avr-*-*" } { "*" } { "" } } */ -/* { dg-options "-std=c99 -Wconversion" { target c } } */ -/* { dg-options "-Wconversion" { target c++ } } */ +/* { dg-options "-std=c99 -Wfloat-conversion" { target c } } */ +/* { dg-options "-Wfloat-conversion" { target c++ } } */ /* { dg-require-effective-target large_double } */ float vfloat; @@ -20,18 +20,18 @@ void h (void) double d = 0; long double ld = 0; - ffloat (3.1); /* { dg-warning "conversion" } */ - vfloat = 3.1; /* { dg-warning "conversion" } */ - ffloat (3.1L); /* { dg-warning "conversion" } */ - vfloat = 3.1L; /* { dg-warning "conversion" } */ - fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */ - ffloat (vdouble); /* { dg-warning "conversion" } */ - vfloat = vdouble; /* { dg-warning "conversion" } */ - ffloat (vlongdouble); /* { dg-warning "conversion" } */ - vfloat = vlongdouble; /* { dg-warning "conversion" } */ - fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */ + ffloat (3.1); /* { dg-warning "float-conversion" } */ + vfloat = 3.1; /* { dg-warning "float-conversion" } */ + ffloat (3.1L); /* { dg-warning "float-conversion" } */ + vfloat = 3.1L; /* { dg-warning "float-conversion" } */ + fdouble (3.1L); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = 3.1L; /* { dg-warning "float-conversion" "" { target large_long_double } } */ + ffloat (vdouble); /* { dg-warning "float-conversion" } */ + vfloat = vdouble; /* { dg-warning "float-conversion" } */ + ffloat (vlongdouble); /* { dg-warning "float-conversion" } */ + vfloat = vlongdouble; /* { dg-warning "float-conversion" } */ + fdouble (vlongdouble); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = vlongdouble; /* { dg-warning "float-conversion" "" { target large_long_double } } */ ffloat ((float) 3.1); Index: gcc/testsuite/gcc.dg/Wconversion-real-integer.c =================================================================== --- gcc/testsuite/gcc.dg/Wconversion-real-integer.c (revision 203112) +++ gcc/testsuite/gcc.dg/Wconversion-real-integer.c (working copy) @@ -25,18 +25,18 @@ void h (void) float f = 3; double d = 3; - fsi (3.1f); /* { dg-warning "conversion" } */ - si = 3.1f; /* { dg-warning "conversion" } */ - fsi (3.1); /* { dg-warning "conversion" } */ - si = 3.1; /* { dg-warning "conversion" } */ - fsi (d); /* { dg-warning "conversion" } */ - si = d; /* { dg-warning "conversion" } */ + fsi (3.1f); /* { dg-warning "float-conversion" } */ + si = 3.1f; /* { dg-warning "float-conversion" } */ + fsi (3.1); /* { dg-warning "float-conversion" } */ + si = 3.1; /* { dg-warning "float-conversion" } */ + fsi (d); /* { dg-warning "float-conversion" } */ + si = d; /* { dg-warning "float-conversion" } */ fui (-1.0); /* { dg-warning "overflow" } */ ui = -1.0; /* { dg-warning "overflow" } */ - ffloat (INT_MAX); /* { dg-warning "conversion" } */ - vfloat = INT_MAX; /* { dg-warning "conversion" } */ - ffloat (16777217); /* { dg-warning "conversion" } */ - vfloat = 16777217; /* { dg-warning "conversion" } */ + ffloat (INT_MAX); /* { dg-warning "float-conversion" } */ + vfloat = INT_MAX; /* { dg-warning "float-conversion" } */ + ffloat (16777217); /* { dg-warning "float-conversion" } */ + vfloat = 16777217; /* { dg-warning "float-conversion" } */ ffloat (si); /* { dg-warning "conversion" } */ vfloat = si; /* { dg-warning "conversion" } */ ffloat (ui); /* { dg-warning "conversion" } */ Index: gcc/testsuite/gcc.dg/pr35635.c =================================================================== --- gcc/testsuite/gcc.dg/pr35635.c (revision 203112) +++ gcc/testsuite/gcc.dg/pr35635.c (working copy) @@ -45,7 +45,7 @@ void func2() /* At least one branch of ? does not fit in the destination, thus warn. */ - schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */ + schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ schar_x = bar != 0 ? (signed char) 1024: -1024; /* { dg-warning "conversion" } */ } @@ -61,7 +61,7 @@ void func3() /* At least one branch of ? does not fit in the destination, thus warn. */ - uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */ + uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ uchar_x = bar != 0 ? (unsigned char) 1024 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
Index: gcc/c-family/c-cppbuiltin.c =================================================================== --- gcc/c-family/c-cppbuiltin.c (revision 203112) +++ gcc/c-family/c-cppbuiltin.c (working copy) @@ -157,7 +157,7 @@ builtin_define_float_constants (const ch p log10 b if b is a power of 10 floor((p - 1) log10 b) otherwise */ - dig = (fmt->p - 1) * log10_b; + dig = (int)((fmt->p - 1) * log10_b); sprintf (name, "__%s_DIG__", name_prefix); builtin_define_with_int_value (name, dig); @@ -173,7 +173,7 @@ builtin_define_float_constants (const ch Recall that emin is negative, so the integer truncation calculates the ceiling, not the floor, in this case. */ - min_10_exp = (fmt->emin - 1) * log10_b; + min_10_exp = (int)((fmt->emin - 1) * log10_b); sprintf (name, "__%s_MIN_10_EXP__", name_prefix); sprintf (buf, "(%d)", min_10_exp); builtin_define_with_value (name, buf, 0); @@ -208,7 +208,7 @@ builtin_define_float_constants (const ch Hand-waving aside, crunching all of the sets of constants above by hand does not yield a case for which the first term is significant, which in the end is all that matters. */ - max_10_exp = fmt->emax * log10_b; + max_10_exp = (int)(fmt->emax * log10_b); sprintf (name, "__%s_MAX_10_EXP__", name_prefix); builtin_define_with_int_value (name, max_10_exp); @@ -224,14 +224,14 @@ builtin_define_float_constants (const ch { double d_decimal_dig = 1 + (fmt->p < ldfmt->p ? ldfmt->p : fmt->p) * log10_b; - decimal_dig = d_decimal_dig; + decimal_dig = (int)d_decimal_dig; if (decimal_dig < d_decimal_dig) decimal_dig++; } /* Similar, for this type rather than long double. */ { double type_d_decimal_dig = 1 + fmt->p * log10_b; - type_decimal_dig = type_d_decimal_dig; + type_decimal_dig = (int)type_d_decimal_dig; if (type_decimal_dig < type_d_decimal_dig) type_decimal_dig++; } Index: gcc/mcf.c =================================================================== --- gcc/mcf.c (revision 203112) +++ gcc/mcf.c (working copy) @@ -348,8 +348,8 @@ mcf_sqrt (double x) gcc_assert (x >= 0); - convertor.floatPart = x; - convertor2.floatPart = x; + convertor.floatPart = (float)x; + convertor2.floatPart = (float)x; convertor.intPart = MAGIC_CONST1 + (convertor.intPart >> 1); convertor2.intPart = MAGIC_CONST2 - (convertor2.intPart >> 1); Index: gcc/predict.c =================================================================== --- gcc/predict.c (revision 203112) +++ gcc/predict.c (working copy) @@ -792,7 +792,7 @@ combine_predictions_for_insn (rtx insn, /* If one probability is 0% and one 100%, avoid division by zero. */ combined_probability = REG_BR_PROB_BASE / 2; else - combined_probability = (((double) combined_probability) * probability + combined_probability = (int)(((double) combined_probability) * probability * REG_BR_PROB_BASE / d + 0.5); } @@ -957,7 +957,7 @@ combine_predictions_for_bb (basic_block /* If one probability is 0% and one 100%, avoid division by zero. */ combined_probability = REG_BR_PROB_BASE / 2; else - combined_probability = (((double) combined_probability) + combined_probability = (int)(((double) combined_probability) * probability * REG_BR_PROB_BASE / d + 0.5); } Index: gcc/real.c =================================================================== --- gcc/real.c (revision 203112) +++ gcc/real.c (working copy) @@ -1550,14 +1550,14 @@ real_to_decimal_for_mode (char *str, con } /* Bound the number of digits printed by the size of the representation. */ - max_digits = SIGNIFICAND_BITS * M_LOG10_2; + max_digits = (int)(SIGNIFICAND_BITS * M_LOG10_2); if (digits == 0 || digits > max_digits) digits = max_digits; /* Estimate the decimal exponent, and compute the length of the string it will print as. Be conservative and add one to account for possible overflow or rounding error. */ - dec_exp = REAL_EXP (&r) * M_LOG10_2; + dec_exp = (int)(REAL_EXP (&r) * M_LOG10_2); for (max_digits = 1; dec_exp ; max_digits++) dec_exp /= 10; @@ -2215,7 +2215,7 @@ decimal_integer_string (char *str, const sign = r.sign; r.sign = 0; - dec_exp = REAL_EXP (&r) * M_LOG10_2; + dec_exp = (int)(REAL_EXP (&r) * M_LOG10_2); digits = dec_exp + 1; gcc_assert ((digits + 2) < (int)buf_size); @@ -2818,7 +2818,7 @@ significand_size (enum machine_mode mode than the number of bits required to hold the largest coefficient of this mode. */ double log2_10 = 3.3219281; - return fmt->p * log2_10; + return (int)(fmt->p * log2_10); } return fmt->p; } Index: libcpp/symtab.c =================================================================== --- libcpp/symtab.c (revision 203112) +++ libcpp/symtab.c (working copy) @@ -287,7 +287,8 @@ ht_dump_statistics (cpp_hash_table *tabl : (x) / (1024*1024)))) #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M')) - total_bytes = longest = sum_of_squares = nids = 0; + total_bytes = longest = nids = 0; + sum_of_squares = 0.0; p = table->entries; limit = p + table->nslots; do