aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseStmt.cpp
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2011-04-21 21:44:26 +0000
committerRichard Trieu <rtrieu@google.com>2011-04-21 21:44:26 +0000
commitbb9b80c308d7d3f758886243c7145404a50c66cf (patch)
treea0f409d3a3e384dabdd86880871ca16a2b229b96 /lib/Parse/ParseStmt.cpp
parent723b1782460bc448d9d865e9b828c09d26a50964 (diff)
Add a fixit suggest for missing case keywords inside a switch scope. For instance, in the following code, 'case ' will be suggested before the '1:'
switch (x) { 1: return 0; default: return 1; } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129943 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseStmt.cpp')
-rw-r--r--lib/Parse/ParseStmt.cpp28
1 files changed, 23 insertions, 5 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d70a745314..aaf79acf4f 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -121,6 +121,9 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
return StmtError();
}
+ // If a case keyword is missing, this is where it should be inserted.
+ Token OldToken = Tok;
+
// FIXME: Use the attributes
// expression[opt] ';'
ExprResult Expr(ParseExpression());
@@ -133,6 +136,18 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
ConsumeToken();
return StmtError();
}
+
+ if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
+ Actions.CheckCaseExpression(Expr.get())) {
+ // If a constant expression is followed by a colon inside a switch block,
+ // suggest a missing case keywork.
+ Diag(OldToken, diag::err_expected_case_before_expression)
+ << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
+
+ // Recover parsing as a case statement.
+ return ParseCaseStatement(attrs, /*MissingCase=*/true, Expr);
+ }
+
// Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));
@@ -251,8 +266,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
- assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,
+ ExprResult Expr) {
+ assert(MissingCase || Tok.is(tok::kw_case) && "Not a case stmt!");
// FIXME: Use attributes?
// It is very very common for code to contain many case statements recursively
@@ -280,7 +296,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
// While we have case statements, eat and stack them.
do {
- SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
+ SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
+ ConsumeToken(); // eat the 'case'.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCase(getCurScope());
@@ -292,7 +309,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
/// expression.
ColonProtectionRAIIObject ColonProtection(*this);
- ExprResult LHS(ParseConstantExpression());
+ ExprResult LHS(MissingCase ? Expr : ParseConstantExpression());
+ MissingCase = false;
if (LHS.isInvalid()) {
SkipUntil(tok::colon);
return StmtError();
@@ -775,7 +793,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) {
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement).
//
- unsigned ScopeFlags = Scope::BreakScope;
+ unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope;
if (C99orCXX)
ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
ParseScope SwitchScope(this, ScopeFlags);