From: Marcin Swiderski Date: Fri, 29 Oct 2010 05:21:47 +0000 (+0000) Subject: Added CFGTerminator class, that holds information about CFGBlock terminator statement. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4ba72a0b28135209c435630682febe1f854ccfa6;p=clang Added CFGTerminator class, that holds information about CFGBlock terminator statement. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117642 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 86acb58c50..1e4692ea76 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -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 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. /// It consists of: /// @@ -279,7 +309,7 @@ class CFGBlock { /// Terminator - The terminator for a basic block that /// indicates the type of control-flow that occurs between a block /// and its successors. - Stmt *Terminator; + CFGTerminator Terminator; /// 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 @@ -422,8 +452,8 @@ public: void setLabel(Stmt* Statement) { Label = Statement; } void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } - Stmt* getTerminator() { return Terminator; } - const Stmt* getTerminator() const { return Terminator; } + CFGTerminator getTerminator() { return Terminator; } + const CFGTerminator getTerminator() const { return Terminator; } Stmt* getTerminatorCondition(); @@ -639,6 +669,22 @@ private: namespace llvm { +/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from +/// CFGTerminator to a specific Stmt class. +template <> struct simplify_type { + 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(Val.getStmt()); + } +}; + // Traits for: CFGBlock template <> struct GraphTraits< ::clang::CFGBlock* > { diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 3653500f92..527d0eb870 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -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 // CaseStmt then filter this edge. if (const SwitchStmt *S = - dyn_cast_or_null(From->getTerminator())) { + dyn_cast_or_null(From->getTerminator().getStmt())) { if (S->isAllEnumCasesCovered()) { const Stmt *L = To->getLabel(); if (!L || !isa(L)) @@ -2834,7 +2834,7 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg, CFGBlockTerminatorPrint TPrinter(OS, Helper, PrintingPolicy(Helper->getLangOpts())); - TPrinter.Visit(const_cast(B.getTerminator())); + TPrinter.Visit(const_cast(B.getTerminator().getStmt())); OS << '\n'; } @@ -2916,11 +2916,11 @@ void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, void CFGBlock::printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const { CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); - TPrinter.Visit(const_cast(getTerminator())); + TPrinter.Visit(const_cast(getTerminator().getStmt())); } Stmt* CFGBlock::getTerminatorCondition() { - + Stmt *Terminator = this->Terminator; if (!Terminator) return NULL; @@ -2974,7 +2974,7 @@ Stmt* CFGBlock::getTerminatorCondition() { } bool CFGBlock::hasBinaryBranchTerminator() const { - + const Stmt *Terminator = this->Terminator; if (!Terminator) return false; diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 00882641db..1abfde2310 100644 --- a/lib/Analysis/ReachableCode.cpp +++ b/lib/Analysis/ReachableCode.cpp @@ -244,7 +244,8 @@ void FindUnreachableCode(AnalysisContext &AC, Callback &CB) { CFGBlock &b = **I; if (!reachable[b.getBlockID()]) { if (b.pred_empty()) { - if (!AddEHEdges && dyn_cast_or_null(b.getTerminator())) { + if (!AddEHEdges + && dyn_cast_or_null(b.getTerminator().getStmt())) { // When not adding EH edges from calls, catch clauses // can otherwise seem dead. Avoid noting them as dead. numReachable += ScanReachableFromBlock(b, reachable);