aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-03-13 03:04:22 +0000
committerTed Kremenek <kremenek@apple.com>2008-03-13 03:04:22 +0000
commit4102af916d52310c3deedd84d6fd5e2fd3c09bfe (patch)
tree3aeaaa8cb8b105dc1e44c157423f56fb8d2eebf6
parent5518e7caf365158c5a03fc34d0d05d5a4981fa05 (diff)
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
-rw-r--r--AST/CFG.cpp21
-rw-r--r--Driver/ASTConsumers.cpp9
2 files changed, 28 insertions, 2 deletions
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";
}
//===----------------------------------------------------------------------===//