]> granicus.if.org Git - clang/commitdiff
Added CFGTerminator class, that holds information about CFGBlock terminator statement.
authorMarcin Swiderski <marcin.sfider@gmail.com>
Fri, 29 Oct 2010 05:21:47 +0000 (05:21 +0000)
committerMarcin Swiderski <marcin.sfider@gmail.com>
Fri, 29 Oct 2010 05:21:47 +0000 (05:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117642 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/CFG.h
lib/Analysis/CFG.cpp
lib/Analysis/ReachableCode.cpp

index 86acb58c506e09c80a7448db134d957a2cf39e46..1e4692ea762fbab58a5902e44f428bc772cd51e6 100644 (file)
@@ -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.
 ///  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<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
 
 template <> struct GraphTraits< ::clang::CFGBlock* > {
index 3653500f92579079bc2c5a66d7b88dad50f6853d..527d0eb870e69e798af58224888e2e0c477c3aa3 100644 (file)
@@ -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<SwitchStmt>(From->getTerminator())) {
+  dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) {
       if (S->isAllEnumCasesCovered()) {
   const Stmt *L = To->getLabel();
   if (!L || !isa<CaseStmt>(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<Stmt*>(B.getTerminator()));
+    TPrinter.Visit(const_cast<Stmt*>(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<Stmt*>(getTerminator()));
+  TPrinter.Visit(const_cast<Stmt*>(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;
 
index 00882641dbc956966f0e7444eebc7e552f7efc9f..1abfde231083c32237345755bfb97da3680263de 100644 (file)
@@ -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<CXXTryStmt>(b.getTerminator())) {
+        if (!AddEHEdges
+        && dyn_cast_or_null<CXXTryStmt>(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);