Try to recover a bit better if a close brace is missing from the end of a class
definition. If we see something that looks like a namespace definition inside a
class, that strongly indicates that a close brace was missing somewhere.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194319 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 8cd16b3..3c534f7 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1953,12 +1953,12 @@
       Diag(Tok, diag::err_at_defs_cxx);
     else
       Diag(Tok, diag::err_at_in_class);
-    
+
     ConsumeToken();
     SkipUntil(tok::r_brace);
     return;
   }
-  
+
   // Access declarations.
   bool MalformedTypeSpec = false;
   if (!TemplateInfo.Kind &&
@@ -2421,7 +2421,7 @@
 ///     assignment-expression
 ///     braced-init-list
 ///
-///   defaulted/deleted function-definition:                                                                                                                                                                                               
+///   defaulted/deleted function-definition:
 ///     '=' 'default'
 ///     '=' 'delete'
 ///
@@ -2625,6 +2625,12 @@
         continue;
       }
 
+      // If we see a namespace here, a close brace was missing somewhere.
+      if (Tok.is(tok::kw_namespace)) {
+        DiagnoseUnexpectedNamespace(cast<DeclContext>(TagDecl));
+        break;
+      }
+
       AccessSpecifier AS = getAccessSpecifierIfPresent();
       if (AS != AS_none) {
         // Current token is a C++ access specifier.
@@ -2666,8 +2672,6 @@
         continue;
       }
 
-      // FIXME: Make sure we don't have a template here.
-
       // Parse all the comma separated declarators.
       ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
     }
@@ -2718,6 +2722,27 @@
   ClassScope.Exit();
 }
 
+void Parser::DiagnoseUnexpectedNamespace(DeclContext *Ctx) {
+  assert(Tok.is(tok::kw_namespace));
+
+  // FIXME: Suggest where the close brace should have gone by looking
+  // at indentation changes within the definition body.
+  Diag(cast<Decl>(Ctx)->getLocation(),
+       diag::err_missing_end_of_definition) << Ctx;
+  Diag(Tok.getLocation(),
+       diag::note_missing_end_of_definition_before) << Ctx;
+
+  // Push '};' onto the token stream to recover.
+  PP.EnterToken(Tok);
+
+  Tok.startToken();
+  Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation));
+  Tok.setKind(tok::semi);
+  PP.EnterToken(Tok);
+
+  Tok.setKind(tok::r_brace);
+}
+
 /// ParseConstructorInitializer - Parse a C++ constructor initializer,
 /// which explicitly initializes the members or base classes of a
 /// class (C++ [class.base.init]). For example, the three initializers