]> granicus.if.org Git - clang/commitdiff
Added an (optional) explicit "Label" statement to CFGBlock. If a
authorTed Kremenek <kremenek@apple.com>
Wed, 29 Aug 2007 23:20:49 +0000 (23:20 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 29 Aug 2007 23:20:49 +0000 (23:20 +0000)
block begins with a label or case statement, CFGBlock::getLabel() will
return the corresponding LabelStmt/CaseStmt/DefaultStmt.

LabelStmts and SwitchCases no longer appear within the "executable"
statements of a CFGBlock.

More cleanups on visualization/pretty-printing of CFGs (less verbose).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41585 91177308-0d34-0410-b5e6-96231b3b80d8

AST/CFG.cpp
include/clang/AST/CFG.h

index 2d6e2409439721cd1e5eedbffc58c5542eae31a2..6e2e4dbe0e7be756312e162c04590bec81a0c98a 100644 (file)
@@ -462,11 +462,10 @@ CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
   LabelMap[ L ] = LabelBlock;
   
   // Labels partition blocks, so this is the end of the basic block
-  // we were processing (the label is the first statement).  Add the label
-  // the to end (really the beginning) of the block.  Because this is
+  // we were processing (L is the block's label).  Because this is
   // label (and we have already processed the substatement) there is no
   // extra control-flow to worry about.
-  LabelBlock->appendStmt(L);
+  LabelBlock->setLabel(L);
   FinishBlock(LabelBlock);
   
   // We set Block to NULL to allow lazy creation of a new block
@@ -808,9 +807,9 @@ CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
   CFGBlock* CaseBlock = Visit(S->getSubStmt());
   assert (CaseBlock);
   
-  // Cases/Default statements parition block, so this is the top of
-  // the basic block we were processing (the case/default is the first stmt).
-  CaseBlock->appendStmt(S);
+  // Cases/Default statements partition block, so this is the top of
+  // the basic block we were processing (the case/default is the label).
+  CaseBlock->setLabel(S);
   FinishBlock(CaseBlock);
   
   // Add this block to the list of successors for the block with the
@@ -898,8 +897,6 @@ void CFG::print(std::ostream& OS) const {
   
   // Print the exit block.
   getExit().print(OS,this);
-
-  OS << "\n";
 }
 
 namespace {
@@ -959,7 +956,7 @@ void CFGBlock::dump(const CFG* cfg) const { print(std::cerr,cfg); }
 
 /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
 ///   Generally this will only be called from CFG::print.
-void CFGBlock::print(std::ostream& OS, const CFG* cfg) const {
+void CFGBlock::print(std::ostream& OS, const CFG* cfg, bool print_edges) const {
 
   // Print the header.
   OS << "\n [ B" << getBlockID();  
@@ -970,53 +967,69 @@ void CFGBlock::print(std::ostream& OS, const CFG* cfg) const {
   }
   else OS << " ]\n";
 
+  // Print the label of this block.
+  if (Stmt* S = const_cast<Stmt*>(getLabel())) {
+    if (print_edges) OS << "    ";
+    if (LabelStmt* L = dyn_cast<LabelStmt>(S))
+      OS << L->getName();
+    else if (CaseStmt* C = dyn_cast<CaseStmt>(S)) {
+      OS << "case ";
+      C->getLHS()->printPretty(OS);
+      if (C->getRHS()) {
+        OS << " ... ";
+        C->getRHS()->printPretty(OS);
+      }
+    }
+    else if (DefaultStmt* D = dyn_cast<DefaultStmt>(D)) {
+      OS << "default";
+    }
+    else assert(false && "Invalid label statement in CFGBlock.");
+    
+    OS << ":\n";
+  }
+  
   // Iterate through the statements in the block and print them.
-  OS << "    ------------------------\n";
   unsigned j = 1;
   for (const_iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) {
-    // Print the statement # in the basic block.
-    OS << "    " << std::setw(3) << j << ": ";    
-
-    // Print the statement/expression.
-    Stmt* S = *I;
-    
-    if (LabelStmt* L = dyn_cast<LabelStmt>(S))
-      OS << L->getName() << ": (LABEL)\n";
-    else
-      (*I)->printPretty(OS);
-      
+    // Print the statement # in the basic block and the statement itself.
+    if (print_edges) OS << "    ";
+    OS << std::setw(3) << j << ": ";        
+    (*I)->printPretty(OS);
+          
     // Expressions need a newline.
     if (isa<Expr>(*I)) OS << '\n';
   }
-  OS << "    ------------------------\n";
-
-  // Print the predecessors of this block.
-  OS << "    Predecessors (" << pred_size() << "):";
-  unsigned i = 0;
-  for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) {
-    if (i == 8 || (i-8) == 0) {
-      OS << "\n     ";
-    }
-    OS << " B" << (*I)->getBlockID();
+
+  // Print the terminator of this block.
+  if (getTerminator()) {
+    if (print_edges) OS << "    ";
+    OS << "  T: ";
+    CFGBlockTerminatorPrint(OS).Visit(const_cast<Stmt*>(getTerminator()));
   }
   
-  // Print the terminator of this block.
-  OS << "\n    Terminator: ";
-  if (ControlFlowStmt)
-    CFGBlockTerminatorPrint(OS).Visit(ControlFlowStmt);
-  else
-    OS << "<NULL>\n";
-
-  // Print the successors of this block.
-  OS << "    Successors (" << succ_size() << "):";
-  i = 0;
-  for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I, ++i) {
-    if (i == 8 || (i-8) % 10 == 0) {
-      OS << "\n    ";
+  if (print_edges) {
+    // Print the predecessors of this block.
+    OS << "    Predecessors (" << pred_size() << "):";
+    unsigned i = 0;
+    for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) {
+      if (i == 8 || (i-8) == 0) {
+        OS << "\n     ";
+      }
+      OS << " B" << (*I)->getBlockID();
+    }
+    OS << '\n';
+
+    // Print the successors of this block.
+    OS << "    Successors (" << succ_size() << "):";
+    i = 0;
+    for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I, ++i) {
+      if (i == 8 || (i-8) % 10 == 0) {
+        OS << "\n    ";
+      }
+      OS << " B" << (*I)->getBlockID();
     }
-    OS << " B" << (*I)->getBlockID();
+    OS << '\n';
   }
-  OS << '\n';
 }
 
 //===----------------------------------------------------------------------===//
@@ -1029,7 +1042,7 @@ struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
   static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
 
     std::ostringstream Out;
-    Node->print(Out,Graph);
+    Node->print(Out,Graph,false);
     std::string OutStr = Out.str();
 
     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
index 18157d136301b6bb19314e53fd2af5c5e541c46a..460e23cdfcca22a4685e4758075d1be327b21c0b 100644 (file)
@@ -43,15 +43,24 @@ class CFG;
 ///     Terminator       Successor Ordering
 ///  -----------------------------------------------------
 ///       if            Then Block;  Else Block
+///     ? operator      LHS expression;  RHS expression
+///     &&, ||          expression that uses result of && or ||, RHS
 ///
 class CFGBlock {
   typedef std::vector<Stmt*> StatementListTy;
   /// Stmts - The set of statements in the basic block.
   StatementListTy Stmts;
-  /// ControlFlowStmt - The terminator for a basic block that
+
+  /// Label - An (optional) label that prefixes the executable
+  ///  statements in the block.  When this variable is non-NULL, it is
+  ///  either an instance of LabelStmt or SwitchCase.
+  Stmt* Label;
+  
+  /// Terminator - The terminator for a basic block that
   ///  indicates the type of control-flow that occurs between a block
   ///  and its successors.
-  Stmt* ControlFlowStmt;
+  Stmt* Terminator;
+  
   /// BlockID - A numerical ID assigned to a CFGBlock during construction
   ///   of the CFG.
   unsigned BlockID;
@@ -63,7 +72,7 @@ class CFGBlock {
   AdjacentBlocks Succs;
   
 public:
-  explicit CFGBlock(unsigned blockid) : ControlFlowStmt(NULL), 
+  explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
                                         BlockID(blockid) {}
   ~CFGBlock() {};
 
@@ -129,8 +138,14 @@ public:
   // Manipulation of block contents
   
   void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
-  void setTerminator(Stmt* Statement) { ControlFlowStmt = Statement; }
-  Stmt* getTerminator() { return ControlFlowStmt; }
+  void setTerminator(Stmt* Statement) { Terminator = Statement; }
+  void setLabel(Stmt* Statement) { Label = Statement; }
+
+  Stmt* getTerminator() { return Terminator; }
+  const Stmt* getTerminator() const { return Terminator; }
+  
+  Stmt* getLabel() { return Label; }
+  const Stmt* getLabel() const { return Label; }
   
   void reverseStmts();
   
@@ -142,7 +157,7 @@ public:
   unsigned getBlockID() const { return BlockID; }
   
   void dump(const CFG* cfg) const;
-  void print(std::ostream& OS, const CFG* cfg) const;
+  void print(std::ostream& OS, const CFG* cfg, bool print_edges = true) const;
 };