[cfe-commits] r151317 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h lib/StaticAnalyzer/Core/BugReporter.cpp lib/StaticAnalyzer/Core/BugReporterVisitors.cpp lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp lib/StaticAnalyzer/Core/PathDiagnostic.cpp lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

Ted Kremenek kremenek at apple.com
Thu Feb 23 16:38:56 PST 2012


Author: kremenek
Date: Thu Feb 23 18:38:56 2012
New Revision: 151317

URL: http://llvm.org/viewvc/llvm-project?rev=151317&view=rev
Log:
Rework PathDiagnostic creation so that call stacks are captured by a nested PathDiagnosticCallPiece.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h Thu Feb 23 18:38:56 2012
@@ -170,23 +170,6 @@
                     llvm::raw_ostream &Out,
                     BugReporterContext &BRC);
 };
-
-class CallEnterExitBRVisitor : public BugReporterVisitor {
-  const bool showTopLevelCall;
-public:
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    static int x = 0;
-    ID.AddPointer(&x);
-  }
-  
-  CallEnterExitBRVisitor(bool showTopLevel)
-    : showTopLevelCall(showTopLevel) {}
-  
-  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                 const ExplodedNode *PrevN,
-                                 BugReporterContext &BRC,
-                                 BugReport &BR);
-};
   
 namespace bugreporter {
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Thu Feb 23 18:38:56 2012
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_PATH_DIAGNOSTIC_H
 
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Analysis/ProgramPoint.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/PointerUnion.h"
@@ -262,7 +263,7 @@
 
 class PathDiagnosticPiece : public RefCountedBaseVPTR {
 public:
-  enum Kind { ControlFlow, Event, Macro, CallEnter, CallExit };
+  enum Kind { ControlFlow, Event, Macro, Call };
   enum DisplayHint { Above, Below };
 
 private:
@@ -364,31 +365,53 @@
     return P->getKind() == Event;
   }
 };
+
+class PathDiagnosticCallPiece : public PathDiagnosticPiece {
+  PathDiagnosticCallPiece(const Decl *callerD,
+                          const PathDiagnosticLocation &callReturnPos)
+    : PathDiagnosticPiece(Call), Caller(callerD),
+      Callee(0), callReturn(callReturnPos) {}
+
+  PathDiagnosticCallPiece(PathPieces &oldPath)
+    : PathDiagnosticPiece(Call), Caller(0), Callee(0), path(oldPath) {}
   
-class PathDiagnosticCallEnterPiece : public PathDiagnosticSpotPiece {
+  const Decl *Caller;
+  const Decl *Callee;
 public:
-  PathDiagnosticCallEnterPiece(const PathDiagnosticLocation &pos,
-                              StringRef s)
-    : PathDiagnosticSpotPiece(pos, s, CallEnter, false) {}
+  PathDiagnosticLocation callEnter;
+  PathDiagnosticLocation callReturn;  
+  PathPieces path;
   
-  ~PathDiagnosticCallEnterPiece();
+  virtual ~PathDiagnosticCallPiece();
   
-  static inline bool classof(const PathDiagnosticPiece *P) {
-    return P->getKind() == CallEnter;
-  }  
-};
+  const Decl *getCaller() const { return Caller; }
+  
+  const Decl *getCallee() const { return Callee; }
+  void setCallee(const CallEnter &CE, const SourceManager &SM);
+  
+  virtual PathDiagnosticLocation getLocation() const {
+    return callEnter;
+  }
+  
+  IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const;
+  IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
 
-class PathDiagnosticCallExitPiece : public PathDiagnosticSpotPiece {
-public:
-  PathDiagnosticCallExitPiece(const PathDiagnosticLocation &pos,
-                             StringRef s)
-  : PathDiagnosticSpotPiece(pos, s, CallExit, false) {}
+  virtual void flattenLocations() {
+    callEnter.flatten();
+    callReturn.flatten();
+    for (PathPieces::iterator I = path.begin(), 
+         E = path.end(); I != E; ++I) (*I)->flattenLocations();
+  }
+  
+  static PathDiagnosticCallPiece *construct(const ExplodedNode *N,
+                                            const CallExit &CE,
+                                            const SourceManager &SM);
   
-  ~PathDiagnosticCallExitPiece();
+  static PathDiagnosticCallPiece *construct(PathPieces &pieces);
   
   static inline bool classof(const PathDiagnosticPiece *P) {
-    return P->getKind() == CallExit;
-  }  
+    return P->getKind() == Call;
+  }
 };
 
 class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
@@ -479,8 +502,27 @@
   std::string Desc;
   std::string Category;
   std::deque<std::string> OtherDesc;
+  PathPieces pathImpl;
+  llvm::SmallVector<PathPieces *, 3> pathStack;
 public:
-  PathPieces path;
+  const PathPieces &path;
+
+  /// Return the path currently used by builders for constructing the 
+  /// PathDiagnostic.
+  PathPieces &getActivePath() {
+    if (pathStack.empty())
+      return pathImpl;
+    return *pathStack.back();
+  }
+  
+  /// Return a mutable version of 'path'.
+  PathPieces &getMutablePieces() {
+    return pathImpl;
+  }
+    
+
+  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
+  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
 
   PathDiagnostic();
   PathDiagnostic(StringRef bugtype, StringRef desc,
@@ -505,7 +547,7 @@
   }
 
   void flattenLocations() {
-    for (PathPieces::iterator I = path.begin(), E = path.end(); 
+    for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); 
          I != E; ++I) (*I)->flattenLocations();
   }
   

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Feb 23 18:38:56 2012
@@ -447,7 +447,7 @@
       PathDiagnosticLocation L =
         PathDiagnosticLocation::createBegin(S, BR.getSourceManager(),
                                                    Pred->getLocationContext());
-      PD.path.push_front(new PathDiagnosticEventPiece(L, os.str()));
+      PD.getActivePath().push_front(new PathDiagnosticEventPiece(L, os.str()));
     }
 
     return true;
@@ -529,6 +529,32 @@
     NextNode = GetPredecessorNode(N);
 
     ProgramPoint P = N->getLocation();
+    
+    if (const CallExit *CE = dyn_cast<CallExit>(&P)) {
+      PathDiagnosticCallPiece *C =
+        PathDiagnosticCallPiece::construct(N, *CE, SMgr);
+      PD.getActivePath().push_front(C);
+      PD.pushActivePath(&C->path);
+      continue;      
+    }
+    
+    if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) {
+      PD.popActivePath();
+      // The current active path should never be empty.  Either we
+      // just added a bunch of stuff to the top-level path, or
+      // we have a previous CallExit.  If the front of the active
+      // path is not a PathDiagnosticCallPiece, it means that the
+      // path terminated within a function call.  We must then take the
+      // current contents of the active path and place it within
+      // a new PathDiagnosticCallPiece.
+      assert(!PD.getActivePath().empty());
+      PathDiagnosticCallPiece *C = 
+        dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
+      if (!C)
+        C = PathDiagnosticCallPiece::construct(PD.getActivePath());
+      C->setCallee(*CE, SMgr);
+      continue;
+    }
 
     if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
       const CFGBlock *Src = BE->getSrc();
@@ -559,7 +585,7 @@
 
           os << "Control jumps to line "
           << End.asLocation().getExpansionLineNumber();
-          PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                                 os.str()));
           break;
         }
@@ -611,13 +637,13 @@
                 break;
               }
             }
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                              os.str()));
           }
           else {
             os << "'Default' branch taken. ";
             const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                              os.str()));
           }
 
@@ -629,7 +655,7 @@
           std::string sbuf;
           llvm::raw_string_ostream os(sbuf);
           PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
-          PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                            os.str()));
           break;
         }
@@ -651,7 +677,7 @@
           if (const Stmt *S = End.asStmt())
             End = PDB.getEnclosingStmtLocation(S);
 
-          PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                            os.str()));
           break;
         }
@@ -674,14 +700,14 @@
               PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
               PathDiagnosticLocation Start =
                 PathDiagnosticLocation::createOperatorLoc(B, SMgr);
-              PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                                os.str()));
             }
             else {
               os << "true";
               PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
               PathDiagnosticLocation End = PDB.ExecutionContinues(N);
-              PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                                os.str()));
             }
           }
@@ -693,7 +719,7 @@
               os << "false";
               PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
               PathDiagnosticLocation End = PDB.ExecutionContinues(N);
-              PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                                os.str()));
             }
             else {
@@ -701,7 +727,7 @@
               PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
               PathDiagnosticLocation Start =
                 PathDiagnosticLocation::createOperatorLoc(B, SMgr);
-              PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                                os.str()));
             }
           }
@@ -720,7 +746,7 @@
             if (const Stmt *S = End.asStmt())
               End = PDB.getEnclosingStmtLocation(S);
 
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                              os.str()));
           }
           else {
@@ -729,7 +755,7 @@
             if (const Stmt *S = End.asStmt())
               End = PDB.getEnclosingStmtLocation(S);
 
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                               "Loop condition is false.  Exiting loop"));
           }
 
@@ -747,7 +773,7 @@
             if (const Stmt *S = End.asStmt())
               End = PDB.getEnclosingStmtLocation(S);
 
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                              os.str()));
           }
           else {
@@ -755,7 +781,7 @@
             if (const Stmt *S = End.asStmt())
               End = PDB.getEnclosingStmtLocation(S);
 
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                             "Loop condition is true.  Entering loop body"));
           }
 
@@ -769,10 +795,10 @@
             End = PDB.getEnclosingStmtLocation(S);
 
           if (*(Src->succ_begin()+1) == Dst)
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                         "Taking false branch"));
           else
-            PD.path.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End,
                                                          "Taking true branch"));
 
           break;
@@ -786,7 +812,7 @@
       for (BugReport::visitor_iterator I = R->visitor_begin(),
            E = R->visitor_end(); I!=E; ++I) {
         if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R))
-          PD.path.push_front(p);
+          PD.getActivePath().push_front(p);
       }
     }
 
@@ -1019,7 +1045,7 @@
       PrevLocClean.asLocation().getExpansionLoc())
     return;
 
-  PD.path.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
+  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
   PrevLoc = NewLoc;
 }
 
@@ -1146,6 +1172,10 @@
                                    LCtx);
         EB.addEdge(Loc, true);
         EB.flushLocations();
+        PathDiagnosticCallPiece *C =
+          PathDiagnosticCallPiece::construct(N, *CE, SM);
+        PD.getActivePath().push_front(C);
+        PD.pushActivePath(&C->path);
         break;
       }
       
@@ -1156,6 +1186,27 @@
           N->getLocationContext()->getCurrentStackFrame()) {
         EB.flushLocations();
       }
+      
+      // Pop the call hierarchy if we are done walking the contents
+      // of a function call.
+      if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) {
+        PD.popActivePath();
+        // The current active path should never be empty.  Either we
+        // just added a bunch of stuff to the top-level path, or
+        // we have a previous CallExit.  If the front of the active
+        // path is not a PathDiagnosticCallPiece, it means that the
+        // path terminated within a function call.  We must then take the
+        // current contents of the active path and place it within
+        // a new PathDiagnosticCallPiece.
+        assert(!PD.getActivePath().empty());
+        PathDiagnosticCallPiece *C = 
+          dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
+        if (!C)
+          C = PathDiagnosticCallPiece::construct(PD.getActivePath());
+        C->setCallee(*CE, SM);
+        EB.addContext(CE->getCallExpr());
+        break;
+      }
 
       // Block edges.
       if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {        
@@ -1179,7 +1230,7 @@
                                         "Looping back to the head of the loop");
 
           EB.addEdge(p->getLocation(), true);
-          PD.path.push_front(p);
+          PD.getActivePath().push_front(p);
 
           if (CS) {
             PathDiagnosticLocation BL =
@@ -1221,7 +1272,7 @@
       if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
         const PathDiagnosticLocation &Loc = p->getLocation();
         EB.addEdge(Loc, true);
-        PD.path.push_front(p);
+        PD.getActivePath().push_front(p);
         if (const Stmt *S = Loc.asStmt())
           EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
       }
@@ -1552,8 +1603,8 @@
 /// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
 ///  and collapses PathDiagosticPieces that are expanded by macros.
 static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
-  typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, SourceLocation> >
-          MacroStackTy;
+  typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>,
+                                SourceLocation> > MacroStackTy;
 
   typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> >
           PiecesTy;
@@ -1561,7 +1612,8 @@
   MacroStackTy MacroStack;
   PiecesTy Pieces;
 
-  for (PathPieces::iterator I = PD.path.begin(), E = PD.path.end(); I!=E; ++I) {
+  for (PathPieces::const_iterator I = PD.path.begin(), E = PD.path.end();
+       I!=E; ++I) {
     // Get the location of the PathDiagnosticPiece.
     const FullSourceLoc Loc = (*I)->getLocation().asLocation();
 
@@ -1630,13 +1682,13 @@
   }
 
   // Now take the pieces and construct a new PathDiagnostic.
-  PD.path.clear();
+  PD.getMutablePieces().clear();
 
   for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
     if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
       if (!MP->containsEvent())
         continue;
-    PD.path.push_back(*I);
+    PD.getMutablePieces().push_back(*I);
   }
 }
 
@@ -1672,11 +1724,6 @@
   // Register additional node visitors.
   R->addVisitor(new NilReceiverBRVisitor());
   R->addVisitor(new ConditionBRVisitor());
-  
-  // If inlining is turning out, emit diagnostics for CallEnter and
-  // CallExit at the top level.
-  bool showTopLevel = Eng.getAnalysisManager().shouldInlineCall();
-  R->addVisitor(new CallEnterExitBRVisitor(showTopLevel));
 
   // Generate the very last diagnostic piece - the piece is visible before 
   // the trace is expanded.
@@ -1692,7 +1739,7 @@
   if (!LastPiece)
     LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
   if (LastPiece)
-    PD.path.push_back(LastPiece);
+    PD.getActivePath().push_back(LastPiece);
   else
     return;
 
@@ -1957,7 +2004,7 @@
                                  exampleReport->getDescription());
 
     for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
-    D->path.push_back(piece);
+    D->getActivePath().push_back(piece);
   }
 
   PD->HandlePathDiagnostic(D.take());

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Thu Feb 23 18:38:56 2012
@@ -709,51 +709,3 @@
   return new PathDiagnosticEventPiece(Loc, Out.str());
 }
 
-static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N,
-                                             const SourceManager &SM) {
-  while (N) {
-    ProgramPoint PP = N->getLocation();
-    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP))
-      return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext());
-    if (N->pred_empty())
-      break;
-    N = *N->pred_begin();
-  }
-  return PathDiagnosticLocation();
-}
-
-PathDiagnosticPiece *
-CallEnterExitBRVisitor::VisitNode(const ExplodedNode *N,
-                                  const ExplodedNode *PrevN,
-                                  BugReporterContext &BRC,
-                                  BugReport &BR) {
-  ProgramPoint PP = N->getLocation();
-  SmallString<256> buf;
-  llvm::raw_svector_ostream Out(buf);
-  PathDiagnosticLocation pos;
-
-  if (const CallEnter *CEnter = dyn_cast<CallEnter>(&PP)) {
-    const Decl *callee = CEnter->getCalleeContext()->getDecl();
-    pos = PathDiagnosticLocation(CEnter->getCallExpr(), BRC.getSourceManager(),
-                                 PP.getLocationContext());
-    if (isa<BlockDecl>(callee))
-      Out << "Entering call to block";
-    else if (const NamedDecl *ND = dyn_cast<NamedDecl>(callee))
-      Out << "Entering call to '" << *ND << "'";
-    StringRef msg = Out.str();
-    if (msg.empty())
-      return 0;
-    return new PathDiagnosticCallEnterPiece(pos, msg);
-  }
-  else if (const CallExit *CExit = dyn_cast<CallExit>(&PP)) {
-    const Decl *caller = CExit->getLocationContext()->getParent()->getDecl();
-    pos = getLastStmtLoc(PrevN, BRC.getSourceManager());
-    if (const NamedDecl *ND = dyn_cast<NamedDecl>(caller))
-      Out << "Returning to '" << *ND << "'";
-    else
-      Out << "Returning to caller";
-    return new PathDiagnosticCallExitPiece(pos, Out.str());
-  }
-
-  return 0;
-} 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp Thu Feb 23 18:38:56 2012
@@ -95,8 +95,31 @@
   }
 }
 
+static void flattenPath(PathPieces &path, const PathPieces &oldPath) {
+  for (PathPieces::const_iterator it = oldPath.begin(), et = oldPath.end();
+       it != et; ++it ) {
+    PathDiagnosticPiece *piece = it->getPtr();
+    if (const PathDiagnosticCallPiece *call =
+        dyn_cast<PathDiagnosticCallPiece>(piece)) {
+      IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnter =
+        call->getCallEnterEvent();
+      if (callEnter)
+        path.push_back(callEnter);
+      flattenPath(path, call->path);
+      IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
+        call->getCallExitEvent();
+      if (callExit)
+        path.push_back(callExit);
+      continue;
+    }
+
+    path.push_back(piece);
+  }
+}
+
 void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
-                                 SmallVectorImpl<std::string> *FilesMade){
+                                 SmallVectorImpl<std::string> *FilesMade) {
+    
   // Create the HTML directory if it is missing.
   if (!createdDir) {
     createdDir = true;
@@ -119,11 +142,15 @@
   if (noDir)
     return;
 
-  const SourceManager &SMgr = (*D.path.begin())->getLocation().getManager();
+  // First flatten out the entire path to make it easier to use.
+  PathPieces path;
+  flattenPath(path, D.path);
+  
+  const SourceManager &SMgr = (*path.begin())->getLocation().getManager();
   FileID FID;
 
   // Verify that the entire path is from the same FileID.
-  for (PathPieces::const_iterator I = D.path.begin(), E = D.path.end();
+  for (PathPieces::const_iterator I = path.begin(), E = path.end();
        I != E; ++I) {
     FullSourceLoc L = (*I)->getLocation().asLocation().getExpansionLoc();
 
@@ -152,10 +179,11 @@
   Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
 
   // Process the path.
-  unsigned n = D.path.size();
+  unsigned n = path.size();
   unsigned max = n;
 
-  for (PathPieces::const_reverse_iterator I = D.path.rbegin(), E=D.path.rend();
+  for (PathPieces::const_reverse_iterator I = path.rbegin(), 
+       E = path.rend();
         I != E; ++I, --n)
     HandlePiece(R, FID, **I, n, max);
 
@@ -200,9 +228,9 @@
       << html::EscapeText(Entry->getName())
       << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
          "<a href=\"#EndPath\">line "
-      << (*D.path.rbegin())->getLocation().asLocation().getExpansionLineNumber()
+      << (*path.rbegin())->getLocation().asLocation().getExpansionLineNumber()
       << ", column "
-      << (*D.path.rbegin())->getLocation().asLocation().getExpansionColumnNumber()
+      << (*path.rbegin())->getLocation().asLocation().getExpansionColumnNumber()
       << "</a></td></tr>\n"
          "<tr><td class=\"rowname\">Description:</td><td>"
       << D.getDescription() << "</td></tr>\n";
@@ -240,10 +268,10 @@
     os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
 
     os << "\n<!-- BUGLINE "
-       << D.path.back()->getLocation().asLocation().getExpansionLineNumber()
+       << path.back()->getLocation().asLocation().getExpansionLineNumber()
        << " -->\n";
 
-    os << "\n<!-- BUGPATHLENGTH " << D.path.size() << " -->\n";
+    os << "\n<!-- BUGPATHLENGTH " << path.size() << " -->\n";
 
     // Mark the end of the tags.
     os << "\n<!-- BUGMETAEND -->\n";
@@ -332,8 +360,8 @@
 
   const char *Kind = 0;
   switch (P.getKind()) {
-  case PathDiagnosticPiece::CallEnter:
-  case PathDiagnosticPiece::CallExit:
+  case PathDiagnosticPiece::Call:
+      llvm_unreachable("Calls should already be handled");
   case PathDiagnosticPiece::Event:  Kind = "Event"; break;
   case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
     // Setting Kind to "Control" is intentional.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Thu Feb 23 18:38:56 2012
@@ -51,11 +51,10 @@
 
 PathDiagnosticPiece::~PathDiagnosticPiece() {}
 PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
-PathDiagnosticCallEnterPiece::~PathDiagnosticCallEnterPiece() {}
-PathDiagnosticCallExitPiece::~PathDiagnosticCallExitPiece() {}
+PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
 PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
 PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
-PathDiagnostic::PathDiagnostic() {}
+PathDiagnostic::PathDiagnostic() : path(pathImpl) {}
 PathPieces::~PathPieces() {}
 PathDiagnostic::~PathDiagnostic() {}
 
@@ -63,7 +62,8 @@
                                StringRef category)
   : BugType(StripTrailingDots(bugtype)),
     Desc(StripTrailingDots(desc)),
-    Category(StripTrailingDots(category)) {}
+    Category(StripTrailingDots(category)),
+    path(pathImpl) {}
 
 void PathDiagnosticConsumer::anchor() { }
 
@@ -421,6 +421,78 @@
   }
 }
 
+
+//===----------------------------------------------------------------------===//
+// Manipulation of PathDiagnosticCallPieces.
+//===----------------------------------------------------------------------===//
+
+static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N,
+                                             const SourceManager &SM) {
+  while (N) {
+    ProgramPoint PP = N->getLocation();
+    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP))
+      return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext());
+    if (N->pred_empty())
+      break;
+    N = *N->pred_begin();
+  }
+  return PathDiagnosticLocation();
+}
+
+PathDiagnosticCallPiece *
+PathDiagnosticCallPiece::construct(const ExplodedNode *N,
+                                   const CallExit &CE,
+                                   const SourceManager &SM) {
+  const Decl *caller = CE.getLocationContext()->getParent()->getDecl();
+  PathDiagnosticLocation pos = getLastStmtLoc(N, SM);
+  return new PathDiagnosticCallPiece(caller, pos);
+}
+
+PathDiagnosticCallPiece *
+PathDiagnosticCallPiece::construct(PathPieces &path) {
+  PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path);
+  path.clear();
+  path.push_front(C);
+  return C;
+}
+
+void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
+                                        const SourceManager &SM) {
+  const Decl *D = CE.getCalleeContext()->getDecl();
+  Caller = D;
+  callEnter = PathDiagnosticLocation(CE.getCallExpr(), SM,
+                                     CE.getLocationContext());  
+}
+
+IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+PathDiagnosticCallPiece::getCallEnterEvent() const {
+  if (!Callee)
+    return 0;  
+  SmallString<256> buf;
+  llvm::raw_svector_ostream Out(buf);
+  if (isa<BlockDecl>(Callee))
+    Out << "Entering call to block";
+  else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Callee))
+    Out << "Entering call to '" << *ND << "'";
+  StringRef msg = Out.str();
+  if (msg.empty())
+    return 0;
+  return new PathDiagnosticEventPiece(callEnter, msg);
+}
+
+IntrusiveRefCntPtr<PathDiagnosticEventPiece> 
+PathDiagnosticCallPiece::getCallExitEvent() const {
+  if (!Caller)
+    return 0;
+  SmallString<256> buf;
+  llvm::raw_svector_ostream Out(buf);
+  if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Caller))
+    Out << "Returning to '" << *ND << "'";
+  else
+    Out << "Returning to caller";
+  return new PathDiagnosticEventPiece(callReturn, Out.str());
+}
+
 //===----------------------------------------------------------------------===//
 // FoldingSet profiling methods.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=151317&r1=151316&r2=151317&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Thu Feb 23 18:38:56 2012
@@ -240,6 +240,33 @@
   Indent(o, indent); o << "</dict>\n";
 }
 
+static void ReportPiece(raw_ostream &o,
+                        const PathDiagnosticPiece &P,
+                        const FIDMap& FM, const SourceManager &SM,
+                        const LangOptions &LangOpts,
+                        unsigned indent,
+                        bool includeControlFlow);
+
+static void ReportCall(raw_ostream &o,
+                       const PathDiagnosticCallPiece &P,
+                       const FIDMap& FM, const SourceManager &SM,
+                       const LangOptions &LangOpts,
+                       unsigned indent) {
+
+  IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
+    P.getCallExitEvent();
+  if (callExit)  
+    ReportPiece(o, *callExit, FM, SM, LangOpts, indent, true);
+
+  for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
+    ReportPiece(o, **I, FM, SM, LangOpts, indent, true);
+  
+  IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnter =
+    P.getCallEnterEvent();  
+  if (callEnter)
+    ReportPiece(o, *callEnter, FM, SM, LangOpts, indent, true);
+}
+
 static void ReportMacro(raw_ostream &o,
                         const PathDiagnosticMacroPiece& P,
                         const FIDMap& FM, const SourceManager &SM,
@@ -248,43 +275,40 @@
 
   for (PathPieces::const_iterator I = P.subPieces.begin(), E=P.subPieces.end();
        I!=E; ++I) {
-
-    switch ((*I)->getKind()) {
-    default:
-      break;
-    case PathDiagnosticPiece::Event:
-      ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
-                  indent);
-      break;
-    case PathDiagnosticPiece::Macro:
-      ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
-                  indent);
-      break;
-    }
+    ReportPiece(o, **I, FM, SM, LangOpts, indent, false);
   }
 }
 
 static void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P,
                        const FIDMap& FM, const SourceManager &SM,
                        const LangOptions &LangOpts) {
+  ReportPiece(o, P, FM, SM, LangOpts, 4, true);
+}
 
-  unsigned indent = 4;
-
+static void ReportPiece(raw_ostream &o,
+                        const PathDiagnosticPiece &P,
+                        const FIDMap& FM, const SourceManager &SM,
+                        const LangOptions &LangOpts,
+                        unsigned indent,
+                        bool includeControlFlow) {
   switch (P.getKind()) {
-  case PathDiagnosticPiece::ControlFlow:
-    ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
-                      LangOpts, indent);
-    break;
-  case PathDiagnosticPiece::CallEnter:
-  case PathDiagnosticPiece::CallExit:
-  case PathDiagnosticPiece::Event:
-    ReportEvent(o, cast<PathDiagnosticSpotPiece>(P), FM, SM, LangOpts,
-                indent);
-    break;
-  case PathDiagnosticPiece::Macro:
-    ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
-                indent);
-    break;
+    case PathDiagnosticPiece::ControlFlow:
+      if (includeControlFlow)
+        ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
+                          LangOpts, indent);
+      break;
+    case PathDiagnosticPiece::Call:
+      ReportCall(o, cast<PathDiagnosticCallPiece>(P), FM, SM, LangOpts,
+                 indent);
+      break;
+    case PathDiagnosticPiece::Event:
+      ReportEvent(o, cast<PathDiagnosticSpotPiece>(P), FM, SM, LangOpts,
+                  indent);
+      break;
+    case PathDiagnosticPiece::Macro:
+      ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
+                  indent);
+      break;
   }
 }
 





More information about the cfe-commits mailing list