[cfe-commits] r154530 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp test/Parser/recovery.cpp test/SemaCXX/class.cpp

Richard Smith richard-llvm at metafoo.co.uk
Wed Apr 11 13:59:20 PDT 2012


Author: rsmith
Date: Wed Apr 11 15:59:20 2012
New Revision: 154530

URL: http://llvm.org/viewvc/llvm-project?rev=154530&view=rev
Log:
Part of PR10101: after a parse error in a declaration, try harder to find the
right place to pick up parsing. In C++, this had a tendency to skip everything
declared within headers if the TU starts with garbage.

Added:
    cfe/trunk/test/Parser/recovery.cpp
Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/test/SemaCXX/class.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=154530&r1=154529&r2=154530&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Apr 11 15:59:20 2012
@@ -742,6 +742,10 @@
   bool SkipUntil(ArrayRef<tok::TokenKind> Toks, 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.
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=154530&r1=154529&r2=154530&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Apr 11 15:59:20 2012
@@ -1117,6 +1117,67 @@
   }
 }
 
+/// 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::r_brace:
+      return;
+
+    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.
@@ -1131,10 +1192,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();
   }
 

Added: cfe/trunk/test/Parser/recovery.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/recovery.cpp?rev=154530&view=auto
==============================================================================
--- cfe/trunk/test/Parser/recovery.cpp (added)
+++ cfe/trunk/test/Parser/recovery.cpp Wed Apr 11 15:59:20 2012
@@ -0,0 +1,42 @@
+// 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}}
+
+namespace N {
+  int
+} // expected-error {{unqualified-id}}
+
+// FIXME: Recover as if the typo correction were applied.
+strcut U { // expected-error {{did you mean 'struct'}}
+} *u[3]; // expected-error {{expected ';'}}

Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=154530&r1=154529&r2=154530&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Wed Apr 11 15:59:20 2012
@@ -131,10 +131,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;





More information about the cfe-commits mailing list