From 662a4822ee7c8696434b054303c5076a606ab175 Mon Sep 17 00:00:00 2001
From: Douglas Gregor <dgregor@apple.com>
Date: Thu, 23 Dec 2010 22:56:40 +0000
Subject: [PATCH] Improve the diagnostic and recovery for missing colons after
 'case' and 'default' statements, including a Fix-It to add the colon:

test/Parser/switch-recovery.cpp:13:12: error: expected ':' after 'case'
    case 17 // expected-error{{expected ':' after 'case'}}
           ^
           :
test/Parser/switch-recovery.cpp:16:12: error: expected ':' after 'default'
    default // expected-error{{expected ':' after 'default'}}
           ^
           :



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122522 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Parse/ParseStmt.cpp         | 28 ++++++++++++++++------------
 test/Parser/switch-recovery.cpp | 10 +++++++++-
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 29779070be..437a950cd9 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -315,14 +315,16 @@ StmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
     
     ColonProtection.restore();
 
+    SourceLocation ColonLoc;
     if (Tok.isNot(tok::colon)) {
-      Diag(Tok, diag::err_expected_colon_after) << "'case'";
-      SkipUntil(tok::colon);
-      return StmtError();
+      SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
+      Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'"
+        << FixItHint::CreateInsertion(ExpectedLoc, ":");
+      ColonLoc = ExpectedLoc;
+    } else {
+      ColonLoc = ConsumeToken();
     }
-
-    SourceLocation ColonLoc = ConsumeToken();
-
+    
     StmtResult Case =
       Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc,
                             RHS.get(), ColonLoc);
@@ -384,14 +386,16 @@ StmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
 
+  SourceLocation ColonLoc;
   if (Tok.isNot(tok::colon)) {
-    Diag(Tok, diag::err_expected_colon_after) << "'default'";
-    SkipUntil(tok::colon);
-    return StmtError();
+    SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
+    Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'"
+      << FixItHint::CreateInsertion(ExpectedLoc, ":");
+    ColonLoc = ExpectedLoc;
+  } else {
+    ColonLoc = ConsumeToken();
   }
-
-  SourceLocation ColonLoc = ConsumeToken();
-
+  
   // Diagnose the common error "switch (X) {... default: }", which is not valid.
   if (Tok.is(tok::r_brace)) {
     Diag(Tok, diag::err_label_end_of_compound_statement);
diff --git a/test/Parser/switch-recovery.cpp b/test/Parser/switch-recovery.cpp
index 8eb4cff4fb..7b6323a405 100644
--- a/test/Parser/switch-recovery.cpp
+++ b/test/Parser/switch-recovery.cpp
@@ -3,10 +3,18 @@
 // <rdar://problem/7971948>
 struct A {};
 struct B {
-  void foo() {
+  void foo(int b) {
     switch (a) { // expected-error{{use of undeclared identifier 'a'}}
     default:
       return;
     }
+    
+    switch (b) {
+    case 17 // expected-error{{expected ':' after 'case'}}
+      break;
+
+    default // expected-error{{expected ':' after 'default'}}
+      return;
+    }
   }
 };
-- 
2.40.0