<html><body>
<p><font size="2" face="sans-serif">I thought I'd try approaching this from the opposite direction: &nbsp;How would you change C++ to handle floating-point exceptions? &nbsp;Then could / how could that be handled in C, and would that also work in C++?</font><br>
<br>
<br>
<font size="2" face="sans-serif">So far C++ exceptions only come from throw statements, never from floating-point exceptions (also never from traps, other hardware detected events, or operating system detected events). &nbsp;Let's assume that is changed so they can come from floating-point exceptions.</font><br>
<br>
<font size="2" face="sans-serif">In C++, a catch clause catches an exception object according to its type, not its value, then is optionally told the value.</font><br>
<font size="2" face="sans-serif">&nbsp;- One way to use that is to define a &quot;floating point exception&quot; struct type that contains something identifying which exception(s) happened in the try block, and possibly information about the kind of operation and the input value(s) triggering it, and catch would catch an object.</font><br>
<font size="2" face="sans-serif">&nbsp;- Another way is to have a separate type for each possible exception.</font><br>
<font size="2" face="sans-serif">&nbsp;- In C++ those could be merged using base and derived types.</font><br>
<font size="2" face="sans-serif">For any of those, we should also define how to handle implementation-defined exceptions; for example, PowerPC has half a dozen specific kinds of invalid operation exceptions plus a general flag combining them.</font><br>
<br>
<font size="2" face="sans-serif">There are of course many variations but syntactically, so far it could look like</font><br>
<br>
<tt><font size="2">        try {</font></tt><br>
<tt><font size="2">                . . . block of code . . .</font></tt><br>
<tt><font size="2">        }</font></tt><br>
<tt><font size="2">        catch (FPException::Overflow fpexception) &nbsp;{ /* overflow handler */ . . . }</font></tt><br>
<tt><font size="2">#ifdef PPC</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_SignalingNaN fpexception) &nbsp;{ /* SNaN handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_InvalidConversion fpexception) &nbsp;{ /* Invalid Conversion handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_SqrtOfNegative fpexception) &nbsp;{ /* Sqrt of Negative handler */ . . . }</font></tt><br>
<tt><font size="2">#endif</font></tt><br>
<tt><font size="2">        catch (FPException::InvalidOperation fpexception) &nbsp;{ /* General Invalid Operation handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::ZeroDivide fpexception) &nbsp;{ /* Divide Finite by Zero handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (int m) &nbsp;{ /* integer handler */ }</font></tt><br>
<tt><font size="2">        catch (...) { /* handler for anything else */ }</font></tt><br>
<br>
<font size="2" face="sans-serif">In each of the </font><tt><font size="2">FPException</font></tt><font size="2" face="sans-serif">&nbsp;catch clauses, the &quot;</font><tt><font size="2">fpexception</font></tt><font size="2" face="sans-serif">&quot; is like a function parameter containing the exception information, is optional, and can be any name you choose.</font><br>
<br>
<font size="2" face="sans-serif">A </font><tt><font size="2">catch</font></tt><font size="2" face="sans-serif">&nbsp;clause can have a list of exception types if they all need the same handling.</font><br>
<br>
<font size="2" face="sans-serif">This is only part of the solution. &nbsp;One issue is how the exceptions to check are to be specified.</font><br>
<br>
<font size="2" face="sans-serif">The rule could be that the floating-point exceptions to be checked for would be those which have a catch clause naming them, but that's not true for general C++ exceptions so would be an inconsistency. &nbsp;A portable way to specify which ones to enable would be useful; for example it could be a function like</font><br>
<font size="2" face="sans-serif">        </font><tt><font size="2">FPEnable &nbsp;oldcontrols = enableFPExceptions (FPEnable::Overflow | FPEnable::InvalidOperation | FPEnable::ZeroDivide);</font></tt><br>
<font size="2" face="sans-serif">which sets up exception checking controls and returns the old exception controls, along with another function to restore the saved controls afterwards</font><br>
<font size="2" face="sans-serif">        </font><tt><font size="2">restoreFPExceptions (oldcontrols);</font></tt><br>
<font size="2" face="sans-serif">Since a catch handler doesn't have access to the try block's local variables, those would have to be outside the try block. &nbsp;They could be useful elsewhere too.</font><br>
<br>
<font size="2" face="sans-serif">In C++ an alternative would be that the control setting would construct an object whose destructor would automatically do the restore (although that wouldn't work for C which doesn't have constructors and destructors), eg,</font><br>
<tt><font size="2">        {</font></tt><br>
<tt><font size="2">                FPEnableExceptions oldcontrols (FPEnable::Overflow | FPEnable::InvalidOperation | FPEnable::ZeroDivide);</font></tt><br>
<tt><font size="2">                try . . .</font></tt><br>
<tt><font size="2">                // At the end of this block the destructor FPEnableExceptions::~FPEnableExceptions (oldcontrols) would be run,</font></tt><br>
<tt><font size="2">                // restoring the old controls.</font></tt><br>
<tt><font size="2">        }</font></tt><br>
<br>
<font size="2" face="sans-serif">Assuming the first way (because it's more compatible with C), the combination (with the </font><tt><font size="2">int</font></tt><font size="2" face="sans-serif">&nbsp;and </font><tt><font size="2">...</font></tt><font size="2" face="sans-serif">&nbsp;deleted)</font><font size="2" face="sans-serif">&nbsp;is</font><br>
<br>
<tt><font size="2">        FPExceptionControls &nbsp;oldcontrols = enableFPExceptions (FPEnable::Overflow | FPEnable::InvalidOperation | FPEnable::ZeroDivide);</font></tt><br>
<tt><font size="2">        try {</font></tt><br>
<tt><font size="2">                . . . block of code . . .</font></tt><br>
<tt><font size="2">        }</font></tt><br>
<tt><font size="2">        catch (FPException::Overflow fpexception) &nbsp;{ /* overflow handler */ . . . }</font></tt><br>
<tt><font size="2">#ifdef PPC</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_SignalingNaN fpexception) &nbsp;{ /* SNaN handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_InvalidConversion fpexception) &nbsp;{ /* Invalid Conversion handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::PowerPC_SqrtOfNegative fpexception) &nbsp;{ /* Sqrt of Negative handler */ . . . }</font></tt><br>
<tt><font size="2">#endif</font></tt><br>
<tt><font size="2">        catch (FPException::InvalidOperation fpexception) &nbsp;{ /* General Invalid Operation handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (FPException::ZeroDivide fpexception) &nbsp;{ /* Divide Finite by Zero handler */ . . . }</font></tt><br>
<tt><font size="2">        restoreFPExceptions (oldcontrols);</font></tt><br>
<br>
<br>
<font size="2" face="sans-serif">What about C? &nbsp;C doesn't have </font><tt><font size="2">try</font></tt><font size="2" face="sans-serif">, </font><tt><font size="2">throw</font></tt><font size="2" face="sans-serif">&nbsp;or </font><tt><font size="2">catch</font></tt><font size="2" face="sans-serif">, and doesn't have classes so the &quot;</font><tt><font size="2">::</font></tt><font size="2" face="sans-serif">&quot; syntax wouldn't work, but possibly could have something like</font><font size="2" face="sans-serif">:</font><br>
<br>
<tt><font size="2">        fpexceptioncontrols &nbsp;oldcontrols = enablefpexceptions (fpexception_overflow | fpexception_invalidoperation | fpexception_zerodivide);</font></tt><br>
<tt><font size="2">        try {</font></tt><br>
<tt><font size="2">                . . . block of code . . .</font></tt><br>
<tt><font size="2">        }</font></tt><br>
<tt><font size="2">        catch (fpexception_overflow &nbsp;fpexception) &nbsp;{ /* overflow handler */ . . . }</font></tt><br>
<tt><font size="2">#ifdef PPC</font></tt><br>
<tt><font size="2">        catch (fpexception_powerpc_signalingnan &nbsp;fpexception) &nbsp;{ /* SNaN handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (fpexception_powerpc_invalidconversion &nbsp;fpexception) &nbsp;{ /* Invalid Conversion handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (fpexception_powerpc_sqrtofnegative &nbsp;fpexception) &nbsp;{ /* Sqrt of Negative handler */ . . . }</font></tt><br>
<tt><font size="2">#endif</font></tt><br>
<tt><font size="2">        catch (fpexception_invalidoperation &nbsp;fpexception) &nbsp;{ /* General Invalid Operation handler */ . . . }</font></tt><br>
<tt><font size="2">        catch (fpexception_zerodivide &nbsp;fpexception) &nbsp;{ /* Divide Finite by Zero handler */ . . . }</font></tt><br>
<tt><font size="2">        restorefpexceptions (oldcontrols);</font></tt><br>
<br>
<font size="2" face="sans-serif">A simpler example to just handle overflow would be</font><br>
<br>
<tt><font size="2">        fpcontrols &nbsp;oldcontrols = enablefpexceptions (fpexception_overflow);</font></tt><br>
<tt><font size="2">        try {</font></tt><br>
<tt><font size="2">                . . . block of code . . .</font></tt><br>
<tt><font size="2">        }</font></tt><br>
<tt><font size="2">        catch (fpexception_overflow &nbsp;fpexception) &nbsp;{ /* overflow handler */ . . . }</font></tt><br>
<tt><font size="2">        restorefpexceptions (oldcontrols);</font></tt><br>
<br>
<font size="2" face="sans-serif">It's more C than C++ style, but should work in C++ too. &nbsp;It doesn't look much different from the proposal below.</font><br>
<br>
<font size="2" face="sans-serif">From an implementation point of view, the same approaches and the same performance issues apply as in my earlier email. &nbsp;Optimizations like saving and setting then later restoring exception controls can be moved out of loops to reduce overhead.</font><br>
<br>
<font size="2" face="sans-serif">This doesn't handle automatic value substitution, and like some of our other approaches is a heavy approach where </font><tt><font size="2">block of code</font></tt><font size="2" face="sans-serif">&nbsp;is a simple expression, but to me it seems fairly readable.</font><br>
<br>
<font size="2" face="sans-serif">If C ever wanted to extend exception handling to allow </font><tt><font size="2">throw</font></tt><font size="2" face="sans-serif">s, this is compatible with the C++ syntax and semantics. &nbsp;If C and/or C++ ever wanted to extend exception handling to handle traps, other hardware detected events, or operating system detected events, those could be extensions of this.</font><br>
<br>
<font size="2" face="sans-serif">- Ian McIntosh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IBM Canada Lab &nbsp; &nbsp; &nbsp; &nbsp; Compiler Back End Support and Development<br>
</font><br>
<br>
<img width="16" height="16" src="cid:1__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt="Inactive hide details for David Hough CFP ---2014-05-29 04:37:24 PM---Unlike normal C++ try blocks which can be compiled withou"><font size="2" color="#424282" face="sans-serif">David Hough CFP ---2014-05-29 04:37:24 PM---Unlike normal C++ try blocks which can be compiled without reference to whatever exceptions might be</font><br>
<br>

<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr valign="top"><td width="1%"><img width="96" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>

<ul style="padding-left: 4pt"><font size="1" color="#5F5F5F" face="sans-serif">From:</font></ul>
</td><td width="100%"><img width="1" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>
<font size="1" face="sans-serif">David Hough CFP &lt;pcfp@oakapple.net&gt;</font></td></tr>

<tr valign="top"><td width="1%"><img width="96" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>

<ul style="padding-left: 4pt"><font size="1" color="#5F5F5F" face="sans-serif">To:</font></ul>
</td><td width="100%"><img width="1" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>
<font size="1" face="sans-serif">cfp-interest@ucbtest.org, </font></td></tr>

<tr valign="top"><td width="1%"><img width="96" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>

<ul style="padding-left: 4pt"><font size="1" color="#5F5F5F" face="sans-serif">Date:</font></ul>
</td><td width="100%"><img width="1" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>
<font size="1" face="sans-serif">2014-05-29 04:37 PM</font></td></tr>

<tr valign="top"><td width="1%"><img width="96" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>

<ul style="padding-left: 4pt"><font size="1" color="#5F5F5F" face="sans-serif">Subject:</font></ul>
</td><td width="100%"><img width="1" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>
<font size="1" face="sans-serif">[Cfp-interest] more on try/catch</font></td></tr>

<tr valign="top"><td width="1%"><img width="96" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>

<ul style="padding-left: 4pt"><font size="1" color="#5F5F5F" face="sans-serif">Sent by:</font></ul>
</td><td width="100%"><img width="1" height="1" src="cid:2__=0ABBF674DFE0EC008f9e8a93df938@ca.ibm.com" border="0" alt=""><br>
<font size="1" face="sans-serif">cfp-interest-bounces@oakapple.net</font></td></tr>
</table>
<hr width="100%" size="2" align="left" noshade style="color:#8091A5; "><br>
<br>
<br>
<tt><font size="2"><br>
Unlike normal C++ try blocks which can be compiled without reference to<br>
whatever exceptions might be caught, floating-point try blocks have to<br>
be compiled knowing what exceptions might be singled out for special<br>
treatment.<br>
<br>
So maybe fp try/catch<br>
should just be separated syntactically as<br>
well as semantically from C++:<br>
<br>
<br>
fe_try {<br>
}<br>
fe_catch_sub( e, elist) {<br>
}<br>
fe_catch_exceps( e, elist) {<br>
}<br>
fe_catch_flags( f, flist) {<br>
}<br>
<br>
I've added a new wrinkle - fe_catch_sub which computes a substituted<br>
value and continues execution. &nbsp; &nbsp; How is the substituted value evaluated?<br>
It's the value of a compound statement - but it's undefined (and compilers<br>
ought to warn) if it uses any variables whose values change within the<br>
try block. &nbsp; &nbsp; &nbsp;Thus the try block to use with the substituted value<br>
is probably pretty small. &nbsp; &nbsp; The substituted value can be presubstituted<br>
if there's system support for that, but in the much more likely event that<br>
there isn't, then the compiler has to generate appropriate tests and branches.<br>
The elist usually better be a list of one subexception of invalid<br>
rather than invalid itself;<br>
otherwise the compiler has to generate tests wherever a signaling NaN might<br>
cause an invalid exception. &nbsp; &nbsp; Do we need a nonstandard pragma (meaning<br>
OK to ignore) that says compiler need not worry about signaling NaNs in a<br>
given scope? &nbsp; &nbsp; Life would have been a lot simpler if signaling NaNs had<br>
been given their own exception in 1977.<br>
 <br>
The substitute-exor feature of 754-2008 can be provided by the above plus<br>
a standard function fe_exor_result(x,y,z) which returns abs(x) with the<br>
exor signs of y and z.<br>
<br>
_______________________________________________<br>
Cfp-interest mailing list<br>
Cfp-interest@oakapple.net<br>
</font></tt><tt><font size="2"><a href="http://mailman.oakapple.net/mailman/listinfo/cfp-interest">http://mailman.oakapple.net/mailman/listinfo/cfp-interest</a></font></tt><tt><font size="2"><br>
<br>
</font></tt><br>
<br>
</body></html>