diff options
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r-- | lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 18 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 28 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 19 |
4 files changed, 47 insertions, 20 deletions
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 1326d0d01b..65faa10134 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -238,6 +238,6 @@ bool AnalyzerOptions::shouldPrunePaths() { } bool AnalyzerOptions::shouldConditionalizeStaticInitializers() { - return getBooleanOption("conditional-static-initializers", false); + return getBooleanOption("cfg-conditional-static-initializers", true); } diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index c61bcf7d41..b09b2c2ddf 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -346,6 +346,11 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { 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 *Cond, const Stmt *Term, 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); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8ad5a3dbde..789abb7d86 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1344,6 +1344,34 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, 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) { diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 2f2eb8628a..3a3c9713dd 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -423,11 +423,6 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 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 DeclStmt *DS, ExplodedNode *Pred, 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 DeclStmt *DS, ExplodedNode *Pred, // 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())) { |