diff options
-rw-r--r-- | include/clang/Analysis/CFG.h | 4 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 32 |
2 files changed, 34 insertions, 2 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 57f980ef4c..ee0be736dd 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -601,6 +601,7 @@ public: bool AddInitializers; bool AddImplicitDtors; bool AddTemporaryDtors; + bool AddStaticInitBranches; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -621,7 +622,8 @@ public: ,AddEHEdges(false) ,AddInitializers(false) ,AddImplicitDtors(false) - ,AddTemporaryDtors(false) {} + ,AddTemporaryDtors(false) + ,AddStaticInitBranches(false) {} }; /// \brief Provides a custom implementation of the iterator class to have the diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index f20f84c5c0..f436ef3f6a 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1653,10 +1653,24 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { bool IsReference = false; bool HasTemporaries = false; + // Guard static initializers under a branch. + CFGBlock *blockBeforeInit = 0; + // Destructors of temporaries in initialization expression should be called // after initialization finishes. Expr *Init = VD->getInit(); if (Init) { + if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) { + // For static variables, we need to create a branch to track + // whether or not they are initialized. + if (Block) { + Succ = Block; + if (badCFG) + return 0; + } + blockBeforeInit = Succ; + } + IsReference = VD->getType()->isReferenceType(); HasTemporaries = isa<ExprWithCleanups>(Init); @@ -1700,7 +1714,18 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { if (ScopePos && VD == *ScopePos) ++ScopePos; - return Block ? Block : LastBlock; + CFGBlock *B = Block ? Block : LastBlock; + if (blockBeforeInit) { + Succ = B; + Block = 0; + CFGBlock *branchBlock = createBlock(false); + branchBlock->setTerminator(DS); + addSuccessor(branchBlock, blockBeforeInit); + addSuccessor(branchBlock, B); + B = branchBlock; + } + + return B; } CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { @@ -3642,6 +3667,11 @@ public: Terminator->printPretty(OS, Helper, Policy); } + void VisitDeclStmt(DeclStmt *DS) { + VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + OS << "static init " << VD->getName(); + } + void VisitForStmt(ForStmt *F) { OS << "for (" ; if (F->getInit()) |