<p><strong>JTC1/SC22/WG14: N#### (N2823 revision 2)</strong></p>
<table border="1">
<tbody>
<tr>
<td><strong>Title:</strong></td>
<td>Freestanding C and IEC 60559 conformance scope reduction proposal</td>
</tr>
<tr>
<td><strong>Author:</strong></td>
<td>CFP</td>
</tr>
<tr>
<td><strong>Date:</strong></td>
<td>2022-01-20</td>
</tr>
</tbody>
</table>
<h3>Changes:</h3>
<table style="width: 486px;" border="1">
<tbody>
<tr>
<td style="width: 85.1875px;">Version 1:</td>
<td style="width: 383.812px;">
<ul>
<li>Original paper (N2823)</li>
</ul>
</td>
</tr>
<tr>
<td style="width: 85.1875px;">Version 2:</td>
<td style="width: 383.812px;">
<ul>
<li>Added in more motivation based on feedback from WG14</li>
<li>Structural changes (Paper header, change log, etc.)</li>
<li>Removed parts voted into C23</li>
<li>Added a third alternative (allow no error reporting)</li>
<li>Added a variation to alternative 1</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>1. Introduction:</h2>
<p>The incorporation of TS-18661 parts 1-3 into C23 brought in more requirements for freestanding C if the freestanding C implementation also conformed to the IEC 60559 parts brought in by the TS. This was indicated through defining some feature test macros (__STDC_IEC_60559_BFP__ and__STDC_IEC_60559_DFP__). Without defining those macros, the original C freestanding support remained. It is only when defining the macros that the implementation has extra functionality it needs to support. But by doing so, some people believe that unintended features are also pulled into being required for freestanding, even though they believe the intent was not to do so.</p>
<h3>Latest revision description:</h3>
<p>This is an update for N2823 as requested by WG14 in the 2021/11 meeting.</p>
<p>All changes requested by WG14 were made. They include: More text for motivation and rationale, removal of what was voted in already, and addition of relative diffs (from/to aspects of the suggested changes to the standard).</p>
<h2><strong>2. Motivation</strong></h2>
<p>Some members of the WG21 committee seem to be concerned with the expansion in scope in freestanding environments in C23 due to the changes brought in from the integration of TS 18661. This paper tries to address the concerns brought forward in WG14 reflector messages 19444 and 19445.</p>
<p>In reflector message 19445, a request was made to have the strtod* functions allow using exceptions to indicate error conditions. This woud allow not having to need thread local errno if the implementation so desires.</p>
<p>In reflector message 19444, concerns about requiring errno were brought up. Also having locale sesitive issues like whitespace and decimal separators for the numeric conversion functions brings in locales to the freestanding space. The addition of errno requires thread local storage, and the locale issue reduces portability.</p>
<p>The addition of thread local storage is a problem in general since freestanding applications often do not want to have "global" storage overhead or cannot have it. Locales have a similar issue in that most freestanding applications do not deal with locales (and hence the associated storage needed for them).</p>
<p>The general floating-point environment (described in 7.6) also has thread storage duration and hence requires overhead in terms of "global" storage. This was not directly mentioned in the reflector messages but is a conceivable concern that needs to be addressed.</p>
<h2>3. Counter claims and workarounds</h2>
<p>Since the addition of errno (along with the floating point environment) and locales are often problematic in freestanding implementations, those implementations can simply not define __STDC_IEC_60559_BFP__ and __STDC_IEC_60559_DFP__.</p>
<p>The argument often made is that that limits the portability of code in implementations that want to support IEEE floating point for freestanding, but can't due to the requirement for thread local storage and locale issues.</p>
<p>This is problematic in at least a couple of cases. First, the portabilty of locale support is already present in hosted implementations so this is not a new problem in general (though it can be for freestanding that wants to support the new floating point specifications). Second, in freestanding implementations, often threads are not supported anyways so the problem of having thread local storage decays into having extra global storage. While this does reduce the problem scope, it is still something that a number of freestanding implementations could consider a burden as global storage is often expensive or unavailable.</p>
<p>Reflector message 19444 had a hand-wavey recommendation to separate out language and library parts to allow the library to be supported only with new macro definitions which would end up not requiring thread local storage and locale support if the library macros were not defined. While this would work, the point of having the language and library parts present was to conform to the IEC standard. Separating them out would seem to miss the point of having the features there in the first place.</p>
<p>Although this was not brought forward by WG14 or WG21, another alternative would be to not have IEC 60559 binding at all for freestanding C as there may not be any demand for this case. CFP however believes it is needed so it was part of the original TS's and now in the C standard.</p>
<h2><strong>4. Proposed changes description</strong></h2>
<p>Some alternatives are proposed here to try and alleviate the concerns given above. The first one is intended to reduce the scope of changes brought in by the TS to remove requirements for thread local storage (errno) and modification to "global" state (the floating-point environment, which also has thread storage duration), and does so in a general way.</p>
<p>The second alternative (which can be done in conjunction with the first alternative if requested by WG14) is to let implementations choose between having errno or modifying the floating point exception states, or both where possible, and does so by modifying functions that currently require only errno to be set. Note that the second alternative does not remove the need to modify the floating-point environment in cases outside certain functions. For example, setting and clearing floating-point exception flags are required.</p>
<p>A variant for the second alternative is to not require any error reporting. This is proposed as alternative 3.</p>
<p>For alternative 1: The practical set of functions in the <strong>fenv.h</strong> header seem to be only <strong>fegetround</strong> and <strong>fe_dec_getround</strong>, but the other query functions were listed as well since they do not modify the floating-point environment. The reduced list of functions to be only <strong>fegetround</strong> and <strong>fe_dec_getround</strong> is a possible modification to alternative 1, if chosen.</p>
<h2><strong>5. Proposed changes text</strong></h2>
<p><strong><em>Alternative 1</em></strong>: In N2596, change Section 4#7 from:</p>
<p style="padding-left: 30px;">The strictly conforming programs that shall be accepted by a conforming freestanding implementation that defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__ may also use features in the contents of the standard headers <fenv.h> and <math.h> and the numeric conversion functions (7.22.1) of the standard header <stdlib.h>. All identifiers that are reserved when <stdlib.h> is included in a hosted implementation are reserved when it is included in a freestanding implementation.</p>
<p>to (exclusion version):</p>
<p style="padding-left: 30px;">The strictly conforming programs that shall be accepted by a conforming freestanding implementation that defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__ may also use features<span style="color: #339966;">, without the requirements to set errno (see 7.5) or modify the floating-point environment (see 7.6), in the following:<br /></span><span style="color: #339966;">- all the macros and the following functions in</span> <fenv.h><span style="color: #339966;">: fegetexceptflag, fetestexceptflag, fetestexcept, fegetmode, fegetround, fe_dec_getround, fegetenv</span><br /><span style="color: #339966;"> - </span><math.h><br /> <span style="color: #339966;">- the floating-point numeric conversion functions (7.22.1) of the standard header <stdlib.h>: strtod, strtof, strtold, strtod32, strtod64, strtod128</span><br /> All identifiers that are reserved when <stdlib.h><span style="color: #339966;"> and <fenv.h> are</span> included in a hosted implementation are reserved when it is included in a freestanding implementation.</p>
<p> In 7.22.1, insert before paragraph 1:</p>
<p style="padding-left: 30px;"><span style="color: #339966;">For freestanding implementations, neither errno or the floating-point exception flags need be affected by any of the functions in this clause; in addition, locales need not have any affect on these functions.</span></p>
<p>Or (inclusive version, only using the practical set of query functions in fenv.h):</p>
<p style="padding-left: 30px;">The strictly conforming programs that shall be accepted by a conforming freestanding implementation that defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__ may also use features in the contents of the standard header <span style="color: #339966;"><math.h><sup>[x]</sup>, the macros and rounding mode query functions</span> in the standard header <fenv.h><span style="color: #339966;"><sup>[x+1]</sup></span> and the <span style="color: #339966;">strto*</span> numeric conversion functions (7.22.1) of the standard header <stdlib.h><span style="color: #339966;"><sup>[x+2]</sup></span>. All identifiers that are reserved when <stdlib.h><span style="color: #339966;">, <fenv.h> and <math.h> are</span> included in a hosted implementation are reserved when it is included in a freestanding implementation.</p>
<p style="padding-left: 30px;"><span style="color: #339966;">[x] Since a conforming freestanding implementation is not required to accept program that use features in the contents of <errno.h>, the implementation need not provide thread storage for errno.</span></p>
<p style="padding-left: 30px;"><span style="color: #339966;">[x+1] Since a conforming freestanding implementation is not required to accept programs that use features in the contents of <fenv.h> for accessing floating-point exceptions or for changing the floating-point rounding mode, the implementation need not provide thread storage for the floating-point environment.</span></p>
<p style="padding-left: 30px;"><span style="color: #339966;">[x+2] Since only the "C" locale is required to be supported by an implementation, the conversion functions need not provide support for localized strings such as ones having different decimal separators.</span></p>
<p><br /><em><strong>Alternative 2</strong></em>: Allow exceptions to be raised for error conditions.</p>
<p>Note that this can be an independent addition to alternative 1.</p>
<p>In N2596 change the strto{d,f,ld} functions in 7.22.1.5#10 from:</p>
<p style="padding-left: 30px;">The functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value overflows and default rounding is in effect (7.12.1), plus or minus HUGE_VAL, HUGE_VALF, or HUGE_VALL is returned (according to the return type and sign of the value), and the value of the macro ERANGE is stored in errno. If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether errno acquires the value ERANGE is implementation-defined.</p>
<p>to:</p>
<p style="padding-left: 30px;">The functions return the converted value, if any. If no conversion could be performed, zero is returned.</p>
<p style="padding-left: 30px;">If the correct value overflows and default rounding is in effect (7.12.1), plus or minus HUGE_VAL, HUGE_VALF, or HUGE_VALL is returned (according to the return type and sign of the value); <span style="color: #339966;">if the integer expression <strong>math_errhandling & MATH_ERRNO</strong> is nonzero, the integer expression <strong>errno</strong> acquires the value <strong>ERANGE</strong>; if the integer expression <strong>math_errhandling & MATH_ERREXCEPT</strong> is nonzero, the "overflow" floating-point exception is raised.</span></p>
<p style="padding-left: 30px;">If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; <span style="color: #339966;">if the integer expression <strong>math_errhandling & MATH_ERRNO</strong> is nonzero, whether <strong>errno</strong> acquires the value <strong>ERANGE</strong> is implementation defined; if the integer expression <strong>math_errhandling & MATH_ERREXCEPT</strong> is nonzero, whether the "underflow" floating-point exception is raised.</span></p>
<p>For the analogous wide character functions:</p>
<p>Change 7.29.4.1.1#10 from:</p>
<p style="padding-left: 30px;">The functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value overflows and default rounding is in effect (7.12.1), plus or minus <strong>HUGE</strong><strong>_</strong><strong>VAL</strong>, <strong>HUGE</strong><strong>_</strong><strong>VALF</strong>, or <strong>HUGE</strong><strong>_</strong><strong>VALL </strong>is returned (according to the return type and sign of the value), and the value of the macro <strong>ERANGE </strong>is stored in <strong>errno</strong>. If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether <strong>errno </strong>acquires the value <strong>ERANGE </strong>is implementation-defined.</p>
<p>to:</p>
<p style="padding-left: 30px;">The functions return the converted value, if any. If no conversion could be performed, zero is returned.</p>
<p style="padding-left: 30px;">If the correct value overflows and default rounding is in effect (7.12.1), plus or minus <strong>HUGE</strong><strong>_</strong><strong>VAL</strong>, <strong>HUGE</strong><strong>_</strong><strong>VALF</strong>, or <strong>HUGE</strong><strong>_</strong><strong>VALL </strong>is returned (according to the return type and sign of the value); <span style="color: #339966;">if the integer expression <strong>math_errhandling & MATH_ERRNO</strong> is nonzero, the integer expression <strong>errno</strong> aquires the value <strong>ERANGE</strong>; if the integer expression <strong>math_errhandling & MATH_ERREXCEPT</strong> is nonzero, the "overflow" floating-point exception is raised.</span></p>
<p style="padding-left: 30px;">If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; <span style="color: #339966;">if the integer expression <strong>math_errhandling & MATH_ERRNO</strong> is nonzero, whether <strong>errno</strong> acquires the value <strong>ERANGE</strong> is implementation defined; if the integer expression <strong>math_errhandling & MATH_ERREXCEPT</strong> is nonzero, whether the "underflow" floating-point exception is raised</span> is implementation-defined.</p>
<p>Change 4#7 as follows from:</p>
<p style="padding-left: 30px;">The strictly conforming programs that shall be accepted by a conforming freestanding implementation that defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__ may also use features in the contents of the standard headers <fenv.h> and and <math.h> and the numeric conversion functions (7.22.1) of the standard header <stdlib.h>. All identifiers that are reserved when <stdlib.h> is included in a hosted implementation are reserved when it is included in a freestanding implementation.</p>
<p>to:</p>
<p style="padding-left: 30px;">The strictly conforming programs that shall be accepted by a conforming freestanding implementation that defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__ may also use features in the contents of the standard headers <fenv.h> and <math.h> and the <span style="color: #339966;">strto* f</span><span style="color: #339966;">loating-point</span> numeric conversion functions (7.22.1) of the standard header <stdlib.h>. All identifiers that are reserved when <stdlib.h> is included in a hosted implementation are reserved when it is included in a freestanding implementation.</p>
<p><em><strong>Alternative 3</strong></em>: No error handling version of alternative 2.</p>
<p>Do the changes in Alternative 2 + change 7.12#20 from:</p>
<p style="padding-left: 30px;">(... math_errhandling ...) expands to an expression that has type int and the value <strong>MATH_ERRNO</strong>, <strong>MATH_ERREXCEPT</strong>, or the bitwise OR of both.</p>
<p>to:</p>
<p style="padding-left: 30px;">(... math_errhandling ...) expands to an expression that has type int and the value <span style="color: #339966;">0,</span> <strong>MATH_ERRNO</strong>, <strong>MATH_ERREXCEPT</strong>, or the bitwise OR of both <span style="color: #339966;"><strong>MATH_ERRNO</strong> and <strong>MATH_ERREXCEPT</strong>.</span></p>