313
edits
(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 == | ||
One case where we don't necessarily want to keep current behavior is at call sites that ignore their return values: | |||
callSomeMethodThatCanFail(); | |||
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 == | ||
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. |
edits