This revision was automatically updated to reflect the committed changes.
Closed by commit rGb321738f7125: [clang][parser] Fix namespace dropping after 
malformed declarations (authored by alejandro-alvarez-sonarsource, committed by 
aaron.ballman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150258/new/

https://reviews.llvm.org/D150258

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseTemplate.cpp
  clang/test/Parser/cxx-namespace-after-missing-semicolon.cpp
  clang/test/Parser/cxx-template-recovery.cpp

Index: clang/test/Parser/cxx-template-recovery.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/cxx-template-recovery.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <class T>
+void Foo<T>::Bar(void* aRawPtr) { // expected-error {{no template named 'Foo'}}
+    (void)(aRawPtr);
+}
+
+namespace baz {
+  class klass {};
+}
+
+int *variable = 0; // ok
+const baz::klass object; // ok
Index: clang/test/Parser/cxx-namespace-after-missing-semicolon.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/cxx-namespace-after-missing-semicolon.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+UNKNOWN_MACRO_1("z", 1) // expected-error {{a type specifier is required for all declarations}}
+// expected-error@-1 {{expected ';' after top level declarator}}
+
+namespace foo {
+  class bar {};
+}
+
+int variable = 0; // ok
+foo::bar something; // ok
+
+UNKNOWN_MACRO_2(void) // expected-error {{a type specifier is required for all declarations}}
+// expected-error@-1 {{expected ';' after top level declarator}}
+
+namespace baz {
+  using Bool = bool;
+}
+
+int variable2 = 2; // ok
+const baz::Bool flag = false;  // ok
Index: clang/lib/Parse/ParseTemplate.cpp
===================================================================
--- clang/lib/Parse/ParseTemplate.cpp
+++ clang/lib/Parse/ParseTemplate.cpp
@@ -275,10 +275,7 @@
 
   // Error parsing the declarator?
   if (!DeclaratorInfo.hasName()) {
-    // If so, skip until the semi-colon or a }.
-    SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
-    if (Tok.is(tok::semi))
-      ConsumeToken();
+    SkipMalformedDecl();
     return nullptr;
   }
 
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2176,13 +2176,16 @@
           return Actions.ConvertDeclToDeclGroup(TheDecl);
         }
 
-        if (isDeclarationSpecifier(ImplicitTypenameContext::No)) {
-          // If there is an invalid declaration specifier right after the
-          // function prototype, then we must be in a missing semicolon case
-          // where this isn't actually a body.  Just fall through into the code
-          // that handles it as a prototype, and let the top-level code handle
-          // the erroneous declspec where it would otherwise expect a comma or
-          // semicolon.
+        if (isDeclarationSpecifier(ImplicitTypenameContext::No) ||
+            Tok.is(tok::kw_namespace)) {
+          // If there is an invalid declaration specifier or a namespace
+          // definition right after the function prototype, then we must be in a
+          // missing semicolon case where this isn't actually a body.  Just fall
+          // through into the code that handles it as a prototype, and let the
+          // top-level code handle the erroneous declspec where it would
+          // otherwise expect a comma or semicolon. Note that
+          // isDeclarationSpecifier already covers 'inline namespace', since
+          // 'inline' can be a declaration specifier.
         } else {
           Diag(Tok, diag::err_expected_fn_body);
           SkipUntil(tok::semi);
@@ -2303,10 +2306,8 @@
     // Okay, there was no semicolon and one was expected.  If we see a
     // declaration specifier, just assume it was missing and continue parsing.
     // Otherwise things are very confused and we skip to recover.
-    if (!isDeclarationSpecifier(ImplicitTypenameContext::No)) {
-      SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
-      TryConsumeToken(tok::semi);
-    }
+    if (!isDeclarationSpecifier(ImplicitTypenameContext::No))
+      SkipMalformedDecl();
   }
 
   return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -449,6 +449,8 @@
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Preserve ``namespace`` definitions that follow malformed declarations.
+
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D150258... Alejandro Álvarez Ayllón via Phabricator via cfe-commits
    • [PATCH] D1... Aaron Ballman via Phabricator via cfe-commits
    • [PATCH] D1... Alejandro Álvarez Ayllón via Phabricator via cfe-commits
    • [PATCH] D1... Alejandro Álvarez Ayllón via Phabricator via cfe-commits
    • [PATCH] D1... Aaron Ballman via Phabricator via cfe-commits
    • [PATCH] D1... Alejandro Álvarez Ayllón via Phabricator via cfe-commits
    • [PATCH] D1... Aaron Ballman via Phabricator via cfe-commits

Reply via email to