[cfe-commits] r137705 - /cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Ted Kremenek kremenek at apple.com
Mon Aug 15 18:53:42 PDT 2011


Author: kremenek
Date: Mon Aug 15 20:53:41 2011
New Revision: 137705

URL: http://llvm.org/viewvc/llvm-project?rev=137705&view=rev
Log:
[analyzer] Enhance ConditionVisitor to understand eagerly evaluated (simple) binary conditions, and teach it to only focus on constraint changes.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=137705&r1=137704&r2=137705&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Mon Aug 15 20:53:41 2011
@@ -18,6 +18,7 @@
 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 
 using namespace clang;
 using namespace ento;
@@ -500,7 +501,15 @@
                                      const DeclRefExpr *DR,
                                      const bool tookTrue,
                                      BugReporterContext &BRC);
-
+  
+  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+                                     const BinaryOperator *BExpr,
+                                     const bool tookTrue,
+                                     BugReporterContext &BRC);
+  
+  void patternMatch(const Expr *Ex,
+                    llvm::raw_ostream &Out,
+                    BugReporterContext &BRC);
 };
 }
 
@@ -509,21 +518,40 @@
                                                  BugReporterContext &BRC) {
   
   const ProgramPoint &progPoint = N->getLocation();
+
+  const ProgramState *CurrentState = N->getState();
+  const ProgramState *PrevState = Prev->getState();
+  
+  // Compare the GDMs of the state, because that is where constraints
+  // are managed.  Note that ensure that we only look at nodes that
+  // were generated by the analyzer engine proper, not checkers.
+  if (CurrentState->getGDM().getRoot() ==
+      PrevState->getGDM().getRoot())
+    return 0;
   
   // If an assumption was made on a branch, it should be caught
   // here by looking at the state transition.
   if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
-    const CFGBlock *srcBlk = BE->getSrc();
-    
-    if (const Stmt *term = srcBlk->getTerminator()) {
-      const ProgramState *CurrentState = N->getState();
-      const ProgramState *PrevState = Prev->getState();
-      if (CurrentState != PrevState)
-        return VisitTerminator(term, CurrentState, PrevState,
-                               srcBlk, BE->getDst(),
-                               BRC);
-    }
-    
+    const CFGBlock *srcBlk = BE->getSrc();    
+    if (const Stmt *term = srcBlk->getTerminator())
+      return VisitTerminator(term, CurrentState, PrevState,
+                             srcBlk, BE->getDst(), BRC);
+    return 0;
+  }
+  
+  if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
+    // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
+    // violation.
+    const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =      
+      cast<GRBugReporter>(BRC.getBugReporter()).
+        getEngine().getEagerlyAssumeTags();
+
+    const ProgramPointTag *tag = PS->getTag();
+    if (tag == tags.first)
+      return VisitTrueTest(cast<Expr>(PS->getStmt()), true, BRC);
+    if (tag == tags.second)
+      return VisitTrueTest(cast<Expr>(PS->getStmt()), false, BRC);
+                           
     return 0;
   }
     
@@ -538,7 +566,6 @@
                                   const CFGBlock *dstBlk,
                                   BugReporterContext &BRC) {
 
-  assert(CurrentState != PrevState);
   const Expr *Cond = 0;
   
   switch (Term->getStmtClass()) {
@@ -566,10 +593,13 @@
   
   const Expr *Ex = Cond;
   
-  while (true)
+  while (true) {
+    Ex = Ex->IgnoreParens();
     switch (Ex->getStmtClass()) {
       default:
         return 0;
+      case Stmt::BinaryOperatorClass:
+        return VisitTrueTest(Cond, cast<BinaryOperator>(Cond), tookTrue, BRC);
       case Stmt::DeclRefExprClass:
         return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC);
       case Stmt::UnaryOperatorClass: {
@@ -582,6 +612,91 @@
         return 0;
       }
     }
+  }
+}
+
+void ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
+                                    BugReporterContext &BRC) {
+  const Expr *OriginalExpr = Ex;
+  Ex = Ex->IgnoreParenCasts();
+
+  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      Out << VD->getDeclName().getAsString();
+    return;
+  }
+  
+  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
+    QualType OriginalTy = OriginalExpr->getType();
+    if (OriginalTy->isPointerType()) {
+      if (IL->getValue() == 0) {
+        Out << "null";
+        return;
+      }
+    }
+    else if (OriginalTy->isObjCObjectPointerType()) {
+      if (IL->getValue() == 0) {
+        Out << "nil";
+        return;
+      }
+    }
+    
+    Out << IL->getValue();
+    return;
+  }
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTrueTest(const Expr *Cond,
+                                const BinaryOperator *BExpr,
+                                const bool tookTrue,
+                                BugReporterContext &BRC) {
+  
+  llvm::SmallString<128> LhsString, RhsString;
+  {
+    llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);  
+    patternMatch(BExpr->getLHS(), OutLHS, BRC);
+    patternMatch(BExpr->getRHS(), OutRHS, BRC);
+  }
+  
+  if (LhsString.empty() || RhsString.empty())
+    return 0;
+
+  llvm::SmallString<256> buf;
+  llvm::raw_svector_ostream Out(buf);
+  Out << "Assuming " << LhsString << " is ";
+
+  // Do we need to invert the opcode?
+  BinaryOperator::Opcode Op = BExpr->getOpcode();
+  
+  if (!tookTrue)
+    switch (Op) {
+      case BO_EQ: Op = BO_NE; break;
+      case BO_NE: Op = BO_EQ; break;
+      case BO_LT: Op = BO_GE; break;
+      case BO_GT: Op = BO_LE; break;
+      case BO_LE: Op = BO_GT; break;
+      case BO_GE: Op = BO_GE; break;
+      default:
+        return 0;
+    }
+  
+  switch (BExpr->getOpcode()) {
+    case BO_EQ:
+      Out << "equal to ";
+      break;
+    case BO_NE:
+      Out << "not equal to ";
+      break;
+    default:
+      Out << BinaryOperator::getOpcodeStr(Op) << ' ';
+      break;
+  }
+  
+  Out << RhsString;
+
+  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
+  return new PathDiagnosticEventPiece(Loc, Out.str());
 }
   
 PathDiagnosticPiece *





More information about the cfe-commits mailing list