On Fri, Mar 21, 2025 at 08:25:10PM +0100, Richard Biener wrote: > > --- gcc/cobol/parse.y.jj 2025-03-21 17:49:43.571440176 +0100 > > +++ gcc/cobol/parse.y 2025-03-21 20:15:24.852414777 +0100 > > @@ -4331,7 +4331,8 @@ value_clause: VALUE all LITERAL[lit] { > > cbl_field_t *field = current_field(); > > auto orig_str = original_number(); > > REAL_VALUE_TYPE orig_val; > > - real_from_string (&orig_val, orig_str); > > + real_from_string3 (&orig_val, orig_str, > > + TYPE_MODE (float128_type_node)); > > char *initial = NULL; > > > > if( real_identical (&orig_val, &$value) ) { > > @@ -6922,7 +6923,8 @@ cce_expr: cce_factor > > cce_factor: NUMSTR { > > /* ??? real_from_string does not allow arbitrary radix. > > */ > > // $$ = numstr2i($1.string, $1.radix); > > - real_from_string (&$$, $1.string); > > + real_from_string3 (&$$, $1.string, > > + TYPE_MODE (float128_type_node)); > > } > > ; > > > > > > The old code was just using _Float128 which has the IEEE quad precision, > > but REAL_VALUE_TYPE in GCC actually has larger internal precision than that, > > so if it isn't rounded to the IEEE quad precision first and builds REAL_CST, > > it isn't the expected 0.0100000000000000000000000000000000002 but > > 0.009999999999...
Without real_from_string3 (or real_from_string + real_convert, the former is just a shorthand for that) you can have excess precision in the stored REAL_VALUE_TYPE, which certainly can't then match what happens when the FE uses _Float128 directly. > we've come from initial_from_float128 which does > > REAL_VALUE_TYPE pow10 > = real_powi10 (field->data.digits + field->data.rdigits); > real_arithmetic (&value, MULT_EXPR, &value, &pow10); > > which produces the 1.0e+0 - do I need to process this to be "normal"? That real_arithmetic is also supposed to be followed by real_convert, otherwise again there is an excess precision. That could be desirable at times but certainly not if it attempts to work the same as former _Float128 *= __int128. Because that computation also rounds. When fold-const.cc calls real_arithmetic, it does that as well: inexact = real_arithmetic (&value, code, &d1, &d2); real_convert (&result, mode, &value); Jakub