diff --git a/AST/CFG.cpp b/AST/CFG.cpp index acda71ef42..3755fa6369 100644 --- a/AST/CFG.cpp +++ b/AST/CFG.cpp @@ -315,7 +315,7 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* S, bool AlwaysAddStmt = false) { Block->appendStmt(B); addStmt(B->getRHS()); return addStmt(B->getLHS()); - } + } // Fall through to the default case. } @@ -929,7 +929,55 @@ CFG* CFG::buildCFG(Stmt* Statement) { /// 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 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(*BI)) + (*M)[E] = M->size(); + + return M; +} + +bool CFG::isBlkExpr(const Stmt* S) { + if (const Expr* E = dyn_cast(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(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(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(BlkExprMap)->size(); + } +} + +CFG::~CFG() { + delete reinterpret_cast(BlkExprMap); +} + //===----------------------------------------------------------------------===// // CFG pretty printing //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h index e50c3cc906..113ee87613 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 @@ public: // 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 @@ public: // 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 @@ private: 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