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
//===----------------------------------------------------------------------===//
diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h
index e50c3cc..113ee87 100644
--- a/include/clang/AST/CFG.h
+++ b/include/clang/AST/CFG.h
@@ -23,6 +23,7 @@
namespace clang {
class Stmt;
+ class Expr;
class CFG;
class PrinterHelper;
@@ -263,6 +264,19 @@
// CFG Introspection.
//===--------------------------------------------------------------------===//
+ struct BlkExprNumTy {
+ const signed Idx;
+ explicit BlkExprNumTy(signed idx) : Idx(idx) {}
+ explicit BlkExprNumTy() : Idx(-1) {}
+ operator bool() const { return Idx >= 0; }
+ operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
+ };
+
+ bool isBlkExpr(const Stmt* S);
+ bool isBlkExpr(const Expr* E) { return getBlkExprNum(E); }
+ BlkExprNumTy getBlkExprNum(const Expr* E);
+ unsigned getNumBlkExprs();
+
unsigned getNumBlockIDs() const { return NumBlockIDs; }
//===--------------------------------------------------------------------===//
@@ -277,8 +291,10 @@
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
- CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0) {};
- ~CFG() {};
+ CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
+ BlkExprMap(NULL) {};
+
+ ~CFG();
private:
CFGBlock* Entry;
@@ -286,7 +302,10 @@
CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
// for indirect gotos
CFGBlockListTy Blocks;
- unsigned NumBlockIDs;
+ unsigned NumBlockIDs;
+ // opaque pointer to prevent inclusion of DenseMap.h. Map from expressions
+ // to integers to record block-level expressions.
+ void* BlkExprMap;
};
} // end namespace clang