sepavloff added you to the CC list for the revision "Recovery of switch
statement".
Fix to PR19022 as well as some other problems of error recovery in switch
statement.
http://llvm-reviews.chandlerc.com/D3137
Files:
lib/Parse/ParseStmt.cpp
lib/Sema/SemaStmt.cpp
test/Parser/switch-recovery.cpp
test/Sema/statements.c
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'}}
{
}
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'}}
{
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits