<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>While building a cute new algorithm, would it be a good idea to move the loop events into visitors instead of mixing them with the main traversal and edge logic?</div><div><br></div><div>Jordan</div><div><br></div><br><div><div>On May 3, 2013, at 11:25 , Ted Kremenek <<a href="mailto:kremenek@apple.com">kremenek@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: kremenek<br>Date: Fri May  3 13:25:33 2013<br>New Revision: 181040<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=181040&view=rev">http://llvm.org/viewvc/llvm-project?rev=181040&view=rev</a><br>Log:<br>[analyzer] Start hacking up alternate control-flow edge generation.  WIP.  Not guaranteed to do anything useful yet.<br><br>Modified:<br>   cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h<br>   cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp<br><br>Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=181040&r1=181039&r2=181040&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=181040&r1=181039&r2=181040&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)<br>+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Fri May  3 13:25:33 2013<br>@@ -94,7 +94,7 @@ public:<br><br>  void HandlePathDiagnostic(PathDiagnostic *D);<br><br>-  enum PathGenerationScheme { None, Minimal, Extensive };<br>+  enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };<br>  virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }<br>  virtual bool supportsLogicalOpControlFlow() const { return false; }<br>  virtual bool supportsAllBlockEdges() const { return false; }<br><br>Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=181040&r1=181039&r2=181040&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=181040&r1=181039&r2=181040&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)<br>+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Fri May  3 13:25:33 2013<br>@@ -1530,6 +1530,212 @@ static bool GenerateExtensivePathDiagnos<br>  return PDB.getBugReport()->isValid();<br>}<br><br>+/// \brief Adds a sanitized control-flow diagnostic edge to a path.<br>+static void addEdgeToPath(PathPieces &path,<br>+                          PathDiagnosticLocation &PrevLoc,<br>+                          PathDiagnosticLocation NewLoc,<br>+                          const LocationContext *LC) {<br>+  if (NewLoc.asLocation().isMacroID())<br>+    return;<br>+<br>+  if (!PrevLoc.isValid()) {<br>+    PrevLoc = NewLoc;<br>+    return;<br>+  }<br>+<br>+  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, LC);<br>+  if (PrevLocClean.asLocation().isInvalid()) {<br>+    PrevLoc = NewLoc;<br>+    return;<br>+  }<br>+<br>+  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, LC);<br>+  if (NewLocClean.asLocation() == PrevLocClean.asLocation())<br>+    return;<br>+<br>+  // FIXME: ignore intra-macro edges for now.<br>+  if (NewLocClean.asLocation().getExpansionLoc() ==<br>+      PrevLocClean.asLocation().getExpansionLoc())<br>+    return;<br>+<br>+  path.push_front(new PathDiagnosticControlFlowPiece(NewLocClean,<br>+                                                     PrevLocClean));<br>+  PrevLoc = NewLoc;<br>+}<br>+<br>+static bool<br>+GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,<br>+                                         PathDiagnosticBuilder &PDB,<br>+                                         const ExplodedNode *N,<br>+                                         LocationContextMap &LCM,<br>+                                      ArrayRef<BugReporterVisitor *> visitors) {<br>+<br>+  BugReport *report = PDB.getBugReport();<br>+  const SourceManager& SM = PDB.getSourceManager();<br>+  StackDiagVector CallStack;<br>+  InterestingExprs IE;<br>+<br>+  // Record the last location for a given visited stack frame.<br>+  llvm::DenseMap<const StackFrameContext *, PathDiagnosticLocation><br>+    PrevLocMap;<br>+<br>+  const ExplodedNode *NextNode = N->getFirstPred();<br>+  while (NextNode) {<br>+    N = NextNode;<br>+    NextNode = N->getFirstPred();<br>+    ProgramPoint P = N->getLocation();<br>+    const LocationContext *LC = N->getLocationContext();<br>+    PathDiagnosticLocation &PrevLoc = PrevLocMap[LC->getCurrentStackFrame()];<br>+<br>+    do {<br>+      if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {<br>+        // For expressions, make sure we propagate the<br>+        // interesting symbols correctly.<br>+        if (const Expr *Ex = PS->getStmtAs<Expr>())<br>+          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,<br>+                                              N->getState().getPtr(), Ex,<br>+                                              N->getLocationContext());<br>+        break;<br>+      }<br>+<br>+      // Have we encountered an exit from a function call?<br>+      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {<br>+        const Stmt *S = CE->getCalleeContext()->getCallSite();<br>+        // Propagate the interesting symbols accordingly.<br>+        if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {<br>+          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,<br>+                                              N->getState().getPtr(), Ex,<br>+                                              N->getLocationContext());<br>+        }<br>+<br>+        // We are descending into a call (backwards).  Construct<br>+        // a new call piece to contain the path pieces for that call.<br>+        PathDiagnosticCallPiece *C =<br>+          PathDiagnosticCallPiece::construct(N, *CE, SM);<br>+<br>+        // Record the location context for this call piece.<br>+        LCM[C] = CE->getCalleeContext();<br>+<br>+        // Add the edge to the return site.<br>+        addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, LC);<br>+<br>+        // Make the contents of the call the active path for now.<br>+        PD.pushActivePath(&C->path);<br>+        CallStack.push_back(StackDiagPair(C, N));<br>+        break;<br>+      }<br>+<br>+      // Have we encountered an entrance to a call?  It may be<br>+      // the case that we have not encountered a matching<br>+      // call exit before this point.  This means that the path<br>+      // terminated within the call itself.<br>+      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {<br>+        // Add an edge to the start of the function.<br>+        const Decl *D = CE->getCalleeContext()->getDecl();<br>+        addEdgeToPath(PD.getActivePath(), PrevLoc,<br>+                      PathDiagnosticLocation::createBegin(D, SM), LC);<br>+<br>+        // Did we visit an entire call?<br>+        bool VisitedEntireCall = PD.isWithinCall();<br>+        PD.popActivePath();<br>+<br>+        PathDiagnosticCallPiece *C;<br>+        if (VisitedEntireCall) {<br>+          C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());<br>+        } else {<br>+          const Decl *Caller = CE->getLocationContext()->getDecl();<br>+          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);<br>+          LCM[C] = CE->getCalleeContext();<br>+        }<br>+        C->setCallee(*CE, SM);<br>+<br>+        if (!CallStack.empty()) {<br>+          assert(CallStack.back().first == C);<br>+          CallStack.pop_back();<br>+        }<br>+        break;<br>+      }<br>+<br>+      // Block edges.<br>+      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {<br>+        // Does this represent entering a call?  If so, look at propagating<br>+        // interesting symbols across call boundaries.<br>+        if (NextNode) {<br>+          const LocationContext *CallerCtx = NextNode->getLocationContext();<br>+          const LocationContext *CalleeCtx = PDB.LC;<br>+          if (CallerCtx != CalleeCtx) {<br>+            reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,<br>+                                               N->getState().getPtr(),<br>+                                               CalleeCtx, CallerCtx);<br>+          }<br>+        }<br>+<br>+        // Are we jumping to the head of a loop?  Add a special diagnostic.<br>+        if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {<br>+          PathDiagnosticLocation L(Loop, SM, PDB.LC);<br>+          const CompoundStmt *CS = NULL;<br>+<br>+          if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))<br>+            CS = dyn_cast<CompoundStmt>(FS->getBody());<br>+          else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))<br>+            CS = dyn_cast<CompoundStmt>(WS->getBody());<br>+<br>+          PathDiagnosticEventPiece *p =<br>+            new PathDiagnosticEventPiece(L, "Looping back to the head "<br>+                                            "of the loop");<br>+          p->setPrunable(true);<br>+<br>+          addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC);<br>+<br>+          if (CS) {<br>+            addEdgeToPath(PD.getActivePath(), PrevLoc,<br>+                          PathDiagnosticLocation::createEndBrace(CS, SM), LC);<br>+          }<br>+        }<br>+        <br>+        const CFGBlock *BSrc = BE->getSrc();<br>+        ParentMap &PM = PDB.getParentMap();<br>+<br>+        if (const Stmt *Term = BSrc->getTerminator()) {<br>+          // Are we jumping past the loop body without ever executing the<br>+          // loop (because the condition was false)?<br>+          if (isLoopJumpPastBody(Term, &*BE) &&<br>+              !isInLoopBody(PM,<br>+                            getStmtBeforeCond(PM,<br>+                                              BSrc->getTerminatorCondition(),<br>+                                              N),<br>+                            Term))<br>+          {<br>+              PathDiagnosticLocation L(Term, SM, PDB.LC);<br>+              PathDiagnosticEventPiece *PE =<br>+              new PathDiagnosticEventPiece(L, "Loop body executed 0 times");<br>+              PE->setPrunable(true);<br>+              addEdgeToPath(PD.getActivePath(), PrevLoc,<br>+                            PE->getLocation(), LC);<br>+          }<br>+        }<br>+        break;<br>+      }<br>+    } while (0);<br>+<br>+    if (!NextNode)<br>+      continue;<br>+<br>+    // Add pieces from custom visitors.<br>+    BugReport *R = PDB.getBugReport();<br>+    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),<br>+         E = visitors.end();<br>+         I != E; ++I) {<br>+      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {<br>+        addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC);<br>+        updateStackPiecesWithMessage(p, CallStack);<br>+      }<br>+    }<br>+  }<br>+<br>+  return report->isValid();<br>+}<br>+<br>//===----------------------------------------------------------------------===//<br>// Methods for BugType and subclasses.<br>//===----------------------------------------------------------------------===//<br>@@ -2108,6 +2314,13 @@ bool GRBugReporter::generatePathDiagnost<br>  typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;<br>  PathGenerationScheme ActiveScheme = PC.getGenerationScheme();<br><br>+  if (ActiveScheme == PathDiagnosticConsumer::Extensive) {<br>+    AnalyzerOptions &options = getEngine().getAnalysisManager().options;<br>+    if (options.getBooleanOption("path-diagnostics-alternate", false)) {<br>+      ActiveScheme = PathDiagnosticConsumer::AlternateExtensive;<br>+    }<br>+  }<br>+<br>  TrimmedGraph TrimG(&getGraph(), errorNodes);<br>  ReportGraph ErrorGraph;<br><br>@@ -2169,6 +2382,9 @@ bool GRBugReporter::generatePathDiagnost<br>      LCM.clear();<br><br>      switch (ActiveScheme) {<br>+      case PathDiagnosticConsumer::AlternateExtensive:<br>+        GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);<br>+        break;<br>      case PathDiagnosticConsumer::Extensive:<br>        GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);<br>        break;<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a></div></blockquote></div><br></body></html>