forked from OSchip/llvm-project
Added CFGTerminator class, that holds information about CFGBlock terminator statement.
llvm-svn: 117642
This commit is contained in:
parent
93aa84e83b
commit
a7d84a7615
|
@ -205,6 +205,36 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// CFGTerminator - Represents CFGBlock terminator statement.
|
||||||
|
///
|
||||||
|
/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
|
||||||
|
/// in control flow of destructors of temporaries. In this case terminator
|
||||||
|
/// statement is the same statement that branches control flow in evaluation
|
||||||
|
/// of matching full expression.
|
||||||
|
class CFGTerminator {
|
||||||
|
llvm::PointerIntPair<Stmt *, 1> Data;
|
||||||
|
public:
|
||||||
|
CFGTerminator() {}
|
||||||
|
CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
|
||||||
|
: Data(S, TemporaryDtorsBranch) {}
|
||||||
|
|
||||||
|
Stmt *getStmt() { return Data.getPointer(); }
|
||||||
|
const Stmt *getStmt() const { return Data.getPointer(); }
|
||||||
|
|
||||||
|
bool isTemporaryDtorsBranch() const { return Data.getInt(); }
|
||||||
|
|
||||||
|
operator Stmt *() { return getStmt(); }
|
||||||
|
operator const Stmt *() const { return getStmt(); }
|
||||||
|
|
||||||
|
Stmt *operator->() { return getStmt(); }
|
||||||
|
const Stmt *operator->() const { return getStmt(); }
|
||||||
|
|
||||||
|
Stmt &operator*() { return *getStmt(); }
|
||||||
|
const Stmt &operator*() const { return *getStmt(); }
|
||||||
|
|
||||||
|
operator bool() const { return getStmt(); }
|
||||||
|
};
|
||||||
|
|
||||||
/// CFGBlock - Represents a single basic block in a source-level CFG.
|
/// CFGBlock - Represents a single basic block in a source-level CFG.
|
||||||
/// It consists of:
|
/// It consists of:
|
||||||
///
|
///
|
||||||
|
@ -279,7 +309,7 @@ class CFGBlock {
|
||||||
/// Terminator - The terminator for a basic block that
|
/// Terminator - The terminator for a basic block that
|
||||||
/// indicates the type of control-flow that occurs between a block
|
/// indicates the type of control-flow that occurs between a block
|
||||||
/// and its successors.
|
/// and its successors.
|
||||||
Stmt *Terminator;
|
CFGTerminator Terminator;
|
||||||
|
|
||||||
/// LoopTarget - Some blocks are used to represent the "loop edge" to
|
/// LoopTarget - Some blocks are used to represent the "loop edge" to
|
||||||
/// the start of a loop from within the loop body. This Stmt* will be
|
/// the start of a loop from within the loop body. This Stmt* will be
|
||||||
|
@ -422,8 +452,8 @@ public:
|
||||||
void setLabel(Stmt* Statement) { Label = Statement; }
|
void setLabel(Stmt* Statement) { Label = Statement; }
|
||||||
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
|
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
|
||||||
|
|
||||||
Stmt* getTerminator() { return Terminator; }
|
CFGTerminator getTerminator() { return Terminator; }
|
||||||
const Stmt* getTerminator() const { return Terminator; }
|
const CFGTerminator getTerminator() const { return Terminator; }
|
||||||
|
|
||||||
Stmt* getTerminatorCondition();
|
Stmt* getTerminatorCondition();
|
||||||
|
|
||||||
|
@ -639,6 +669,22 @@ private:
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
|
||||||
|
/// CFGTerminator to a specific Stmt class.
|
||||||
|
template <> struct simplify_type<const ::clang::CFGTerminator> {
|
||||||
|
typedef const ::clang::Stmt *SimpleType;
|
||||||
|
static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
|
||||||
|
return Val.getStmt();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct simplify_type< ::clang::CFGTerminator> {
|
||||||
|
typedef ::clang::Stmt *SimpleType;
|
||||||
|
static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
|
||||||
|
return const_cast<SimpleType>(Val.getStmt());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Traits for: CFGBlock
|
// Traits for: CFGBlock
|
||||||
|
|
||||||
template <> struct GraphTraits< ::clang::CFGBlock* > {
|
template <> struct GraphTraits< ::clang::CFGBlock* > {
|
||||||
|
|
|
@ -2455,7 +2455,7 @@ bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
|
||||||
// If the 'To' has no label or is labeled but the label isn't a
|
// If the 'To' has no label or is labeled but the label isn't a
|
||||||
// CaseStmt then filter this edge.
|
// CaseStmt then filter this edge.
|
||||||
if (const SwitchStmt *S =
|
if (const SwitchStmt *S =
|
||||||
dyn_cast_or_null<SwitchStmt>(From->getTerminator())) {
|
dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) {
|
||||||
if (S->isAllEnumCasesCovered()) {
|
if (S->isAllEnumCasesCovered()) {
|
||||||
const Stmt *L = To->getLabel();
|
const Stmt *L = To->getLabel();
|
||||||
if (!L || !isa<CaseStmt>(L))
|
if (!L || !isa<CaseStmt>(L))
|
||||||
|
@ -2834,7 +2834,7 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
|
||||||
|
|
||||||
CFGBlockTerminatorPrint TPrinter(OS, Helper,
|
CFGBlockTerminatorPrint TPrinter(OS, Helper,
|
||||||
PrintingPolicy(Helper->getLangOpts()));
|
PrintingPolicy(Helper->getLangOpts()));
|
||||||
TPrinter.Visit(const_cast<Stmt*>(B.getTerminator()));
|
TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt()));
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2916,11 +2916,11 @@ void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg,
|
||||||
void CFGBlock::printTerminator(llvm::raw_ostream &OS,
|
void CFGBlock::printTerminator(llvm::raw_ostream &OS,
|
||||||
const LangOptions &LO) const {
|
const LangOptions &LO) const {
|
||||||
CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
|
CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
|
||||||
TPrinter.Visit(const_cast<Stmt*>(getTerminator()));
|
TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt* CFGBlock::getTerminatorCondition() {
|
Stmt* CFGBlock::getTerminatorCondition() {
|
||||||
|
Stmt *Terminator = this->Terminator;
|
||||||
if (!Terminator)
|
if (!Terminator)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -2974,7 +2974,7 @@ Stmt* CFGBlock::getTerminatorCondition() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFGBlock::hasBinaryBranchTerminator() const {
|
bool CFGBlock::hasBinaryBranchTerminator() const {
|
||||||
|
const Stmt *Terminator = this->Terminator;
|
||||||
if (!Terminator)
|
if (!Terminator)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,8 @@ void FindUnreachableCode(AnalysisContext &AC, Callback &CB) {
|
||||||
CFGBlock &b = **I;
|
CFGBlock &b = **I;
|
||||||
if (!reachable[b.getBlockID()]) {
|
if (!reachable[b.getBlockID()]) {
|
||||||
if (b.pred_empty()) {
|
if (b.pred_empty()) {
|
||||||
if (!AddEHEdges && dyn_cast_or_null<CXXTryStmt>(b.getTerminator())) {
|
if (!AddEHEdges
|
||||||
|
&& dyn_cast_or_null<CXXTryStmt>(b.getTerminator().getStmt())) {
|
||||||
// When not adding EH edges from calls, catch clauses
|
// When not adding EH edges from calls, catch clauses
|
||||||
// can otherwise seem dead. Avoid noting them as dead.
|
// can otherwise seem dead. Avoid noting them as dead.
|
||||||
numReachable += ScanReachableFromBlock(b, reachable);
|
numReachable += ScanReachableFromBlock(b, reachable);
|
||||||
|
|
Loading…
Reference in New Issue