[cfe-commits] r137012 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h lib/StaticAnalyzer/Core/BugReporter.cpp lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Ted Kremenek kremenek at apple.com
Fri Aug 5 23:54:45 PDT 2011


Author: kremenek
Date: Sat Aug  6 01:54:45 2011
New Revision: 137012

URL: http://llvm.org/viewvc/llvm-project?rev=137012&view=rev
Log:
[analyzer] Start sketching out a new BugReporterVisitor that inspects branches and other expressions to generate interesting path events in diagnostics.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Sat Aug  6 01:54:45 2011
@@ -490,13 +490,15 @@
 const Stmt *GetCalleeExpr(const ExplodedNode *N);
 const Stmt *GetRetValExpr(const ExplodedNode *N);
 
+void registerConditionVisitor(BugReporterContext &BRC);
+
 void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt,
                                    const ExplodedNode* N);
 
 void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
                            const ExplodedNode *N);
 
-void registerNilReceiverVisitor(BugReporterContext &BRC);
+void registerNilReceiverVisitor(BugReporterContext &BRC);  
 
 void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
                                const ExplodedNode *N);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Sat Aug  6 01:54:45 2011
@@ -1619,6 +1619,7 @@
   // Register node visitors.
   R->registerInitialVisitors(PDB, N);
   bugreporter::registerNilReceiverVisitor(PDB);
+  bugreporter::registerConditionVisitor(PDB);
 
   switch (PDB.getGenerationScheme()) {
     case PathDiagnosticClient::Extensive:

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sat Aug  6 01:54:45 2011
@@ -468,3 +468,155 @@
       WorkList.push_back(*I);
   }
 }
+
+//===----------------------------------------------------------------------===//
+// Visitor that tries to report interesting diagnostics from conditions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ConditionVisitor : public BugReporterVisitor {
+public:
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    static int x = 0;
+    ID.AddPointer(&x);
+  }
+
+  virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                         const ExplodedNode *Prev,
+                                         BugReporterContext &BRC);
+  
+  PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
+                                       const GRState *CurrentState,
+                                       const GRState *PrevState,
+                                       const CFGBlock *srcBlk,
+                                       const CFGBlock *dstBlk,
+                                       BugReporterContext &BRC);
+  
+  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+                                     bool tookTrue,
+                                     BugReporterContext &BRC);
+
+  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+                                     const DeclRefExpr *DR,
+                                     const bool tookTrue,
+                                     BugReporterContext &BRC);
+
+};
+}
+
+PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
+                                                 const ExplodedNode *Prev,
+                                                 BugReporterContext &BRC) {
+  
+  const ProgramPoint &progPoint = N->getLocation();
+  
+  // 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 GRState *CurrentState = N->getState();
+      const GRState *PrevState = Prev->getState();
+      if (CurrentState != PrevState)
+        return VisitTerminator(term, CurrentState, PrevState,
+                               srcBlk, BE->getDst(),
+                               BRC);
+    }
+    
+    return 0;
+  }
+    
+  return 0;
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTerminator(const Stmt *Term,
+                                  const GRState *CurrentState,
+                                  const GRState *PrevState,
+                                  const CFGBlock *srcBlk,
+                                  const CFGBlock *dstBlk,
+                                  BugReporterContext &BRC) {
+
+  assert(CurrentState != PrevState);
+  const Expr *Cond = 0;
+  
+  switch (Term->getStmtClass()) {
+  default:
+    return 0;
+  case Stmt::IfStmtClass:
+    Cond = cast<IfStmt>(Term)->getCond();
+    break;
+  case Stmt::ConditionalOperatorClass:
+    Cond = cast<ConditionalOperator>(Term)->getCond();
+    break;
+  }      
+
+  assert(Cond);
+  assert(srcBlk->succ_size() == 2);
+  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
+  return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
+                       tookTrue, BRC);
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTrueTest(const Expr *Cond,
+                                bool tookTrue,
+                                BugReporterContext &BRC) {
+  
+  const Expr *Ex = Cond;
+  
+  while (true)
+    switch (Ex->getStmtClass()) {
+      default:
+        return 0;
+      case Stmt::DeclRefExprClass:
+        return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC);
+      case Stmt::UnaryOperatorClass: {
+        const UnaryOperator *UO = cast<UnaryOperator>(Ex);
+        if (UO->getOpcode() == UO_LNot) {
+          tookTrue = !tookTrue;
+          Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
+          continue;
+        }
+        return 0;
+      }
+    }
+}
+  
+PathDiagnosticPiece *
+ConditionVisitor::VisitTrueTest(const Expr *Cond,
+                                const DeclRefExpr *DR,
+                                const bool tookTrue,
+                                BugReporterContext &BRC) {
+
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return 0;
+  
+  llvm::SmallString<256> Buf;
+  llvm::raw_svector_ostream Out(Buf);
+    
+  Out << "Assuming '";
+  VD->getDeclName().printName(Out);
+  Out << "' is ";
+    
+  QualType VDTy = VD->getType();
+  
+  if (VDTy->isPointerType())
+    Out << (tookTrue ? "non-null" : "null");
+  else if (VDTy->isObjCObjectPointerType())
+    Out << (tookTrue ? "non-nil" : "nil");
+  else if (VDTy->isScalarType())
+    Out << (tookTrue ? "not equal to 0" : "0");
+  else
+    return 0;
+  
+  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
+  return new PathDiagnosticEventPiece(Loc, Out.str());
+}
+
+void bugreporter::registerConditionVisitor(BugReporterContext &BRC) {
+  BRC.addVisitor(new ConditionVisitor());
+}
+





More information about the cfe-commits mailing list