r178318 - Add static analyzer support for conditionally executing static initializers.

Ted Kremenek kremenek at apple.com
Thu Mar 28 17:09:29 PDT 2013


Author: kremenek
Date: Thu Mar 28 19:09:28 2013
New Revision: 178318

URL: http://llvm.org/viewvc/llvm-project?rev=178318&view=rev
Log:
Add static analyzer support for conditionally executing static initializers.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/test/Analysis/analyzer-config.c
    cfe/trunk/test/Analysis/analyzer-config.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h Thu Mar 28 19:09:28 2013
@@ -96,6 +96,10 @@ private:
   void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
                     ExplodedNode *Pred);
 
+  /// Handle conditional logic for running static initializers.
+  void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
+                        ExplodedNode *Pred);
+
 private:
   CoreEngine(const CoreEngine &) LLVM_DELETED_FUNCTION;
   void operator=(const CoreEngine &) LLVM_DELETED_FUNCTION;

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=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Thu Mar 28 19:09:28 2013
@@ -224,6 +224,15 @@ public:
                      const CFGBlock *DstT,
                      const CFGBlock *DstF);
 
+  /// Called by CoreEngine.  Used to processing branching behavior
+  /// at static initalizers.
+  void processStaticInitializer(const DeclStmt *DS,
+                                NodeBuilderContext& BuilderCtx,
+                                ExplodedNode *Pred,
+                                ExplodedNodeSet &Dst,
+                                const CFGBlock *DstT,
+                                const CFGBlock *DstF);
+
   /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a computed goto jump.
   void processIndirectGoto(IndirectGotoNodeBuilder& builder);

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=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Thu Mar 28 19:09:28 2013
@@ -72,6 +72,15 @@ public:
                              const CFGBlock *DstT,
                              const CFGBlock *DstF) = 0;
 
+  /// Called by CoreEngine.  Used to processing branching behavior
+  /// at static initalizers.
+  virtual void processStaticInitializer(const DeclStmt *DS,
+                                        NodeBuilderContext& BuilderCtx,
+                                        ExplodedNode *Pred,
+                                        ExplodedNodeSet &Dst,
+                                        const CFGBlock *DstT,
+                                        const CFGBlock *DstF) = 0;
+
   /// Called by CoreEngine.  Used to generate successor
   /// nodes by processing the 'effects' of a computed goto jump.
   virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0;

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Thu Mar 28 19:09:28 2013
@@ -1665,6 +1665,7 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(D
       // whether or not they are initialized.
       if (Block) {
         Succ = Block;
+        Block = 0;
         if (badCFG)
           return 0;
       }
@@ -1714,15 +1715,14 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(D
   if (ScopePos && VD == *ScopePos)
     ++ScopePos;
 
-  CFGBlock *B = Block ? Block : LastBlock;
+  CFGBlock *B = LastBlock;
   if (blockBeforeInit) {
     Succ = B;
-    Block = 0;
-    CFGBlock *branchBlock = createBlock(false);
-    branchBlock->setTerminator(DS);
-    addSuccessor(branchBlock, blockBeforeInit);
-    addSuccessor(branchBlock, B);
-    B = branchBlock;
+    Block = createBlock(false);
+    Block->setTerminator(DS);
+    addSuccessor(Block, blockBeforeInit);
+    addSuccessor(Block, B);
+    B = Block;
   }
 
   return B;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Thu Mar 28 19:09:28 2013
@@ -238,6 +238,6 @@ bool AnalyzerOptions::shouldPrunePaths()
 }
 
 bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
-  return getBooleanOption("conditional-static-initializers", false);
+  return getBooleanOption("cfg-conditional-static-initializers", true);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Thu Mar 28 19:09:28 2013
@@ -346,6 +346,11 @@ void CoreEngine::HandleBlockExit(const C
       default:
         llvm_unreachable("Analysis for this terminator not implemented.");
 
+      // Model static initializers.
+      case Stmt::DeclStmtClass:
+        HandleStaticInit(cast<DeclStmt>(Term), B, Pred);
+        return;
+
       case Stmt::BinaryOperatorClass: // '&&' and '||'
         HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
         return;
@@ -456,6 +461,19 @@ void CoreEngine::HandleBranch(const Stmt
   enqueue(Dst);
 }
 
+
+void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
+                                  ExplodedNode *Pred) {
+  assert(B->succ_size() == 2);
+  NodeBuilderContext Ctx(*this, B, Pred);
+  ExplodedNodeSet Dst;
+  SubEng.processStaticInitializer(DS, Ctx, Pred, Dst,
+                                  *(B->succ_begin()), *(B->succ_begin()+1));
+  // Enqueue the new frontier onto the worklist.
+  enqueue(Dst);
+}
+
+
 void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, 
                                   ExplodedNode *Pred) {
   assert(B);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Mar 28 19:09:28 2013
@@ -1344,6 +1344,34 @@ void ExprEngine::processBranch(const Stm
   currBldrCtx = 0;
 }
 
+/// The GDM component containing the set of global variables which have been
+/// previously initialized with explicit initializers.
+REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
+                                 llvm::ImmutableSet<const VarDecl *>)
+
+void ExprEngine::processStaticInitializer(const DeclStmt *DS,
+                                          NodeBuilderContext &BuilderCtx,
+                                          ExplodedNode *Pred,
+                                          clang::ento::ExplodedNodeSet &Dst,
+                                          const CFGBlock *DstT,
+                                          const CFGBlock *DstF) {
+  currBldrCtx = &BuilderCtx;
+
+  const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+  ProgramStateRef state = Pred->getState();
+  bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
+  BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
+
+  if (!initHasRun) {
+    state = state->add<InitializedGlobalsSet>(VD);
+  }
+
+  builder.generateNode(state, initHasRun, Pred);
+  builder.markInfeasible(!initHasRun);
+
+  currBldrCtx = 0;
+}
+
 /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a computed goto jump.
 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Mar 28 19:09:28 2013
@@ -423,11 +423,6 @@ void ExprEngine::VisitCompoundLiteralExp
     B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV));
 }
 
-/// The GDM component containing the set of global variables which have been
-/// previously initialized with explicit initializers.
-REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
-                                 llvm::ImmutableSet<const VarDecl *> )
-
 void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
                                ExplodedNodeSet &Dst) {
   // Assumption: The CFG has one DeclStmt per Decl.
@@ -438,15 +433,6 @@ void ExprEngine::VisitDeclStmt(const Dec
     Dst.insert(Pred);
     return;
   }
-
-  // Check if a value has been previously initialized. There will be an entry in
-  // the set for variables with global storage which have been previously
-  // initialized.
-  if (VD->hasGlobalStorage())
-    if (Pred->getState()->contains<InitializedGlobalsSet>(VD)) {
-      Dst.insert(Pred);
-      return;
-    }
   
   // FIXME: all pre/post visits should eventually be handled by ::Visit().
   ExplodedNodeSet dstPreVisit;
@@ -464,11 +450,6 @@ void ExprEngine::VisitDeclStmt(const Dec
 
       // Note in the state that the initialization has occurred.
       ExplodedNode *UpdatedN = N;
-      if (VD->hasGlobalStorage()) {
-        state = state->add<InitializedGlobalsSet>(VD);
-        UpdatedN = B.generateNode(DS, N, state);
-      }
-
       SVal InitVal = state->getSVal(InitEx, LC);
 
       if (isa<CXXConstructExpr>(InitEx->IgnoreImplicit())) {

Modified: cfe/trunk/test/Analysis/analyzer-config.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.c?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/analyzer-config.c (original)
+++ cfe/trunk/test/Analysis/analyzer-config.c Thu Mar 28 19:09:28 2013
@@ -5,6 +5,7 @@ void bar() {}
 void foo() { bar(); }
 
 // CHECK: [config]
+// CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-temporary-dtors = false
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
@@ -15,4 +16,5 @@ void foo() { bar(); }
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: mode = deep
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 9
+// CHECK-NEXT: num-entries = 10
+

Modified: cfe/trunk/test/Analysis/analyzer-config.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.cpp?rev=178318&r1=178317&r2=178318&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/analyzer-config.cpp (original)
+++ cfe/trunk/test/Analysis/analyzer-config.cpp Thu Mar 28 19:09:28 2013
@@ -14,6 +14,7 @@ public:
 // CHECK-NEXT: c++-inlining = constructors
 // CHECK-NEXT: c++-stdlib-inlining = true
 // CHECK-NEXT: c++-template-inlining = true
+// CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-temporary-dtors = false
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
@@ -24,4 +25,4 @@ public:
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: mode = deep
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 12
+// CHECK-NEXT: num-entries = 13





More information about the cfe-commits mailing list