Pork Tools

Outparamdel

Outparamdel converts functions to return via return value instead of an outparam. It takes a list of functions as input and rewrites the definition and call sites of those functions.

<caption>Rewrites Performed</caption>
nsresult Getter(nsIFoo **aResult) {
*aResult = ...
if (!*aResult)
return NS_ERROR_FAILURE;

return NS_OK;
}

nsIFoo* Getter() {
nsIFoo *result = NULL;
// aResult below is kept for complicated cases
// typically it wont be needed and can be removed
nsIFoo **aResult = &result;
// *aResult patterns are replaced with result
result = ...
if (result)
return nsnull; // error returns are changed to nsnull
//instead NS_OK, actual result is returned
return result;
}

caller1 {
//case 1
nsresult rv;
rv = Getter(&var);
NS_ENSURE_SUCCESS(rv,rv);
//case 2: naked call
Getter(&var);
//case 3: nsresult decl
nsresult r
v2 = Getter(&var);
NS_ENSURE_SUCCESS(rv2,rv2);

}

caller1 {
// case 1
// figure out that rv was only used for the rewritten
// outparam call + NS_ENSURE_SUCCESS. Then nuke the declaration
// nsresult rv;
// move outparam to lhs
var = Getter();
// detect NS_ENSURE_SUCCESS immediately following
// and change it to an equivalent NS_ENSURE_TRUE
NS_ENSURE_TRUE(var, NS_ERROR_FAILURE);
// case 2
var = Getter();
// case 3, eliminate rv2 decl given that it's not used elsewhere
var = Getter();
NS_ENSURE_TRUE(var, NS_ERROR_FAILURE)
}

Outparamdel also support rewriting getters such that they return already_AddRefed<nsIFoo>. In this case all of the callsites are modified to:
a) getter_AddRefs case: getter(getter_AddRefs(foo)) -> foo = getter()
b) all other cases: getter(&foo) -> foo = getter().get()