Improve CFG support for C++ throw expressions.
authorMike Stump <mrs@apple.com>
Wed, 22 Jul 2009 22:56:04 +0000 (22:56 +0000)
committerMike Stump <mrs@apple.com>
Wed, 22 Jul 2009 22:56:04 +0000 (22:56 +0000)
llvm-svn: 76814

clang/lib/Analysis/CFG.cpp
clang/test/Analysis/dead-stores.cpp [new file with mode: 0644]

index 4c2ecb9..f43631c 100644 (file)
@@ -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/clang/test/Analysis/dead-stores.cpp b/clang/test/Analysis/dead-stores.cpp
new file mode 100644 (file)
index 0000000..ec7aebb
--- /dev/null
@@ -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;
+  }
+}