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
This commit is contained in:
Ted Kremenek 2007-10-01 19:33:33 +00:00
Родитель 980e508ca7
Коммит 63f5887f31
2 изменённых файлов: 71 добавлений и 4 удалений

Просмотреть файл

@ -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<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
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -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