Open vinc17fr opened 4 months ago
It's not clear to me what it means to "evaluate a constant" if you're talking about a constant that isn't used as part of a constant expression. Elsewhere the standard says, "The translation-time conversion of floating constants should match the execution-time conversion of character strings by library functions, such as strtod, given matching inputs suitable for both conversions, the same result format, and default execution-time rounding." But this is listed as a recommended practice.
It's not clear to me that 0.1f (for example) should be represented the same way that 0.1L would be, even when FLT_EVAL_METHOD is 2. I'm inclined to regard the evaluation of a constant as referring to how constant expressions are evaluated (for example, "10.0f/1.0f"). It seems that gcc interprets it as you do, translating literal constants directly to the higher precision type. The Intel Classic Compiler (icc) uses the single-precision rendering of the literal, promoted to extended precision, but evaluates constant expressions at extended precision. Clang doesn't seem to apply the eval method to constants in any way.
It's not clear to me what it means to "evaluate a constant" if you're talking about a constant that isn't used as part of a constant expression.
This is the translation-time conversion of the constant.
Elsewhere the standard says, "The translation-time conversion of floating constants should match the execution-time conversion of character strings by library functions, such as strtod, given matching inputs suitable for both conversions, the same result format, and default execution-time rounding." But this is listed as a recommended practice.
Note that above this paragraph: "For decimal floating constants, and also for hexadecimal floating constants when FLT_RADIX is not a power of 2, the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner." And with FLT_EVAL_METHOD = 2, the evaluation type is long double. So, blindly using a smaller format is wrong.
It's not clear to me that 0.1f (for example) should be represented the same way that 0.1L would be, even when FLT_EVAL_METHOD is 2.
Not necessarily, but it must be close enough to the nearest representable value in long double. And with Annex F, correct rounding is required for this constant.
I'm inclined to regard the evaluation of a constant as referring to how constant expressions are evaluated (for example, "10.0f/1.0f"). It seems that gcc interprets it as you do, translating literal constants directly to the higher precision type. The Intel Classic Compiler (icc) uses the single-precision rendering of the literal, promoted to extended precision, but evaluates constant expressions at extended precision.
I would say that icc is buggy.
Clang doesn't seem to apply the eval method to constants in any way.
It does, but on this machine on godbolt, FLT_EVAL_METHOD = 0 instead of 2. Thus you get the behavior for FLT_EVAL_METHOD = 0.
@llvm/issue-subscribers-clang-frontend
Author: Vincent Lefèvre (vinc17fr)
It's not clear to me what it means to "evaluate a constant" if you're talking about a constant that isn't used as part of a constant expression.
C23 5.1.2.4p2: Evaluation of an expression in general includes both value computations and initiation of side effects. Value computation for an lvalue expression includes determining the identity of the designated object.
So evaluating a constant means getting the value computation of it, which I believe is subject to FLT_EVAL_METHOD.
Elsewhere the standard says, "The translation-time conversion of floating constants should match the execution-time conversion of character strings by library functions, such as strtod, given matching inputs suitable for both conversions, the same result format, and default execution-time rounding." But this is listed as a recommended practice.
We should be following recommended practices unless we have a good reason not to.
Elsewhere the standard says, "The translation-time conversion of floating constants should match the execution-time conversion of character strings by library functions, such as strtod, given matching inputs suitable for both conversions, the same result format, and default execution-time rounding." But this is listed as a recommended practice.
We should be following recommended practices unless we have a good reason not to.
Note that before considering this recommended practice, the destination format/type has to be determined, which is the point of this bug.
It does, but on this machine on godbolt, FLT_EVAL_METHOD = 0 instead of 2. Thus you get the behavior for FLT_EVAL_METHOD = 0.
FWIW, -m32 -mno-sse
generally gets you to FLT_EVAL_METHOD=2.
I should clarify that I'm in no way opposed to fixing this behavior in clang. I'm happy to accept the interpretation that's been described here, and I appreciate the explanation.
Do folks want this question raised with the C floating point study group or WG14? If so, I can ask on the reflectors (or @jcranmer-intel could ask at the next SG meeting, perhaps).
The ISO C17 standard says in 5.2.4.2.2p9, when
FLT_EVAL_METHOD
is 2: "evaluate all operations and constants to the range and precision of the long double type." (note the word "constants"). But Debian clang version 18.1.3 (1) does not behave that way:gives with
-m32 -std=c17
on x86_64:instead of