Exceptions: Difference between revisions

433 bytes added ,  21 December 2007
copy edit
(copy edit)
Line 1: Line 1:
This is a discussion document for ideas about how to use static analysis to help refactor Mozilla to use C++ exceptions instead of nsresults. In particular, this is about how to modify the call sites of methods so that the code uses exception handling and is exception safe.
This is a discussion document for ideas about how to use static analysis to help refactor Mozilla to use C++ exceptions instead of nsresults. In particular, this is about how to modify the call sites of methods so that the code uses exception handling and is exception safe.
The main goal of the rewriting is to make the code use exceptions instead of nsresults without modifying the behavior of the code. This breaks down into:
* Ensuring that methods that don't crash now don't crash by throwing an unhandled exception.
* Ensuring that the error handling code at the call sites runs under the same conditions and does the same thing. (Effectively, we are assuming that the current error handling is correct, and that replicating that behavior with exceptions will result in exception-safe code.)


== Call sites that ignore return values ==
== Call sites that ignore return values ==


Once nothrows are identified and taken care of, all the remaining call sites need to be made exception safe. Static analysis has no way of knowing the safety requirements, so we can't create a static analysis that just makes everything exception safe. But it seems reasonable to assume that existing call sites that test the nsresult do the right thing in the presence of errors, and then we can make a rewriting tool that will ensure the same thing is done with exceptions.
One case where we don't necessarily want to keep current behavior is at call sites that ignore their return values:
 
  callSomeMethodThatCanFail();


But first we need to take care of existing call sites that just ignore errors, because (a) that looks like a bug, and (b) if they are supposed to ignore errors, they'll need to be rewritten to ignore exceptions.
This is probably a bug, so we want a tool that can find and flag all of these results. After the bugs are fixed, any remaining call sites that really should ignore failures can be rewritten automatically to ignore exceptions.


=== Analysis to detect ignored return values ===
=== Analysis to detect ignored return values ===
Line 11: Line 19:
Roughly, the analysis should flag all call sites where:
Roughly, the analysis should flag all call sites where:


* the method is not nothrow
* the method is not guaranteed nothrow (i.e., the method can fail)


* there is no branch on NS_FAILED(rv) or NS_SUCCEEDED(rv)
* there is no branch on NS_FAILED(rv) or NS_SUCCEEDED(rv)
Line 43: Line 51:
     callMethod();
     callMethod();
   } except (nserror e) {}
   } except (nserror e) {}
The latter pattern can be expressed with a macro. (dmandelin: But macros are bad, right? I'd vote for no macros here.)


== Making call sites exception safe ==
== Making call sites exception safe ==


Once the nothrows are identified (and optionally, call sites that ignore errors are rewritten), we are left with the harder job of rewriting all other call sites to be exception safe.
Most call sites do check for errors and respond somehow. This section is about how to rewrite those call sites.


We'll start with the assumption that call sites adhere to a simple pattern that's relatively easy to rewrite, namely:
We'll start with the assumption that call sites adhere to a simple pattern that's relatively easy to rewrite, namely:
Line 72: Line 82:
         maybe return;            // if original returns 0
         maybe return;            // if original returns 0
       }
       }
The '''thrower''' tool handles some instances of this pattern. (dmandelin: I don't know exactly what thrower can do at this point.)


But there are at least two big practical problems with this rewrite.
But there are at least two big practical problems with this rewrite.
313

edits