[Cfp-interest] FE_EXCEPTIONAL simplifies alternate exception handling a lot

David Hough CFP pcfp at oakapple.net
Tue May 13 16:35:53 PDT 2014


Here's the current:


----- ALTERNATE EXCEPTION HANDLING -----

standard pragmas do not afford all the flexibility needed to specify
alternate exception handling, so standard macros 
FP_EXCEPTIONAL_DETERMINISTIC and FP_EXCEPTIONAL_NONDETERMINISTIC are defined
as well as a standard pragma, FENV_EXCEPT .



 exceptions enumerated in ANSI-C 7.6:
	FE_INEXACT
	FE_UNDERFLOW
	FE_OVERFLOW 
	FE_DIVBYZERO
	FE_INVALID
	FE_ALL_EXCEPT		shorthand for all five

Add the following subexceptions of invalid and divbyzero:
 subexception:
	FE_INVALID_SNAN		7.2a
	FE_INVALID_MUL		7.2b
	FE_INVALID_FMA		7.2c
	FE_INVALID_ADD		7.2d
	FE_INVALID_DIV		7.2e
	FE_INVALID_REM		7.2f
	FE_INVALID_SQRT		7.2g
	FE_INVALID_QUANTIZE	7.2h
	FE_INVALID_INT		7.2i
	FE_INVALID_UNORDERED	7.2j
	FE_INVALID_LOGB		7.2k
	FE_INVALID_OTHER	especially for 754 chapter 9 functions
	FE_DIVBYZERO_DIVISOR	7.3 divisor zero
	FE_DIVBYZERO_LOGB	7.3 logb(0)
	FE_DIVBYZERO_OTHER	especially for 754 chapter 9 functions
	

#pragma STDC FENV_EXCEPT exception-list action 
 exception list is a list of exceptions and subexceptions
 separated by commas

 This pragma's actions don't change control flow:
	DEFAULT				754 default
 	NO_FLAG				default result, but no flag raised
	MAY_FLAG			implementation may raise flag or not
	ABRUPT 				underflow only, mandatory
	RECORD				record the exception in a "debugger"
					and continue; same as default if
					no debugger active

What about functions invoked within compound statements controlled by
an alternate exception handling pragma?    To follow the lead of
FENV_ROUND, a list of functions corresponding to 754 operations
specifies those affected by rounding and alternate exception handling pragmas.
Inlining does not affect whether an operation is affected.

Exceptional Macros

 FE_EXCEPTIONAL_DETERMINISTIC( 
	expression or compound statement, exception1, exception2, ...)
 FE_EXCEPTIONAL_NONDETERMINISTIC( 
	expression or compound statement, exception1, exception2, ...)

are special macros, almost varargs functions.   
They evaluates the expression or compound statement,
and return a non-zero int if any of the listed exceptions arose in the
course of the computation, and a zero int otherwise.
The non-zero int might be an implementation-dependent encoding of the listed
exceptions that arose, taking into account sub-exceptions.
Flags and traps for the listed exceptions
are the same after execution as before.

FE_EXCEPTIONAL_DETERMINISTIC
finishes the expression or compound statement and then
sets the result value and continues execution.

FE_EXCEPTIONAL_NONDETERMINISTIC 
is allowed to quit work on the expression or compound 
statement as soon as it determines that a listed exception has occurred.
Intermediate results might not be in a consistent state.   Listed exceptions
that might have been encountered later might not be reported.

Using the notation FE_EXCEPTIONAL to refer to either,
they are intended to be used like any other conditional expression,

 if FE_EXCEPTIONAL(expr, exception) {
  exceptional case code
 } else {
  nonexceptional case code
 }
 
 FE_EXCEPTIONAL(expr, exception) ? exceptional case code : nonexceptional case code
 
 switch FE_EXCEPTIONAL(expr, exception) {
 case ...
 }


Since common usages would include

 if FE_EXCEPTIONAL( expr, exception) {
  exceptional case code
 } else {
  a = expr ;
 }
 
 FE_EXCEPTIONAL(expr, exception) ? exceptional case code : a = expr;

optimizing compilers would be expected to handle these cases
without unnecessary recomputation. 


FE_EXCEPTIONAL is intended to impart the flexibility of C++ try/catch without
damaging C syntax or supporting the full generality of C++ try/catch.
FE_EXCEPTIONAL is not a function; its arguments can include a compound
statement and the expression or compound statement is not to be 
evaluated outside the macro.
It seems much better to avoid scope issues by having
expressions and labels exist within normal
C syntax rather than somehow grafted onto pragmas. 

We could note than a corresponding construct

 FE_SIGNALING( expression or compound statement, signal1, signal2, ...)

could have commensurate benefits for non-numeric programs: hiding all
the complication of setting up, using, and tearing down local signal handlers
by making the compiler and operating system figure it out.
But that's not our case. 

(By considering signals I came up with the name FE_SIGNALING and then
the name FE_EXCEPTIONAL, rather than FE_TRYCATCH,
but maybe somebody else has a better idea.)



More information about the Cfp-interest mailing list