diff options
-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; + } +} |