[PATCH] D130511: [pseudo][wip] Eliminate simple-type-specifier ambiguities.
Haojian Wu via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 28 01:53:10 PDT 2022
hokein updated this revision to Diff 448265.
hokein marked an inline comment as done.
hokein added a comment.
address review comments.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D130511/new/
https://reviews.llvm.org/D130511
Files:
clang-tools-extra/pseudo/include/clang-pseudo/Token.h
clang-tools-extra/pseudo/lib/cxx/CXX.cpp
clang-tools-extra/pseudo/lib/cxx/cxx.bnf
clang-tools-extra/pseudo/test/cxx/nested-name-specifier.cpp
Index: clang-tools-extra/pseudo/test/cxx/nested-name-specifier.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/test/cxx/nested-name-specifier.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-pseudo -grammar=cxx -source=%s --print-forest | FileCheck %s
+
+// Verify that we don't form a complete `::` nested-name-specifier if there is
+// an identifier preceding it.
+Foo::Foo() {} // No "Foo ::Foo()" false parse
+// CHECK: ├─declaration-seq~function-definition := function-declarator function-body
+// CHECK-NEXT: │ ├─function-declarator~noptr-declarator := noptr-declarator parameters-and-qualifiers
+
+int ::x;
+// CHECK: declaration~simple-declaration := decl-specifier-seq init-declarator-list ;
+// CHECK-NEXT: ├─decl-specifier-seq~INT
+
+void test() {
+ X::Y::Z; // No false qualified-declarator parses "X ::Y::Z" and "X::Y ::Z".
+// CHECK: statement-seq~statement := <ambiguous>
+// CHECK: statement~expression-statement := expression ;
+// CHECK: statement~simple-declaration := decl-specifier-seq ;
+// CHECK-NOT: simple-declaration := decl-specifier-seq init-declarator-list ;
+
+ // FIXME: eliminate the false `a<b> ::c` declaration parse.
+ a<b>::c;
+// CHECK: statement := <ambiguous>
+// CHECK-NEXT: ├─statement~expression-statement := expression ;
+// CHECK-NEXT: │ ├─expression~relational-expression :=
+// CHECK: └─statement~simple-declaration := <ambiguous>
+// CHECK-NEXT: ├─simple-declaration := decl-specifier-seq ;
+// CHECK: └─simple-declaration := decl-specifier-seq init-declarator-list ;
+}
Index: clang-tools-extra/pseudo/lib/cxx/cxx.bnf
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -68,7 +68,7 @@
unqualified-id := ~ decltype-specifier
unqualified-id := template-id
qualified-id := nested-name-specifier TEMPLATE_opt unqualified-id
-nested-name-specifier := ::
+nested-name-specifier := :: [guard]
nested-name-specifier := type-name ::
nested-name-specifier := namespace-name ::
nested-name-specifier := decltype-specifier ::
Index: clang-tools-extra/pseudo/lib/cxx/CXX.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -312,6 +312,14 @@
IF__CONSTEXPR__L_PAREN__init_statement__condition__R_PAREN__statement,
guardNextTokenNotElse},
+ // Implement C++ [basic.lookup.qual.general]:
+ // If a name, template-id, or decltype-specifier is followed by a
+ // ::, it shall designate a namespace, class, enumeration, or
+ // dependent type, and the :: is never interpreted as a complete
+ // nested-name-specifier.
+ {rule::nested_name_specifier::COLONCOLON,
+ TOKEN_GUARD(coloncolon, Tok.prev().Kind != tok::identifier)},
+
// The grammar distinguishes (only) user-defined vs plain string literals,
// where the clang lexer distinguishes (only) encoding types.
{rule::user_defined_string_literal_chunk::STRING_LITERAL,
Index: clang-tools-extra/pseudo/include/clang-pseudo/Token.h
===================================================================
--- clang-tools-extra/pseudo/include/clang-pseudo/Token.h
+++ clang-tools-extra/pseudo/include/clang-pseudo/Token.h
@@ -90,6 +90,11 @@
while (T->Kind == tok::comment);
return *T;
}
+ /// Returns the previous token in the stream. this may not be a sentinel.
+ const Token &prev() const {
+ assert(Kind != tok::eof);
+ return *(this - 1);
+ }
/// Returns the bracket paired with this one, if any.
const Token *pair() const { return Pair == 0 ? nullptr : this + Pair; }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130511.448265.patch
Type: text/x-patch
Size: 3826 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220728/7c35ddcc/attachment.bin>
More information about the cfe-commits
mailing list