]> granicus.if.org Git - clang/commitdiff
Added bandaid support in CFG construction for ObjCForEachStmt and ObjCAtTryStmt:
authorTed Kremenek <kremenek@apple.com>
Thu, 13 Mar 2008 03:04:22 +0000 (03:04 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 13 Mar 2008 03:04:22 +0000 (03:04 +0000)
we gracefully back out and return NULL for the CFG, allowing clients to skip
analyzing functions with these CFGs. We will add support later.

Modified base ASTConsumer "CFGVisitor" to detect when a CFG is not constructed
and to emit a warning.

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

AST/CFG.cpp
Driver/ASTConsumers.cpp

index da8159cdfed2c19e1ab309e8ca6d78d3d8d394fa..9bafb05daf4ca14470101efa03ddca0015017471 100644 (file)
@@ -113,6 +113,18 @@ public:
   CFGBlock* VisitDefaultStmt(DefaultStmt* D);
   CFGBlock* VisitIndirectGotoStmt(IndirectGotoStmt* I);
   
+  // FIXME: Add support for ObjC-specific control-flow structures.
+  
+  CFGBlock* VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+    badCFG = true;
+    return Block;
+  }
+  
+  CFGBlock* VisitObjCAtTryStmt(ObjCAtTryStmt* S) {
+    badCFG = true;
+    return Block;
+  }
+  
 private:
   CFGBlock* createBlock(bool add_successor = true);
   CFGBlock* addStmt(Stmt* S);
@@ -122,6 +134,7 @@ private:
   CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* S);
   void FinishBlock(CFGBlock* B);
   
+  bool badCFG;
 };
     
 /// BuildCFG - Constructs a CFG from an AST (a Stmt*).  The AST can
@@ -133,6 +146,8 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement) {
   assert (cfg);
   if (!Statement) return NULL;
 
+  badCFG = false;
+  
   // Create an empty block that will serve as the exit block for the CFG.
   // Since this is the first block added to the CFG, it will be implicitly
   // registered as the exit block.
@@ -186,6 +201,12 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement) {
   // Create an empty entry block that has no predecessors.    
   cfg->setEntry(createBlock());
     
+  if (badCFG) {
+    delete cfg;
+    cfg = NULL;
+    return NULL;
+  }
+    
   // NULL out cfg so that repeated calls to the builder will fail and that
   // the ownership of the constructed CFG is passed to the caller.
   CFG* t = cfg;
index a24cd0478e014bb9c32d02e1dc08726efb632e72..1e40495815c6db821208739bac58c71172d39310 100644 (file)
@@ -482,8 +482,13 @@ void CFGVisitor::HandleTopLevelDecl(Decl *D) {
   }
     
   CFG *C = CFG::buildCFG(FD->getBody());
-  VisitCFG(*C, *FD);
-  delete C;
+  
+  if (C) {  
+    VisitCFG(*C, *FD);
+    delete C;
+  }
+  else
+    llvm::cerr << "warning: CFG could not be constructed.\n";
 }
 
 //===----------------------------------------------------------------------===//