Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -620,7 +620,9 @@ ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); MissingCase = false; if (LHS.isInvalid()) { - SkipUntil(tok::colon, StopAtSemi); + if (SkipUntil(tok::colon, StopAtSemi | StopBeforeMatch) && + TryConsumeToken(tok::colon, ColonLoc)) + continue; return StmtError(); } @@ -676,8 +678,6 @@ // Handle all case statements. } while (Tok.is(tok::kw_case)); - assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!"); - // If we found a non-case statement, start by parsing it. StmtResult SubStmt; @@ -692,12 +692,13 @@ SubStmt = true; } - // Broken sub-stmt shouldn't prevent forming the case statement properly. - if (SubStmt.isInvalid()) - SubStmt = Actions.ActOnNullStmt(SourceLocation()); - // Install the body into the most deeply-nested case. - Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + if (DeepestParsedCaseStmt) { + // Broken sub-stmt shouldn't prevent forming the case statement properly. + if (SubStmt.isInvalid()) + SubStmt = Actions.ActOnNullStmt(SourceLocation()); + Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + } // Return the top level parsed statement tree. return TopLevelCase; @@ -1222,15 +1223,6 @@ InnerScope.Exit(); SwitchScope.Exit(); - if (Body.isInvalid()) { - // FIXME: Remove the case statement list from the Switch statement. - - // Put the synthesized null statement on the same line as the end of switch - // condition. - SourceLocation SynthesizedNullStmtLocation = Cond.get()->getLocEnd(); - Body = Actions.ActOnNullStmt(SynthesizedNullStmtLocation); - } - return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -702,7 +702,19 @@ assert(SS == getCurFunction()->SwitchStack.back() && "switch stack missing push/pop!"); - SS->setBody(BodyStmt, SwitchLoc); + Stmt *Body = BodyStmt; + if (!Body) { + // Put the synthesized null statement on the same line as the end of switch + // condition. + SourceLocation SynthesizedNullStmtLocation; + if (Expr *Cond = SS->getCond()) + SynthesizedNullStmtLocation = Cond->getLocEnd(); + else if (VarDecl *CondVar = SS->getConditionVariable()) + SynthesizedNullStmtLocation = CondVar->getLocEnd(); + Body = ActOnNullStmt(SynthesizedNullStmtLocation).release(); + SS->setSwitchCaseList(0); + } + SS->setBody(Body, SwitchLoc); getCurFunction()->SwitchStack.pop_back(); Expr *CondExpr = SS->getCond(); @@ -1141,8 +1153,9 @@ } } - DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, - diag::warn_empty_switch_body); + if (BodyStmt) + DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, + diag::warn_empty_switch_body); // FIXME: If the case list was broken is some way, we don't have a good system // to patch it up. Instead, just return the whole substmt as broken. Index: test/Parser/switch-recovery.cpp =================================================================== --- test/Parser/switch-recovery.cpp +++ test/Parser/switch-recovery.cpp @@ -170,3 +170,19 @@ default: // expected-error {{label at end of compound statement: expected statement}} } } + +void pr19022_1() { + switch (int x) // expected-error {{variable declaration in condition must have an initializer}} + case v: ; // expected-error {{use of undeclared identifier 'v'}} +} + +void pr19022_2() { + switch (int x) // expected-error {{variable declaration in condition must have an initializer}} + case v1: case v2: ; // expected-error {{use of undeclared identifier 'v1'}} \ + // expected-error {{use of undeclared identifier 'v2'}} +} + +void pr19022_3(int x) { + switch (x) + case 1: case v2: ; // expected-error {{use of undeclared identifier 'v2'}} +} Index: test/Sema/statements.c =================================================================== --- test/Sema/statements.c +++ test/Sema/statements.c @@ -36,7 +36,7 @@ // PR6034 void test11(int bit) { - switch (bit) // expected-warning {{switch statement has empty body}} expected-note {{put the semicolon on a separate line to silence this warning}} + switch (bit) switch (env->fpscr) // expected-error {{use of undeclared identifier 'env'}} { }