diff options
author | Mike Stump <mrs@apple.com> | 2009-07-22 22:56:04 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-07-22 22:56:04 +0000 |
commit | 0979d80615df97c675423de631c1b884819f4712 (patch) | |
tree | 18d1d588ec10fed6e56d062ecf078b61f3946c9f | |
parent | f0549e2b5c73d65ce96fc37c9030577997fe19d4 (diff) |
Improve CFG support for C++ throw expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76814 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/CFG.cpp | 21 | ||||
-rw-r--r-- | test/Analysis/dead-stores.cpp | 21 |
2 files changed, 42 insertions, 0 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 4c2ecb92f6..f43631c4d0 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -99,6 +99,7 @@ private: CFGBlock *VisitCompoundStmt(CompoundStmt *C); CFGBlock *VisitConditionalOperator(ConditionalOperator *C); CFGBlock *VisitContinueStmt(ContinueStmt *C); + CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); CFGBlock *VisitDeclStmt(DeclStmt *DS); CFGBlock *VisitDeclSubExpr(Decl* D); CFGBlock *VisitDefaultStmt(DefaultStmt *D); @@ -319,6 +320,9 @@ tryAgain: case Stmt::ObjCAtCatchStmtClass: return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); + case Stmt::CXXThrowExprClass: + return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); + case Stmt::ObjCAtSynchronizedStmtClass: return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); @@ -1262,6 +1266,23 @@ CFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { return VisitStmt(S, true); } +CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) { + // If we were in the middle of a block we stop processing that block and + // reverse its statements. + if (Block && !FinishBlock(Block)) + return 0; + + // Create the new block. + Block = createBlock(false); + + // The Exit block is the only successor. + Block->addSuccessor(&cfg->getExit()); + + // Add the statement to the block. This may create new blocks if S contains + // control-flow (short-circuit operations). + return VisitStmt(T, true); +} + CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { // See if this is a known constant. bool KnownTrue = false; diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp new file mode 100644 index 0000000000..ec7aebbc5b --- /dev/null +++ b/test/Analysis/dead-stores.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -analyze -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-old-cast -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-old-cast -analyzer-constraints=range -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s + +int j; +void f1() { + int x = 4; + + ++x; // expected-warning{{never read}} + + switch (j) { + case 1: + throw 1; + (void)x; + break; + } +} |