Index: test/Parser/recovery.cpp
===================================================================
--- test/Parser/recovery.cpp	(revision 0)
+++ test/Parser/recovery.cpp	(revision 0)
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -verify -std=c++11 %s
+
+8gi///===--- recovery.cpp ---===// // expected-error {{unqualified-id}}
+namespace Std { // expected-note {{here}}
+  typedef int Important;
+}
+
+/ redeclare as an inline namespace // expected-error {{unqualified-id}}
+inline namespace Std { // expected-error {{cannot be reopened as inline}}
+  Important n;
+} / end namespace Std // expected-error {{unqualified-id}}
+int x;
+Std::Important y;
+
+// FIXME: Recover as if the typo correction were applied.
+extenr "C" { // expected-error {{did you mean 'extern'}} expected-error {{unqualified-id}}
+  void f();
+}
+void g() {
+  z = 1; // expected-error {{undeclared}}
+  f(); // expected-error {{undeclared}}
+}
+
+struct S {
+  int a, b, c;
+  S();
+};
+8S::S() : a{ 5 }, b{ 6 }, c{ 2 } { // expected-error {{unqualified-id}}
+  return;
+}
+int k;
+int l = k;
+
+5int m = { l }, n = m; // expected-error {{unqualified-id}}
Index: test/SemaCXX/class.cpp
===================================================================
--- test/SemaCXX/class.cpp	(revision 153880)
+++ test/SemaCXX/class.cpp	(working copy)
@@ -129,10 +129,10 @@
     bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \
                        // BOGUS expected-error {{expected '{' after base class list}} \
                        // BOGUS expected-error {{expected ';' after struct}} \
-                       // BOGUS expected-error {{expected unqualified-id}} \
+                       // BOGUS expected-error {{expected unqualified-id}}
   { };
 
-  template<> struct foo<unknown,unknown> { // why isn't there an error here?
+  template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}}
     template <typename U1, typename U2> struct bar {
       typedef bar type;
       static const int value = 0;
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 153880)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -736,6 +736,10 @@
                  bool StopAtSemi = true, bool DontConsume = false,
                  bool StopAtCodeCompletion = false);
 
+  /// SkipMalformedDecl - Read tokens until we get to some likely good stopping
+  /// point for skipping past a simple-declaration.
+  void SkipMalformedDecl();
+
   //===--------------------------------------------------------------------===//
   // Lexing and parsing of C++ inline methods.
 
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 153880)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -1073,6 +1073,64 @@
   }
 }
 
+/// Skip until we reach something which seems like a sensible place to pick
+/// up parsing after a malformed declaration. This will sometimes stop sooner
+/// than SkipUntil(tok::r_brace) would, but will never stop later.
+void Parser::SkipMalformedDecl() {
+  while (true) {
+    switch (Tok.getKind()) {
+    case tok::l_brace:
+      // Skip until matching }, then stop. We've probably skipped over
+      // a malformed class or function definition or similar.
+      ConsumeBrace();
+      SkipUntil(tok::r_brace, /*StopAtSemi*/false);
+      if (Tok.is(tok::comma) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try)) {
+        // This declaration isn't over yet. Keep skipping.
+        continue;
+      }
+      if (Tok.is(tok::semi))
+        ConsumeToken();
+      return;
+
+    case tok::l_square:
+      ConsumeBracket();
+      SkipUntil(tok::r_square, /*StopAtSemi*/false);
+      continue;
+
+    case tok::l_paren:
+      ConsumeParen();
+      SkipUntil(tok::r_paren, /*StopAtSemi*/false);
+      continue;
+
+    case tok::semi:
+      ConsumeToken();
+      return;
+
+    case tok::kw_inline:
+      // 'inline namespace' at the start of a line is almost certainly
+      // a good place to pick back up parsing.
+      if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace))
+        return;
+      break;
+
+    case tok::kw_namespace:
+      // 'namespace' at the start of a line is almost certainly a good
+      // place to pick back up parsing.
+      if (Tok.isAtStartOfLine())
+        return;
+      break;
+
+    case tok::eof:
+      return;
+
+    default:
+      break;
+    }
+
+    ConsumeAnyToken();
+  }
+}
+
 /// ParseDeclGroup - Having concluded that this is either a function
 /// definition or a group of object declarations, actually parse the
 /// result.
@@ -1087,10 +1145,7 @@
 
   // Bail out if the first declarator didn't seem well-formed.
   if (!D.hasName() && !D.mayOmitIdentifier()) {
-    // Skip until ; or }.
-    SkipUntil(tok::r_brace, true, true);
-    if (Tok.is(tok::semi))
-      ConsumeToken();
+    SkipMalformedDecl();
     return DeclGroupPtrTy();
   }
 
