From: Chris Lattner Date: Sat, 18 Apr 2009 20:10:59 +0000 (+0000) Subject: abstract the SwitchStack for blocks just like we do the goto labels. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bcfce66584e47bb07f49a86b7cb39b4fdd269a5a;p=clang abstract the SwitchStack for blocks just like we do the goto labels. 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 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 48e465ea1f..7818ae171b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -103,6 +103,10 @@ struct BlockSemaInfo { /// labels have a LabelStmt created for them with a null location & SubStmt. llvm::DenseMap LabelMap; + /// SwitchStack - This is the current set of active switch statements in the + /// block. + llvm::SmallVector 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 FunctionLabelMap; - llvm::SmallVector 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 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 &getSwitchStack() { + return CurBlock ? CurBlock->SwitchStack : FunctionSwitchStack; + } + //===--------------------------------------------------------------------===// // Type Analysis / Processing: SemaType.cpp. // diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index a5b188696a..6595b88122 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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(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(); diff --git a/test/Sema/block-misc.c b/test/Sema/block-misc.c index 277d6d20c8..b2d4fd8229 100644 --- a/test/Sema/block-misc.c +++ b/test/Sema/block-misc.c @@ -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}} +} +