[cfe-commits] r93840 - /cfe/trunk/lib/Analysis/CFG.cpp

Mike Stump mrs at apple.com
Mon Jan 18 18:20:09 PST 2010


Author: mrs
Date: Mon Jan 18 20:20:09 2010
New Revision: 93840

URL: http://llvm.org/viewvc/llvm-project?rev=93840&view=rev
Log:
Add try/catch CFG support.  Also improve throw CFG support.  WIP.

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=93840&r1=93839&r2=93840&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Mon Jan 18 20:20:09 2010
@@ -70,6 +70,7 @@
   CFGBlock* BreakTargetBlock;
   CFGBlock* SwitchTerminatedBlock;
   CFGBlock* DefaultCaseBlock;
+  CFGBlock* TryTerminatedBlock;
 
   // LabelMap records the mapping from Label expressions to their blocks.
   typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
@@ -88,7 +89,8 @@
   explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
                           Block(NULL), Succ(NULL),
                           ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
-                          SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {}
+                          SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
+                          TryTerminatedBlock(NULL) {}
 
   // buildCFG - Used by external clients to construct the CFG.
   CFG* buildCFG(Stmt *Statement, ASTContext *C);
@@ -106,9 +108,9 @@
   CFGBlock *VisitConditionalOperator(ConditionalOperator *C,
                                      AddStmtChoice asc);
   CFGBlock *VisitContinueStmt(ContinueStmt *C);
-  CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S) { return NYS(); }
+  CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
   CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
-  CFGBlock *VisitCXXTryStmt(CXXTryStmt *S) { return NYS(); }  
+  CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
   CFGBlock *VisitDeclStmt(DeclStmt *DS);
   CFGBlock *VisitDeclSubExpr(Decl* D);
   CFGBlock *VisitDefaultStmt(DefaultStmt *D);
@@ -390,6 +392,12 @@
     case Stmt::SwitchStmtClass:
       return VisitSwitchStmt(cast<SwitchStmt>(S));
 
+    case Stmt::CXXTryStmtClass:
+      return VisitCXXTryStmt(cast<CXXTryStmt>(S));
+
+    case Stmt::CXXCatchStmtClass:
+      return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
+
     case Stmt::WhileStmtClass:
       return VisitWhileStmt(cast<WhileStmt>(S));
   }
@@ -923,8 +931,8 @@
 
     // Save the current values for Block, Succ, and continue and break targets
     SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-    save_continue(ContinueTargetBlock),
-    save_break(BreakTargetBlock);
+      save_continue(ContinueTargetBlock),
+      save_break(BreakTargetBlock);
 
     // Create a new block to contain the (bottom) of the loop body.
     Block = NULL;
@@ -1252,8 +1260,12 @@
   // Create the new block.
   Block = createBlock(false);
 
-  // The Exit block is the only successor.
-  AddSuccessor(Block, &cfg->getExit());
+  if (TryTerminatedBlock)
+    // The current try statement is the only successor.
+    AddSuccessor(Block, TryTerminatedBlock);
+  else 
+    // otherwise the Exit block is the only successor.
+    AddSuccessor(Block, &cfg->getExit());
 
   // Add the statement to the block.  This may create new blocks if S contains
   // control-flow (short-circuit operations).
@@ -1305,8 +1317,8 @@
 
     // Save the current values for Block, Succ, and continue and break targets
     SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-    save_continue(ContinueTargetBlock),
-    save_break(BreakTargetBlock);
+      save_continue(ContinueTargetBlock),
+      save_break(BreakTargetBlock);
 
     // All continues within this loop should go to the condition block
     ContinueTargetBlock = EntryConditionBlock;
@@ -1528,6 +1540,74 @@
   return DefaultCaseBlock;
 }
 
+CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
+  // "try"/"catch" is a control-flow statement.  Thus we stop processing the
+  // current block.
+  CFGBlock* TrySuccessor = NULL;
+
+  if (Block) {
+    if (!FinishBlock(Block))
+      return 0;
+    TrySuccessor = Block;
+  } else TrySuccessor = Succ;
+
+  // Save the current "try" context.
+  SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock);
+
+  // Create a new block that will contain the try statement.
+  TryTerminatedBlock = createBlock(false);
+  // Add the terminator in the try block.
+  TryTerminatedBlock->setTerminator(Terminator);
+
+  for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
+    // The code after the try is the implicit successor.
+    Succ = TrySuccessor;
+    CXXCatchStmt *CS = Terminator->getHandler(h);
+    Block = NULL;
+    CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
+    if (CatchBlock == 0)
+      return 0;
+    // Add this block to the list of successors for the block with the try
+    // statement.
+    AddSuccessor(TryTerminatedBlock, CatchBlock);
+  }
+
+  // The code after the try is the implicit successor.
+  Succ = TrySuccessor;
+
+  // When visiting the body, the case statements should automatically get linked
+  // up to the try.
+  assert (Terminator->getTryBlock() && "try must contain a non-NULL body");
+  Block = NULL;
+  CFGBlock *BodyBlock = addStmt(Terminator->getTryBlock());
+
+  Block = BodyBlock;
+  
+  return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
+  // CXXCatchStmt are treated like labels, so they are the first statement in a
+  // block.
+
+  if (CS->getHandlerBlock())
+    addStmt(CS->getHandlerBlock());
+
+  CFGBlock* CatchBlock = Block;
+  if (!CatchBlock)
+    CatchBlock = createBlock();
+
+  CatchBlock->setLabel(CS);
+
+  if (!FinishBlock(CatchBlock))
+    return 0;
+
+  // We set Block to NULL to allow lazy creation of a new block (if necessary)
+  Block = NULL;
+
+  return CatchBlock;
+}
+
 CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
   // Lazily create the indirect-goto dispatch block if there isn't one already.
   CFGBlock* IBlock = cfg->getIndirectGotoBlock();
@@ -1782,6 +1862,10 @@
     Terminator->getCond()->printPretty(OS, Helper, Policy);
   }
 
+  void VisitCXXTryStmt(CXXTryStmt* CS) {
+    OS << "try ...";
+  }
+
   void VisitConditionalOperator(ConditionalOperator* C) {
     C->getCond()->printPretty(OS, Helper, Policy);
     OS << " ? ... : ...";
@@ -1894,7 +1978,13 @@
       }
     } else if (isa<DefaultStmt>(Terminator))
       OS << "default";
-    else
+    else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Terminator)) {
+      OS << "catch (";
+      CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()),
+        0);
+      OS << ")";
+
+    } else
       assert(false && "Invalid label statement in CFGBlock.");
 
     OS << ":\n";





More information about the cfe-commits mailing list