diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index 33a11344e7..f19737e30a 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -55,7 +55,7 @@ Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval, SourceLocation DotDotDotLoc, ExprTy *rhsval, SourceLocation ColonLoc, StmtTy *subStmt) { Stmt *SubStmt = static_cast(subStmt); - Expr *LHSVal = ((Expr *)lhsval); + Expr *LHSVal = ((Expr *)lhsval), *RHSVal = ((Expr *)rhsval); assert((LHSVal != 0) && "missing expression in case statement"); SourceLocation ExpLoc; @@ -67,19 +67,19 @@ Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval, } // GCC extension: The expression shall be an integer constant. - Expr *RHSVal = ((Expr *)rhsval); if (RHSVal && !RHSVal->isIntegerConstantExpr(Context, &ExpLoc)) { Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr, RHSVal->getSourceRange()); return SubStmt; } + + if (SwitchStack.empty()) { + Diag(CaseLoc, diag::err_case_not_in_switch); + return SubStmt; + } CaseStmt *CS = new CaseStmt(LHSVal, RHSVal, SubStmt); - - assert(!SwitchStack.empty() && "missing push/pop in switch stack!"); - SwitchStmt *SS = SwitchStack.back(); - SS->addSwitchCase(CS); - + SwitchStack.back()->addSwitchCase(CS); return CS; } @@ -87,18 +87,14 @@ Action::StmtResult Sema::ParseDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, StmtTy *subStmt, Scope *CurScope) { Stmt *SubStmt = static_cast(subStmt); - Scope *S = CurScope->getBreakParent(); - if (!S) { + if (SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; } DefaultStmt *DS = new DefaultStmt(DefaultLoc, SubStmt); - - assert(!SwitchStack.empty() && "missing push/pop in switch stack!"); - SwitchStmt *SS = SwitchStack.back(); - SS->addSwitchCase(DS); + SwitchStack.back()->addSwitchCase(DS); return DS; } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 2224d7e057..4069bda645 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -655,6 +655,8 @@ DIAG(err_break_not_in_loop_or_switch, ERROR, "'break' statement not in loop or switch statement") DIAG(err_default_not_in_switch, ERROR, "'default' statement not in switch statement") +DIAG(err_case_not_in_switch, ERROR, + "'case' statement not in switch statement") DIAG(err_typecheck_return_incompatible, ERROR, "incompatible type returning '%1', expected '%0'") DIAG(ext_typecheck_return_pointer_int, EXTENSION, diff --git a/test/Sema/switch.c b/test/Sema/switch.c new file mode 100644 index 0000000000..0c244cfcf5 --- /dev/null +++ b/test/Sema/switch.c @@ -0,0 +1,9 @@ +// RUN: clang -parse-ast-check %s + + +void f (int z) { + while (z) { + default: z--; // expected-error {{statement not in switch}} + } +} +