[cfe-commits] r138728 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/ include/clang/StaticAnalyzer/Core/PathSensitive/ lib/StaticAnalyzer/Core/

Jordy Rose jediknil at belkadan.com
Sun Aug 28 12:11:56 PDT 2011


Author: jrose
Date: Sun Aug 28 14:11:56 2011
New Revision: 138728

URL: http://llvm.org/viewvc/llvm-project?rev=138728&view=rev
Log:
[analyzer] Introduce a new callback for checkers, printState, to be used for debug-printing the contents of a ProgramState.

Unlike the other callbacks, this one is a simple virtual method, since it is only to be used for debugging.

This new callback replaces the old ProgramState::Printer interface, and allows us to move the printing of refcount bindings from CFRefCount to RetainReleaseChecker.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
    cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Sun Aug 28 14:11:56 2011
@@ -338,6 +338,10 @@
 class CheckerBase : public ProgramPointTag {
 public:
   StringRef getTagDescription() const;
+
+  /// See CheckerManager::runCheckersForPrintState.
+  virtual void printState(raw_ostream &Out, const ProgramState *State,
+                          const char *NL, const char *Sep) const { }
 };
   
 template <typename CHECK1, typename CHECK2=check::_VoidCheck,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Sun Aug 28 14:11:56 2011
@@ -267,6 +267,17 @@
                                          AnalysisManager &mgr,
                                          BugReporter &BR);
 
+  /// \brief Run checkers for debug-printing a ProgramState.
+  ///
+  /// Unlike most other callbacks, any checker can simply implement the virtual
+  /// method CheckerBase::printState if it has custom data to print.
+  /// \param Out The output stream
+  /// \param State The state being printed
+  /// \param NL The preferred representation of a newline.
+  /// \param Sep The preferred separator between different kinds of data.
+  void runCheckersForPrintState(raw_ostream &Out, const ProgramState *State,
+                                const char *NL, const char *Sep);
+
 //===----------------------------------------------------------------------===//
 // Internal registration functions for AST traversing.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Sun Aug 28 14:11:56 2011
@@ -195,6 +195,10 @@
                        ArrayRef<const MemRegion *> ExplicitRegions,
                        ArrayRef<const MemRegion *> Regions);
 
+  /// printState - Called by ProgramStateManager to print checker-specific data.
+  void printState(raw_ostream &Out, const ProgramState *State,
+                  const char *NL, const char *Sep);
+
   virtual ProgramStateManager& getStateManager() { return StateMgr; }
 
   StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Sun Aug 28 14:11:56 2011
@@ -332,14 +332,6 @@
     return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key);
   }
 
-  // State pretty-printing.
-  class Printer {
-  public:
-    virtual ~Printer() {}
-    virtual void Print(raw_ostream &Out, const ProgramState *state,
-                       const char* nl, const char* sep) = 0;
-  };
-
   // Pretty-printing.
   void print(raw_ostream &Out, CFG &C, const char *nl = "\n",
              const char *sep = "") const;
@@ -404,7 +396,6 @@
 
 class ProgramStateManager {
   friend class ProgramState;
-  friend class ExprEngine; // FIXME: Remove.
 private:
   /// Eng - The SubEngine that owns this state manager.
   SubEngine *Eng; /* Can be null. */
@@ -418,10 +409,6 @@
   typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
   GDMContextsTy GDMContexts;
 
-  /// Printers - A set of printer objects used for pretty-printing a ProgramState.
-  ///  ProgramStateManager owns these objects.
-  std::vector<ProgramState::Printer*> Printers;
-
   /// StateSet - FoldingSet containing all the states created for analyzing
   ///  a particular function.  This is used to unique states.
   llvm::FoldingSet<ProgramState> StateSet;

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Sun Aug 28 14:11:56 2011
@@ -109,6 +109,10 @@
     return processRegionChanges(state, 0, MR, MR);
   }
 
+  /// printState - Called by ProgramStateManager to print checker-specific data.
+  virtual void printState(raw_ostream &Out, const ProgramState *State,
+                          const char *NL, const char *Sep) = 0;
+
   /// Called by CoreEngine when the analysis worklist is either empty or the
   //  maximum number of analysis steps have been reached.
   virtual void processEndWorklist(bool hasWorkRemaining) = 0;

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h Sun Aug 28 14:11:56 2011
@@ -36,7 +36,6 @@
   TransferFuncs() {}
   virtual ~TransferFuncs() {}
 
-  virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {}
   virtual void RegisterChecks(ExprEngine& Eng) {}
 
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Sun Aug 28 14:11:56 2011
@@ -255,7 +255,7 @@
 
 void RefVal::print(raw_ostream &Out) const {
   if (!T.isNull())
-    Out << "Tracked Type:" << T.getAsString() << '\n';
+    Out << "Tracked " << T.getAsString() << '/';
 
   switch (getKind()) {
     default: assert(false);
@@ -1585,14 +1585,6 @@
 
 class CFRefCount : public TransferFuncs {
 public:
-  class BindingsPrinter : public ProgramState::Printer {
-  public:
-    virtual void Print(raw_ostream &Out,
-                       const ProgramState *state,
-                       const char* nl,
-                       const char* sep);
-  };
-
   const LangOptions&   LOpts;
   const bool GCEnabled;
 
@@ -1601,60 +1593,12 @@
     : LOpts(lopts), GCEnabled(gcenabled) {}
 
   void RegisterChecks(ExprEngine &Eng);
-
-  virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {
-    Printers.push_back(new BindingsPrinter());
-  }
   
   const LangOptions& getLangOptions() const { return LOpts; }
 };
 
 } // end anonymous namespace
 
-static void PrintPool(raw_ostream &Out,
-                      SymbolRef Sym,
-                      const ProgramState *state) {
-  Out << ' ';
-  if (Sym)
-    Out << Sym->getSymbolID();
-  else
-    Out << "<pool>";
-  Out << ":{";
-
-  // Get the contents of the pool.
-  if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
-    for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
-      Out << '(' << J.getKey() << ',' << J.getData() << ')';
-
-  Out << '}';
-}
-
-void CFRefCount::BindingsPrinter::Print(raw_ostream &Out,
-                                        const ProgramState *state,
-                                        const char* nl, const char* sep) {
-
-  RefBindings B = state->get<RefBindings>();
-
-  if (!B.isEmpty())
-    Out << sep << nl;
-
-  for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
-    Out << (*I).first << " : ";
-    (*I).second.print(Out);
-    Out << nl;
-  }
-
-  // Print the autorelease stack.
-  Out << sep << nl << "AR pool stack:";
-  ARStack stack = state->get<AutoreleaseStack>();
-
-  PrintPool(Out, SymbolRef(), state);  // Print the caller's pool.
-  for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
-    PrintPool(Out, *I, state);
-
-  Out << nl;
-}
-
 //===----------------------------------------------------------------------===//
 // Error reporting.
 //===----------------------------------------------------------------------===//
@@ -2543,6 +2487,9 @@
     }
   }
 
+  void printState(raw_ostream &Out, const ProgramState *State,
+                  const char *NL, const char *Sep) const;
+
   void checkBind(SVal loc, SVal val, CheckerContext &C) const;
   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
   void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
@@ -3623,6 +3570,62 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Debug printing of refcount bindings and autorelease pools.
+//===----------------------------------------------------------------------===//
+
+static void PrintPool(raw_ostream &Out, SymbolRef Sym,
+                      const ProgramState *State) {
+  Out << ' ';
+  if (Sym)
+    Out << Sym->getSymbolID();
+  else
+    Out << "<pool>";
+  Out << ":{";
+
+  // Get the contents of the pool.
+  if (const ARCounts *Cnts = State->get<AutoreleasePoolContents>(Sym))
+    for (ARCounts::iterator I = Cnts->begin(), E = Cnts->end(); I != E; ++I)
+      Out << '(' << I.getKey() << ',' << I.getData() << ')';
+
+  Out << '}';
+}
+
+bool UsesAutorelease(const ProgramState *state) {
+  // A state uses autorelease if it allocated an autorelease pool or if it has
+  // objects in the caller's autorelease pool.
+  return !state->get<AutoreleaseStack>().isEmpty() ||
+          state->get<AutoreleasePoolContents>(SymbolRef());
+}
+
+void RetainReleaseChecker::printState(raw_ostream &Out,
+                                      const ProgramState *State,
+                                      const char *NL, const char *Sep) const {
+
+  RefBindings B = State->get<RefBindings>();
+
+  if (!B.isEmpty())
+    Out << Sep << NL;
+
+  for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+    Out << I->first << " : ";
+    I->second.print(Out);
+    Out << NL;
+  }
+
+  // Print the autorelease stack.
+  if (UsesAutorelease(State)) {
+    Out << Sep << NL << "AR pool stack:";
+    ARStack Stack = State->get<AutoreleaseStack>();
+
+    PrintPool(Out, SymbolRef(), State);  // Print the caller's pool.
+    for (ARStack::iterator I = Stack.begin(), E = Stack.end(); I != E; ++I)
+      PrintPool(Out, *I, State);
+
+    Out << NL;
+  }
+}
+
+//===----------------------------------------------------------------------===//
 // Transfer function creation for external clients.
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Sun Aug 28 14:11:56 2011
@@ -426,6 +426,14 @@
     EndOfTranslationUnitCheckers[i](TU, mgr, BR);
 }
 
+void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
+                                              const ProgramState *State,
+                                              const char *NL, const char *Sep) {
+  for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
+        I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
+    I->second->printState(Out, State, NL, Sep);
+}
+
 //===----------------------------------------------------------------------===//
 // Internal registration functions for AST traversing.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sun Aug 28 14:11:56 2011
@@ -67,7 +67,6 @@
 
   // FIXME: Eventually remove the TF object entirely.
   TF->RegisterChecks(*this);
-  TF->RegisterPrinters(getStateManager().Printers);
   
   if (mgr.shouldEagerlyTrimExplodedGraph()) {
     // Enable eager node reclaimation when constructing the ExplodedGraph.  
@@ -189,6 +188,11 @@
                                                          Explicits, Regions);
 }
 
+void ExprEngine::printState(raw_ostream &Out, const ProgramState *State,
+                            const char *NL, const char *Sep) {
+  getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
+}
+
 void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
   getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=138728&r1=138727&r2=138728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Sun Aug 28 14:11:56 2011
@@ -51,10 +51,6 @@
 }
 
 ProgramStateManager::~ProgramStateManager() {
-  for (std::vector<ProgramState::Printer*>::iterator I=Printers.begin(),
-        E=Printers.end(); I!=E; ++I)
-    delete *I;
-
   for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
        I!=E; ++I)
     I->second.second(I->second.first);
@@ -389,11 +385,11 @@
   return (bool) (((uintptr_t) S) & 0x1);
 }
 
-void ProgramState::print(raw_ostream &Out, CFG &C, const char* nl,
-                    const char* sep) const {
+void ProgramState::print(raw_ostream &Out, CFG &C,
+                         const char *NL, const char *Sep) const {
   // Print the store.
   ProgramStateManager &Mgr = getStateManager();
-  Mgr.getStoreManager().print(getStore(), Out, nl, sep);
+  Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
 
   // Print Subexpression bindings.
   bool isFirst = true;
@@ -404,10 +400,11 @@
       continue;
 
     if (isFirst) {
-      Out << nl << nl << "Sub-Expressions:" << nl;
+      Out << NL << NL << "Sub-Expressions:" << NL;
       isFirst = false;
+    } else {
+      Out << NL;
     }
-    else { Out << nl; }
 
     Out << " (" << (void*) I.getKey() << ") ";
     LangOptions LO; // FIXME.
@@ -423,10 +420,11 @@
       continue;
 
     if (isFirst) {
-      Out << nl << nl << "Block-level Expressions:" << nl;
+      Out << NL << NL << "Block-level Expressions:" << NL;
       isFirst = false;
+    } else {
+      Out << NL;
     }
-    else { Out << nl; }
 
     Out << " (" << (void*) I.getKey() << ") ";
     LangOptions LO; // FIXME.
@@ -442,10 +440,11 @@
       continue;
     
     if (isFirst) {
-      Out << nl << nl << "Load/store locations:" << nl;
+      Out << NL << NL << "Load/store locations:" << NL;
       isFirst = false;
+    } else {
+      Out << NL;
     }
-    else { Out << nl; }
 
     const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
     
@@ -455,13 +454,10 @@
     Out << " : " << I.getData();
   }
 
-  Mgr.getConstraintManager().print(this, Out, nl, sep);
+  Mgr.getConstraintManager().print(this, Out, NL, Sep);
 
   // Print checker-specific data.
-  for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
-                                       E = Mgr.Printers.end(); I != E; ++I) {
-    (*I)->Print(Out, this, nl, sep);
-  }
+  Mgr.getOwningEngine()->printState(Out, this, NL, Sep);
 }
 
 void ProgramState::printDOT(raw_ostream &Out, CFG &C) const {





More information about the cfe-commits mailing list