[PATCH] D130511: [pseudo][wip] Eliminate simple-type-specifier ambiguities.

Haojian Wu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 26 13:30:00 PDT 2022


hokein updated this revision to Diff 447815.
hokein added a comment.

refine the patch: guard the "::" nested-name-specifier rule instead.


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/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,19 @@
+// 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 ;
+}
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
@@ -164,6 +164,12 @@
   return P.Tokens.tokens()[P.LookaheadIndex].Kind != tok::kw_else;
 }
 
+bool guardPreviousTokenNotIdentifier(const GuardParams &P) {
+  if (P.LookaheadIndex < 2)
+    return true;
+  return P.Tokens.tokens()[P.LookaheadIndex-2].Kind != tok::identifier;
+}
+
 // Whether this e.g. decl-specifier contains an "exclusive" type such as a class
 // name, and thus can't combine with a second exclusive type.
 //
@@ -310,6 +316,14 @@
            selection_statement_0if_1constexpr_2l_paren_3condition_4r_paren_5statement,
        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.
+      {(RuleID)Rule::nested_name_specifier_0coloncolon,
+       guardPreviousTokenNotIdentifier},
+
       // The grammar distinguishes (only) user-defined vs plain string literals,
       // where the clang lexer distinguishes (only) encoding types.
       {(RuleID)Rule::user_defined_string_literal_chunk_0string_literal,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130511.447815.patch
Type: text/x-patch
Size: 3158 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220726/62e65e02/attachment.bin>


More information about the cfe-commits mailing list