[cfe-commits] r126977 - in /cfe/trunk: lib/Analysis/CFG.cpp test/SemaCXX/array-bounds.cpp

Ted Kremenek kremenek at apple.com
Thu Mar 3 17:03:41 PST 2011


Author: kremenek
Date: Thu Mar  3 19:03:41 2011
New Revision: 126977

URL: http://llvm.org/viewvc/llvm-project?rev=126977&view=rev
Log:
Correctly handle nested switch statements in CFGBuilder when on switch statement has a condition that evaluates to a constant.

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/test/SemaCXX/array-bounds.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=126977&r1=126976&r2=126977&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Thu Mar  3 19:03:41 2011
@@ -279,14 +279,14 @@
   
   // State to track for building switch statements.
   bool switchExclusivelyCovered;
-  Expr::EvalResult switchCond;
+  Expr::EvalResult *switchCond;
 
 public:
   explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
                           Block(NULL), Succ(NULL),
                           SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
                           TryTerminatedBlock(NULL), badCFG(false),
-                          switchExclusivelyCovered(false) {}
+                          switchExclusivelyCovered(false), switchCond(0) {}
 
   // buildCFG - Used by external clients to construct the CFG.
   CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C,
@@ -2197,13 +2197,13 @@
   // for tracking the condition value.
   SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered,
                                                      false);
-  SaveAndRestore<Expr::EvalResult> save_switchCond(switchCond);
-  
-  
+
   // Determine if the switch condition can be explicitly evaluated.
   assert(Terminator->getCond() && "switch condition must be non-NULL");
-  tryEvaluate(Terminator->getCond(), switchCond);
-  
+  Expr::EvalResult result;
+  tryEvaluate(Terminator->getCond(), result);
+  SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, &result);
+
   // If body is not a compound statement create implicit scope
   // and add destructors.
   if (!isa<CompoundStmt>(Terminator->getBody()))
@@ -2243,7 +2243,7 @@
                           const CaseStmt *CS,
                           ASTContext &Ctx) {
   bool addCase = false;
-  
+
   if (!switchExclusivelyCovered) {
     if (switchCond.Val.isInt()) {
       // Evaluate the LHS of the case value.
@@ -2280,7 +2280,8 @@
   // CaseStmts are essentially labels, so they are the first statement in a
   // block.
   CFGBlock *TopBlock = 0, *LastBlock = 0;
-  
+  assert(switchCond);
+
   if (Stmt *Sub = CS->getSubStmt()) {
     // For deeply nested chains of CaseStmts, instead of doing a recursion
     // (which can blow out the stack), manually unroll and create blocks
@@ -2295,7 +2296,7 @@
         TopBlock = currentBlock;
 
       addSuccessor(SwitchTerminatedBlock,
-                   shouldAddCase(switchExclusivelyCovered, switchCond,
+                   shouldAddCase(switchExclusivelyCovered, *switchCond,
                                  CS, *Context)
                    ? currentBlock : 0);
 
@@ -2322,7 +2323,7 @@
   // statement.
   assert(SwitchTerminatedBlock);
   addSuccessor(SwitchTerminatedBlock,
-               shouldAddCase(switchExclusivelyCovered, switchCond,
+               shouldAddCase(switchExclusivelyCovered, *switchCond,
                              CS, *Context)
                ? CaseBlock : 0);
 

Modified: cfe/trunk/test/SemaCXX/array-bounds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/array-bounds.cpp?rev=126977&r1=126976&r2=126977&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/array-bounds.cpp (original)
+++ cfe/trunk/test/SemaCXX/array-bounds.cpp Thu Mar  3 19:03:41 2011
@@ -147,3 +147,16 @@
   }
 }
 
+// Test nested switch statements.
+enum enumA { enumA_A, enumA_B, enumA_C, enumA_D, enumA_E };
+enum enumB { enumB_X, enumB_Y, enumB_Z };
+static enum enumB myVal = enumB_X;
+void test_nested_switch()
+{
+  switch (enumA_E) { // expected-warning {{no case matching constant}}
+    switch (myVal) { // expected-warning {{enumeration values 'enumB_X' and 'enumB_Z' not handled in switch}}
+      case enumB_Y: ;
+    }
+  }
+}
+





More information about the cfe-commits mailing list