Performing a path-sensitive check only when a function return value is ignored

I generally followed Artem’s suggestions (for my approach) and things worked out okay. Specifically:

void MyChecker::checkPreCall(const CallEvent &Call, CheckerContext &ChCtx) const {

const Stmt *Parent = ChCtx.getStackFrame()->getParentMap().getParent(Call.getOriginExpr());

if (!Parent || !isa(Parent))

return;

// Proceed with my checks.

}

Then I generalized this a bit, but still in a syntactic way (not in the path-sensitive way Artem suggested). The idea is to follow the parent chain to get the first non-Expr statement containing the call, and then check if that statement makes use of the expression value (which is built from the call’s return value).

bool isReturnValueUsed(const CallEvent &Call, CheckerContext &ChCtx) {

const ParentMap &PM = ChCtx.getStackFrame()->getParentMap();

const Expr *TopLevelExpr = Call.getOriginExpr();

const Stmt *Containing Stmt = PM.getParent(TopLevelExpr);

while (ContainingStmt && isa(ContainingStmt)) {

if (is(ContainingStmt) && cast(ContainingStmt)->isAssignmentOp())

return true; // return value is used in an assignment

TopLevelExpr = cast(ContainingStmt);

ContainingStmt = PM.getParent(TopLevelExpr);

}

if (!ContainingStmt)

return false;

if (isa(ContainingStmt))

return true; // return value is used in an initialization

if (isa(ContainingStmt) && TopLevelExpr == cast(ContainingStmt)->getCond())

return true; // return value is used in an if condition

if (isa(ContainingStmt) && TopLevelExpr == cast(ContainingStmt)->getCond())

return true; // return value is used in a switch condition

if (isa(ContainingStmt) && TopLevelExpr == cast(ContainingStmt)->getCond())

return true; // return value is used in a while loop condition

if (isa(ContainingStmt) && TopLevelExpr == cast(ContainingStmt)->getCond())

return true; // return value is used in do loop condition

if (isa(ContainingStmt) && TopLevelExpr == cast(ContainingStmt)->getRetValue())

return true; // return value is used to construct a higher-level return value

return false;

}

void MyChecker::checkPreCall(const CallEvent &Call, CheckerContext &ChCtx) const {

const Stmt *Parent = ChCtx.getStackFrame()->getParentMap().getParent(Call.getOriginExpr());

if (!Parent || !isa(Parent))

return;

// Proceed with my checks.

}