]> granicus.if.org Git - clang/commitdiff
abstract the SwitchStack for blocks just like we do the goto labels.
authorChris Lattner <sabre@nondot.org>
Sat, 18 Apr 2009 20:10:59 +0000 (20:10 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 18 Apr 2009 20:10:59 +0000 (20:10 +0000)
This fixes a crash on invalid (test10). rdar://6805469

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69465 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaStmt.cpp
test/Sema/block-misc.c

index 48e465ea1f6ceb6f8441b31dbf54adbd05afd14b..7818ae171b905cba984b36c954ae3dedebd2db0a 100644 (file)
@@ -103,6 +103,10 @@ struct BlockSemaInfo {
   /// labels have a LabelStmt created for them with a null location & SubStmt.
   llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
   
+  /// SwitchStack - This is the current set of active switch statements in the
+  /// block.
+  llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+  
   /// PrevBlockInfo - If this is nested inside another block, this points
   /// to the outer block.
   BlockSemaInfo *PrevBlockInfo;
@@ -144,7 +148,10 @@ public:
   /// to handle blocks properly.
   llvm::DenseMap<IdentifierInfo*, LabelStmt*> FunctionLabelMap;
   
-  llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+  /// FunctionSwitchStack - This is the current set of active switch statements
+  /// in the top level function.  Clients should always use getSwitchStack() to
+  /// handle the case when they are in a block.
+  llvm::SmallVector<SwitchStmt*, 8> FunctionSwitchStack;
   
   /// ExtVectorDecls - This is a list all the extended vector types. This allows
   /// us to associate a raw vector type with one of the ext_vector type names.
@@ -336,6 +343,12 @@ public:
     return CurBlock ? CurBlock->LabelMap : FunctionLabelMap;
   }
   
+  /// getSwitchStack - This is returns the switch stack for the current block or
+  /// function.
+  llvm::SmallVector<SwitchStmt*,8> &getSwitchStack() {
+    return CurBlock ? CurBlock->SwitchStack : FunctionSwitchStack;
+  }
+  
   //===--------------------------------------------------------------------===//
   // Type Analysis / Processing: SemaType.cpp.
   //
index a5b188696a53b55a84de9b5abe3bc9be2fe7758e..6595b881220ee8e7ee50eb883905797355716403 100644 (file)
@@ -112,7 +112,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval,
     rhsval = 0;
   }
 
-  if (SwitchStack.empty()) {
+  if (getSwitchStack().empty()) {
     Diag(CaseLoc, diag::err_case_not_in_switch);
     return StmtError();
   }
@@ -121,7 +121,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval,
   lhsval.release();
   rhsval.release();
   CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc);
-  SwitchStack.back()->addSwitchCase(CS);
+  getSwitchStack().back()->addSwitchCase(CS);
   return Owned(CS);
 }
 
@@ -137,13 +137,13 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
                        StmtArg subStmt, Scope *CurScope) {
   Stmt *SubStmt = static_cast<Stmt*>(subStmt.release());
 
-  if (SwitchStack.empty()) {
+  if (getSwitchStack().empty()) {
     Diag(DefaultLoc, diag::err_default_not_in_switch);
     return Owned(SubStmt);
   }
 
   DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, SubStmt);
-  SwitchStack.back()->addSwitchCase(DS);
+  getSwitchStack().back()->addSwitchCase(DS);
   return Owned(DS);
 }
 
@@ -241,7 +241,7 @@ Sema::ActOnStartOfSwitchStmt(ExprArg cond) {
   }
 
   SwitchStmt *SS = new (Context) SwitchStmt(Cond);
-  SwitchStack.push_back(SS);
+  getSwitchStack().push_back(SS);
   return Owned(SS);
 }
 
@@ -325,11 +325,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
                             StmtArg Body) {
   Stmt *BodyStmt = (Stmt*)Body.release();
 
-  SwitchStmt *SS = SwitchStack.back();
+  SwitchStmt *SS = getSwitchStack().back();
   assert(SS == (SwitchStmt*)Switch.get() && "switch stack missing push/pop!");
 
   SS->setBody(BodyStmt, SwitchLoc);
-  SwitchStack.pop_back(); 
+  getSwitchStack().pop_back(); 
 
   Expr *CondExpr = SS->getCond();
   QualType CondType = CondExpr->getType();
index 277d6d20c89bd95b05b03b2b4a26383e9fb1a43f..b2d4fd822900a65d61e24506cccec9e6dfd69dea 100644 (file)
@@ -95,4 +95,21 @@ void test9() {
   ^{ somelabel: ; }();
 }
 
+void test10(int i) {
+  switch (i) {
+  case 41: ;
+  ^{ case 42: ; }();     // expected-error {{'case' statement not in switch statement}}
+  }
+}
+
+void test11(int i) {
+  switch (i) {
+  case 41: ;
+    ^{ break; }();     // expected-error {{'break' statement not in loop or switch statement}}
+  }
+  
+  for (; i < 100; ++i)
+    ^{ break; }();     // expected-error {{'break' statement not in loop or switch statement}}
+}
+