CFG objects now internally store a (lazily created) map from block-level
expressions to IDs. This is used by various dataflow analyses, but is
also useful for anyone querying a CFG to determine where an expression
is evaluated.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42495 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/CFG.cpp b/AST/CFG.cpp
index acda71e..3755fa6 100644
--- a/AST/CFG.cpp
+++ b/AST/CFG.cpp
@@ -315,7 +315,7 @@
Block->appendStmt(B);
addStmt(B->getRHS());
return addStmt(B->getLHS());
- }
+ }
// Fall through to the default case.
}
@@ -929,7 +929,55 @@
/// reverseStmts - Reverses the orders of statements within a CFGBlock.
void CFGBlock::reverseStmts() { std::reverse(Stmts.begin(),Stmts.end()); }
+//===----------------------------------------------------------------------===//
+// CFG: Queries for BlkExprs.
+//===----------------------------------------------------------------------===//
+namespace {
+ typedef llvm::DenseMap<const Expr*,unsigned> BlkExprMapTy;
+}
+
+static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
+ BlkExprMapTy* M = new BlkExprMapTy();
+
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
+ for (CFGBlock::iterator BI=I->begin(), EI=I->end(); BI != EI; ++BI)
+ if (const Expr* E = dyn_cast<Expr>(*BI))
+ (*M)[E] = M->size();
+
+ return M;
+}
+
+bool CFG::isBlkExpr(const Stmt* S) {
+ if (const Expr* E = dyn_cast<Expr>(S)) return getBlkExprNum(E);
+ else return true; // Statements are by default "block-level expressions."
+}
+
+CFG::BlkExprNumTy CFG::getBlkExprNum(const Expr* E) {
+ if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); }
+
+ BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
+ BlkExprMapTy::iterator I = M->find(E);
+
+ if (I == M->end()) return CFG::BlkExprNumTy();
+ else return CFG::BlkExprNumTy(I->second);
+}
+
+unsigned CFG::getNumBlkExprs() {
+ if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap))
+ return M->size();
+ else {
+ // We assume callers interested in the number of BlkExprs will want
+ // the map constructed if it doesn't already exist.
+ BlkExprMap = (void*) PopulateBlkExprMap(*this);
+ return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size();
+ }
+}
+
+CFG::~CFG() {
+ delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap);
+}
+
//===----------------------------------------------------------------------===//
// CFG pretty printing
//===----------------------------------------------------------------------===//