aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/CFG.cpp')
-rw-r--r--lib/Analysis/CFG.cpp36
1 files changed, 32 insertions, 4 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index a22a5aa033..fa054f66e2 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -282,6 +282,8 @@ class CFGBuilder {
// State to track for building switch statements.
bool switchExclusivelyCovered;
Expr::EvalResult *switchCond;
+
+ CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
public:
explicit CFGBuilder(ASTContext *astContext,
@@ -290,11 +292,14 @@ public:
Block(NULL), Succ(NULL),
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts),
- switchExclusivelyCovered(false), switchCond(0) {}
+ switchExclusivelyCovered(false), switchCond(0),
+ cachedEntry(0) {}
// buildCFG - Used by external clients to construct the CFG.
CFG* buildCFG(const Decl *D, Stmt *Statement);
+ bool alwaysAdd(const Stmt *stmt);
+
private:
// Visitors to walk an AST and construct the CFG.
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
@@ -387,6 +392,12 @@ private:
// Interface to CFGBlock - adding CFGElements.
void appendStmt(CFGBlock *B, Stmt *S) {
+ if (cachedEntry) {
+ assert(cachedEntry->first == S);
+ cachedEntry->second = B;
+ cachedEntry = 0;
+ }
+
B->appendStmt(S, cfg->getBumpVectorContext());
}
void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
@@ -443,9 +454,26 @@ private:
};
-bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
- const Stmt *stmt) const {
- return kind == AlwaysAdd;
+inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
+ const Stmt *stmt) const {
+ return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
+}
+
+bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
+ if (!BuildOpts.forcedBlkExprs)
+ return false;
+
+ CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;
+
+ if (!fb)
+ return false;
+
+ CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
+ if (itr == fb->end())
+ return false;
+
+ cachedEntry = &*itr;
+ return true;
}
// FIXME: Add support for dependent-sized array types in C++?