From: Ted Kremenek Date: Thu, 13 Mar 2008 03:04:22 +0000 (+0000) Subject: Added bandaid support in CFG construction for ObjCForEachStmt and ObjCAtTryStmt: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4102af916d52310c3deedd84d6fd5e2fd3c09bfe;p=clang Added bandaid support in CFG construction for ObjCForEachStmt and ObjCAtTryStmt: 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 --- diff --git a/AST/CFG.cpp b/AST/CFG.cpp index da8159cdfe..9bafb05daf 100644 --- a/AST/CFG.cpp +++ b/AST/CFG.cpp @@ -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; diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index a24cd0478e..1e40495815 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -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"; } //===----------------------------------------------------------------------===//