[PATCH] D150258: [clang][parser] Fix namespace dropping after malformed declarations
Alejandro Álvarez Ayllón via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed May 10 02:22:38 PDT 2023
alejandro-alvarez-sonarsource created this revision.
alejandro-alvarez-sonarsource added a reviewer: aaron.ballman.
alejandro-alvarez-sonarsource added a project: clang.
Herald added a subscriber: kadircet.
Herald added a project: All.
alejandro-alvarez-sonarsource requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
- After a malformed top-level declaration
- After a malformed templated class method declaration
In both cases, when there is a malformed declaration, any following namespace is dropped from the AST.
This can trigger a cascade of confusing diagnostics that may hide the original error. An example:
// Start #include "SomeFile.h"
template <class T>
void Foo<T>::Bar(void* aRawPtr) {
(void)(aRawPtr);
}
// End #include "SomeFile.h"
#include <iostream>
int main() {}
We get the original error, plus 19 others from the standard library.
With this patch, we only get the original error.
clangd
``` can also benefit from this patch, as namespaces following the malformed declaration is now preserved. i.e.
#pragma once
MACRO_FROM_MISSING_INCLUDE("X")
namespace my_namespace {
//...
}
Before this patch, `my_namespace` is not visible for auto-completion.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D150258
Files:
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 -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 -verify %s
+
+UNKNOWN_MACRO_1("z", 1) // expected-error {{a type specifier is required for all declarations}}
+// expected-error at -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 at -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,7 +2176,8 @@
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- if (isDeclarationSpecifier(ImplicitTypenameContext::No)) {
+ if (isDeclarationSpecifier(ImplicitTypenameContext::No) ||
+ Tok.is(tok::kw_namespace)) {
// 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
@@ -2304,8 +2305,7 @@
// 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);
+ SkipMalformedDecl();
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D150258.520935.patch
Type: text/x-patch
Size: 2796 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230510/e4b0aa83/attachment-0001.bin>
More information about the cfe-commits
mailing list