]> granicus.if.org Git - clang/commitdiff
Make a bunch of new data structures for the new analysis
authorZhongxing Xu <xuzhongxing@gmail.com>
Thu, 22 Jul 2010 13:52:13 +0000 (13:52 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Thu, 22 Jul 2010 13:52:13 +0000 (13:52 +0000)
engine of the new translation unit. State marshal is there but no real
work is done. End nodes are passed back.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109105 91177308-0d34-0410-b5e6-96231b3b80d8

examples/wpa/clang-wpa.cpp
include/clang/Analysis/AnalysisContext.h
include/clang/Checker/PathSensitive/AnalysisManager.h
include/clang/Checker/PathSensitive/GRCoreEngine.h
include/clang/Checker/PathSensitive/GRExprEngine.h
include/clang/Checker/PathSensitive/GRState.h
include/clang/Checker/PathSensitive/GRSubEngine.h
include/clang/Index/TranslationUnit.h
lib/Analysis/AnalysisContext.cpp
lib/Checker/GRCoreEngine.cpp
lib/Checker/GRState.cpp

index 1caa3b9b68ccfa0a4708c8f1f820946d0e2d5f8e..af3fb6a2d2acfbb994ed1059ee95af96ec966f2f 100644 (file)
@@ -62,6 +62,10 @@ public:
     return AST->getPreprocessor();
   }
 
+  virtual Diagnostic &getDiagnostic() {
+    return AST->getDiagnostics();
+  }
+
   virtual DeclReferenceMap &getDeclReferenceMap() {
     return DeclRefMap;
   }
index 45f1e9369947a45aa921d54dd19fd9894e345523..04672a5f18c6e802976897ff90cfc06e54a97612 100644 (file)
@@ -42,7 +42,7 @@ class AnalysisContext {
   const Decl *D;
 
   // TranslationUnit is NULL if we don't have multiple translation units.
-  const idx::TranslationUnit *TU;
+  idx::TranslationUnit *TU;
 
   // AnalysisContext owns the following data.
   CFG *cfg;
@@ -53,7 +53,7 @@ class AnalysisContext {
   llvm::BumpPtrAllocator A;
   bool AddEHEdges;
 public:
-  AnalysisContext(const Decl *d, const idx::TranslationUnit *tu,
+  AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
                   bool addehedges = false)
     : D(d), TU(tu), cfg(0), builtCFG(false), liveness(0), PM(0),
       ReferencedBlockVars(0), AddEHEdges(addehedges) {}
@@ -63,7 +63,7 @@ public:
   ASTContext &getASTContext() { return D->getASTContext(); }
   const Decl *getDecl() const { return D; }
 
-  const idx::TranslationUnit *getTranslationUnit() const { return TU; }
+  idx::TranslationUnit *getTranslationUnit() const { return TU; }
 
   /// getAddEHEdges - Return true iff we are adding exceptional edges from
   /// callExprs.  If this is false, then try/catch statements and blocks
@@ -91,7 +91,7 @@ class AnalysisContextManager {
 public:
   ~AnalysisContextManager();
 
-  AnalysisContext *getContext(const Decl *D,const idx::TranslationUnit *TU = 0);
+  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
 
   // Discard all previously created AnalysisContexts.
   void clear();
@@ -121,7 +121,7 @@ public:
 
   AnalysisContext *getAnalysisContext() const { return Ctx; }
 
-  const idx::TranslationUnit *getTranslationUnit() const { 
+  idx::TranslationUnit *getTranslationUnit() const { 
     return Ctx->getTranslationUnit(); 
   }
 
index 3f673618cf66717ebb26979ed64d5015addde686..606dd0df6ddc458c6d28b746a4edb5dec1f056c9 100644 (file)
@@ -99,6 +99,8 @@ public:
     return CreateConstraintMgr;
   }
 
+  idx::Indexer *getIndexer() const { return Idxer; }
+
   virtual ASTContext &getASTContext() {
     return Ctx;
   }
@@ -160,10 +162,14 @@ public:
     return AnaCtxMgr.getContext(D)->getParentMap();
   }
 
-  const AnalysisContext *getAnalysisContext(const Decl *D) {
+  AnalysisContext *getAnalysisContext(const Decl *D) {
     return AnaCtxMgr.getContext(D);
   }
 
+  AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
+    return AnaCtxMgr.getContext(D, TU);
+  }
+
   const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
                                          LocationContext const *Parent,
                                          Stmt const *S, const CFGBlock *Blk,
@@ -173,7 +179,7 @@ public:
 
   // Get the top level stack frame.
   const StackFrameContext *getStackFrame(Decl const *D, 
-                                         const idx::TranslationUnit *TU) {
+                                         idx::TranslationUnit *TU) {
     return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
   }
 
index 6e3cd85b996a74cf05303e6998fefe45421c05cc..c69ef70bef4df158d2fe310617d7a7a0ca4cd04c 100644 (file)
@@ -153,7 +153,11 @@ public:
 
   /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
   ///  steps.  Returns true if there is still simulation state on the worklist.
-  bool ExecuteWorkList(const LocationContext *L, unsigned Steps);
+  bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
+                       const GRState *InitState);
+  void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+                                       const GRState *InitState, 
+                                       ExplodedNodeSet &Dst);
 };
 
 class GRStmtNodeBuilder {
index 6a12d6304eb4e538be5f4a4a866e116130a73c1c..8f01ab9f7ce07238b795f3f0d6cf43efbba9830a 100644 (file)
@@ -114,13 +114,22 @@ public:
   ~GRExprEngine();
 
   void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
-    CoreEngine.ExecuteWorkList(L, Steps);
+    CoreEngine.ExecuteWorkList(L, Steps, 0);
+  }
+
+  /// Execute the work list with an initial state. Nodes that reaches the exit
+  /// of the function are added into the Dst set, which represent the exit
+  /// state of the function call.
+  void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+                                       const GRState *InitState, 
+                                       ExplodedNodeSet &Dst) {
+    CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
   }
 
   /// getContext - Return the ASTContext associated with this analysis.
   ASTContext& getContext() const { return AMgr.getASTContext(); }
 
-  AnalysisManager &getAnalysisManager() const { return AMgr; }
+  virtual AnalysisManager &getAnalysisManager() { return AMgr; }
 
   SValuator &getSValuator() { return SVator; }
 
@@ -204,8 +213,7 @@ public:
   ///  making assumptions about state values.
   const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
 
-  GRStateManager& getStateManager() { return StateMgr; }
-  const GRStateManager& getStateManager() const { return StateMgr; }
+  virtual GRStateManager& getStateManager() { return StateMgr; }
 
   StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
 
index 67a2caf06a13bd40a8cafc042567a2058bf56da2..2787976e743f74461cc421125ec6005c7a241dd3 100644 (file)
@@ -452,6 +452,10 @@ public:
                                     const StackFrameContext *LCtx,
                                     SymbolReaper& SymReaper);
 
+  /// Marshal a new state for the callee in another translation unit.
+  /// 'state' is owned by the caller's engine.
+  const GRState *MarshalState(const GRState *state, const LocationContext *L);
+
 public:
 
   SVal ArrayToPointer(Loc Array) {
index 535ffe288ce2e0044e5368d6e73615045c43c415..90f479835910fe883c7de128bd044ef42ea78064 100644 (file)
@@ -39,7 +39,9 @@ public:
 
   virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
 
-  virtual GRStateManager& getStateManager() = 0;
+  virtual AnalysisManager &getAnalysisManager() = 0;
+
+  virtual GRStateManager &getStateManager() = 0;
 
   /// Called by GRCoreEngine. Used to generate new successor
   /// nodes by processing the 'effects' of a block-level statement.
index b86ba3ee8a581ac4982b53aee2803c8e862f4d45..0099d630f164907a05b0506624ba4180d5e3965a 100644 (file)
@@ -16,6 +16,7 @@
 
 namespace clang {
   class ASTContext;
+  class Diagnostic;
   class Preprocessor;
 
 namespace idx {
@@ -28,6 +29,7 @@ public:
   virtual ~TranslationUnit();
   virtual ASTContext &getASTContext() = 0;
   virtual Preprocessor &getPreprocessor() = 0;
+  virtual Diagnostic &getDiagnostic() = 0;
   virtual DeclReferenceMap &getDeclReferenceMap() = 0;
   virtual SelectorMap &getSelectorMap() = 0;
 };
index 538d559c16cd3bee72bd096d95df1fcf92cf40e9..4a7c60d4cc9136093298adf0f40fdd0d598efea7 100644 (file)
@@ -84,7 +84,7 @@ LiveVariables *AnalysisContext::getLiveVariables() {
 }
 
 AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
-                                               const idx::TranslationUnit *TU) {
+                                                    idx::TranslationUnit *TU) {
   AnalysisContext *&AC = Contexts[D];
   if (!AC)
     AC = new AnalysisContext(D, TU);
index a457b37ee1d5674322fb92b75bb3251d36ff9567..b0be7096615d2f2b6c6c9ff094ffce51f35c014c 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
 #include "clang/Checker/PathSensitive/GRCoreEngine.h"
 #include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/Index/TranslationUnit.h"
 #include "clang/AST/Expr.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/DenseMap.h"
@@ -24,6 +26,12 @@ using llvm::cast;
 using llvm::isa;
 using namespace clang;
 
+// This should be removed in the future.
+namespace clang {
+GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+                                  const LangOptions& lopts);
+}
+
 //===----------------------------------------------------------------------===//
 // Worklist classes for exploration of reachable states.
 //===----------------------------------------------------------------------===//
@@ -120,7 +128,8 @@ GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
 //===----------------------------------------------------------------------===//
 
 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
-bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
+bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
+                                   const GRState *InitState) {
 
   if (G->num_roots() == 0) { // Initialize the analysis by constructing
     // the root if none exists.
@@ -143,8 +152,11 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
     // Set the current block counter to being empty.
     WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
 
-    // Generate the root.
-    GenerateNode(StartLoc, getInitialState(L), 0);
+    if (!InitState)
+      // Generate the root.
+      GenerateNode(StartLoc, getInitialState(L), 0);
+    else
+      GenerateNode(StartLoc, InitState, 0);
   }
 
   while (Steps && WList->hasWork()) {
@@ -192,6 +204,17 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
   return WList->hasWork();
 }
 
+void GRCoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, 
+                                                   unsigned Steps,
+                                                   const GRState *InitState, 
+                                                   ExplodedNodeSet &Dst) {
+  ExecuteWorkList(L, Steps, InitState);
+  for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(), 
+                                           E = G->EndNodes.end(); I != E; ++I) {
+    Dst.Add(*I);
+  }
+}
+
 void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
                                    unsigned Index, ExplodedNode *Pred) {
   GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), 
@@ -662,7 +685,53 @@ void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
   // Check if the callee is in the same translation unit.
   if (CalleeCtx->getTranslationUnit() != 
       Pred->getLocationContext()->getTranslationUnit()) {
-    assert(0 && "to be implemented");
+    // Create a new engine. We must be careful that the new engine should not
+    // reference data structures owned by the old engine.
+
+    AnalysisManager &OldMgr = Eng.SubEngine.getAnalysisManager();
+    
+    // Get the callee's translation unit.
+    idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
+
+    // Create a new AnalysisManager with components of the callee's
+    // TranslationUnit.
+    // The Diagnostic is actually shared when we create ASTUnits from PCH files.
+    AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), 
+                         OldMgr.getLangOptions(), 
+                         OldMgr.getPathDiagnosticClient(),
+                         OldMgr.getStoreManagerCreator(),
+                         OldMgr.getConstraintManagerCreator(),
+                         OldMgr.getIndexer(),
+                         OldMgr.getMaxNodes(), OldMgr.getMaxLoop(),
+                         OldMgr.shouldVisualizeGraphviz(),
+                         OldMgr.shouldVisualizeUbigraph(),
+                         OldMgr.shouldPurgeDead(),
+                         OldMgr.shouldEagerlyAssume(),
+                         OldMgr.shouldTrimGraph(),
+                         OldMgr.shouldInlineCall());
+    llvm::OwningPtr<GRTransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
+                                                         /* GCEnabled */ false,
+                                                        AMgr.getLangOptions()));
+    // Create the new engine.
+    GRExprEngine NewEng(AMgr, TF.take());
+
+    // Create the new LocationContext.
+    AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(), 
+                                               CalleeCtx->getTranslationUnit());
+    const StackFrameContext *OldLocCtx = cast<StackFrameContext>(LocCtx);
+    const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, 
+                                               OldLocCtx->getParent(),
+                                               OldLocCtx->getCallSite(),
+                                               OldLocCtx->getCallSiteBlock(), 
+                                               OldLocCtx->getIndex());
+
+    // Now create an initial state for the new engine.
+    const GRState *NewState = NewEng.getStateManager().MarshalState(state,
+                                                                    NewLocCtx);
+    ExplodedNodeSet ReturnNodes;
+    NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(), 
+                                           NewState, ReturnNodes);
+    return;
   }
 
   // Get the callee entry block.
index 9e584b56148ccd88b1ba555315cdd38e39dc5176..67b3dfe0b653cba8bec6fcf925e1138fea0bb6f1 100644 (file)
@@ -57,6 +57,17 @@ GRStateManager::RemoveDeadBindings(const GRState* state,
   return ConstraintMgr->RemoveDeadBindings(s, SymReaper);
 }
 
+const GRState *GRStateManager::MarshalState(const GRState *state,
+                                            const LocationContext *InitLoc) {
+  // make up an empty state for now.
+  GRState State(this,
+                EnvMgr.getInitialEnvironment(),
+                StoreMgr->getInitialStore(InitLoc),
+                GDMFactory.GetEmptyMap());
+
+  return getPersistentState(State);
+}
+
 const GRState *GRState::unbindLoc(Loc LV) const {
   Store OldStore = getStore();
   Store NewStore = getStateManager().StoreMgr->Remove(OldStore, LV);