r181282 - [analyzer; alternate arrows] provide a diagnostic for entering a loop for the first time.

Ted Kremenek kremenek at apple.com
Mon May 6 18:18:10 PDT 2013


Author: kremenek
Date: Mon May  6 20:18:10 2013
New Revision: 181282

URL: http://llvm.org/viewvc/llvm-project?rev=181282&view=rev
Log:
[analyzer; alternate arrows] provide a diagnostic for entering a loop for the first time.

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

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=181282&r1=181281&r2=181282&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Mon May  6 20:18:10 2013
@@ -1261,25 +1261,34 @@ static void reversePropagateInterestingS
 // Functions for determining if a loop was executed 0 times.
 //===----------------------------------------------------------------------===//
 
-/// Return true if the terminator is a loop and the destination is the
-/// false branch.
-static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
+static bool isLoop(const Stmt *Term) {
   switch (Term->getStmtClass()) {
     case Stmt::ForStmtClass:
     case Stmt::WhileStmtClass:
     case Stmt::ObjCForCollectionStmtClass:
-      break;
+      return true;
     default:
       // Note that we intentionally do not include do..while here.
       return false;
   }
+}
 
-  // Did we take the false branch?
+static bool isJumpToFalseBranch(const BlockEdge *BE) {
   const CFGBlock *Src = BE->getSrc();
   assert(Src->succ_size() == 2);
   return (*(Src->succ_begin()+1) == BE->getDst());
 }
 
+/// Return true if the terminator is a loop and the destination is the
+/// false branch.
+static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
+  if (!isLoop(Term))
+    return false;
+
+  // Did we take the false branch?
+  return isJumpToFalseBranch(BE);
+}
+
 static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
   while (SubS) {
     if (SubS == S)
@@ -1557,6 +1566,45 @@ static void addEdgeToPath(PathPieces &pa
   PrevLoc = NewLoc;
 }
 
+enum EventCategorization { EC_None, EC_EnterLoop, EC_LoopingBack };
+
+typedef llvm::DenseMap<const PathDiagnosticEventPiece *,
+                       enum EventCategorization>
+        EventCategoryMap;
+
+
+static void pruneLoopEvents(PathPieces &path, EventCategoryMap &ECM) {
+  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
+    if (PathDiagnosticCallPiece *call = dyn_cast<PathDiagnosticCallPiece>(*I)) {
+      pruneLoopEvents(call->path, ECM);
+      continue;
+    }
+
+    PathDiagnosticEventPiece *I_event = dyn_cast<PathDiagnosticEventPiece>(*I);
+    if (!I_event || ECM[I_event] != EC_LoopingBack)
+      continue;
+
+    PathPieces::iterator Next = I; ++Next;
+    PathDiagnosticEventPiece *Next_event = 0;
+    for ( ; Next != E ; ++Next) {
+      Next_event = dyn_cast<PathDiagnosticEventPiece>(*Next);
+      if (Next_event)
+        break;
+    }
+
+    if (Next_event) {
+      EventCategorization E = ECM[Next_event];
+      if (E == EC_EnterLoop) {
+        PathDiagnosticLocation L = I_event->getLocation();
+        PathDiagnosticLocation L_next = Next_event->getLocation();
+        if (L == L_next) {
+          path.erase(Next);
+        }
+      }
+    }
+  }
+}
+
 static bool
 GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
                                          PathDiagnosticBuilder &PDB,
@@ -1573,6 +1621,8 @@ GenerateAlternateExtensivePathDiagnostic
   llvm::DenseMap<const StackFrameContext *, PathDiagnosticLocation>
     PrevLocMap;
 
+  EventCategoryMap EventCategory;
+
   const ExplodedNode *NextNode = N->getFirstPred();
   while (NextNode) {
     N = NextNode;
@@ -1687,33 +1737,48 @@ GenerateAlternateExtensivePathDiagnostic
 
           addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC);
           PD.getActivePath().push_front(p);
+          EventCategory[p] = EC_LoopingBack;
 
           if (CS) {
             addEdgeToPath(PD.getActivePath(), PrevLoc,
                           PathDiagnosticLocation::createEndBrace(CS, SM), LC);
           }
         }
-        
+
         const CFGBlock *BSrc = BE->getSrc();
         ParentMap &PM = PDB.getParentMap();
 
         if (const Stmt *Term = BSrc->getTerminator()) {
           // Are we jumping past the loop body without ever executing the
           // loop (because the condition was false)?
-          if (isLoopJumpPastBody(Term, &*BE) &&
-              !isInLoopBody(PM,
-                            getStmtBeforeCond(PM,
-                                              BSrc->getTerminatorCondition(),
-                                              N),
-                            Term))
-          {
-            PathDiagnosticLocation L(Term, SM, PDB.LC);
-            PathDiagnosticEventPiece *PE =
-              new PathDiagnosticEventPiece(L, "Loop body executed 0 times");
-            PE->setPrunable(true);
-            addEdgeToPath(PD.getActivePath(), PrevLoc,
-                          PE->getLocation(), LC);
-            PD.getActivePath().push_front(PE);
+          if (isLoop(Term)) {
+            const Stmt *TermCond = BSrc->getTerminatorCondition();
+            bool IsInLoopBody =
+              isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
+
+            const char *str = 0;
+            enum EventCategorization EC = EC_None;
+
+            if (isJumpToFalseBranch(&*BE)) {
+              if (!IsInLoopBody) {
+                str = "Loop body executed 0 times";
+              }
+            }
+            else {
+              str = "Entering loop body";
+              EC = EC_EnterLoop;
+            }
+
+            if (str) {
+              PathDiagnosticLocation L(Term, SM, PDB.LC);
+              PathDiagnosticEventPiece *PE =
+                new PathDiagnosticEventPiece(L, str);
+              EventCategory[PE] = EC;
+              PE->setPrunable(true);
+              addEdgeToPath(PD.getActivePath(), PrevLoc,
+                            PE->getLocation(), LC);
+              PD.getActivePath().push_front(PE);
+            }
           }
         }
         break;
@@ -1735,6 +1800,11 @@ GenerateAlternateExtensivePathDiagnostic
     }
   }
 
+  if (report->isValid()) {
+    // Prune redundant loop diagnostics.
+    pruneLoopEvents(PD.getMutablePieces(), EventCategory);
+  }
+
   return report->isValid();
 }
 





More information about the cfe-commits mailing list