[cfe-dev] Performing a path-sensitive check only when a function return value is ignored

McDowell, Raymond C. via cfe-dev cfe-dev at lists.llvm.org
Tue Jun 21 14:25:11 PDT 2016


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<CompoundStmt>(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<Expr>(ContainingStmt)) {
      if (is<BinaryOperator>(ContainingStmt) && cast<BinaryOperator>(ContainingStmt)->isAssignmentOp())
         return true;   // return value is used in an assignment
      TopLevelExpr = cast<Expr>(ContainingStmt);
      ContainingStmt = PM.getParent(TopLevelExpr);
   }
   if (!ContainingStmt)
      return false;
   if (isa<DeclStmt>(ContainingStmt))
      return true;   // return value is used in an initialization
   if (isa<IfStmt>(ContainingStmt) && TopLevelExpr == cast<IfStmt>(ContainingStmt)->getCond())
      return true;   // return value is used in an if condition
   if (isa<SwitchStmt>(ContainingStmt) && TopLevelExpr == cast<SwitchStmt>(ContainingStmt)->getCond())
      return true;   // return value is used in a switch condition
   if (isa<WhileStmt>(ContainingStmt) && TopLevelExpr == cast<WhileStmt>(ContainingStmt)->getCond())
      return true;   // return value is used in a while loop condition
   if (isa<DoStmt>(ContainingStmt) && TopLevelExpr == cast<DoStmt>(ContainingStmt)->getCond())
      return true;   // return value is used in do loop condition
   if (isa<ReturnStmt>(ContainingStmt) && TopLevelExpr == cast<ReturnStmt>(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<CompoundStmt>(Parent))
     return;
   // Proceed with my checks.
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160621/71a82a7d/attachment.html>


More information about the cfe-dev mailing list