Author: Haojian Wu
Date: 2022-08-23T15:25:52+02:00
New Revision: f7dc91ad5609fab02cb805861dd232cab492340d

URL: 
https://github.com/llvm/llvm-project/commit/f7dc91ad5609fab02cb805861dd232cab492340d
DIFF: 
https://github.com/llvm/llvm-project/commit/f7dc91ad5609fab02cb805861dd232cab492340d.diff

LOG: [pseudo] Eliminate a false parse of structured binding declaration.

Using the guard to implement part of the rule https://eel.is/c++draft/dcl.pre#6.

```
void foo() {
  // can be parsed as
  //   - structured-binding declaration (a false parse)
  //   - assignment expression
  array[index] = value;
}
```

Differential Revision: https://reviews.llvm.org/D132260

Added: 
    clang-tools-extra/pseudo/test/cxx/structured-binding.cpp

Modified: 
    clang-tools-extra/pseudo/lib/cxx/CXX.cpp
    clang-tools-extra/pseudo/lib/cxx/cxx.bnf

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp 
b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp
index 668c4d1bfcb6a..46d837aec44ad 100644
--- a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -161,6 +161,27 @@ bool guardNextTokenNotElse(const GuardParams &P) {
   return symbolToToken(P.Lookahead) != tok::kw_else;
 }
 
+bool specifiesStructuredBinding(const GuardParams &P) {
+  const auto DSS = P.RHS[0];
+  assert(DSS->symbol() == Symbol::decl_specifier_seq);
+
+  auto Length = P.RHS[1]->startTokenIndex() - DSS->startTokenIndex();
+  for (const auto &T :
+       P.Tokens.tokens().slice(DSS->startTokenIndex(), Length)) {
+    switch (T.Kind) {
+    case clang::tok::kw_static:
+    case clang::tok::kw_thread_local:
+    case clang::tok::kw_auto:
+    case clang::tok::kw_const:
+    case clang::tok::kw_volatile:
+      break;
+    default:
+      return false;
+    }
+  }
+  return true;
+}
+
 // 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.
 //
@@ -320,6 +341,18 @@ llvm::DenseMap<ExtensionID, RuleGuard> buildGuards() {
       {rule::nested_name_specifier::COLONCOLON,
        TOKEN_GUARD(coloncolon, Tok.prev().Kind != tok::identifier)},
 
+      // Implement C++ [dcl.pre#6]:
+      //   A simple-declaration with an identifier-list is called a structured
+      //   binding declaration ([dcl.struct.bind]). If the decl-specifier-seq
+      //   contains any decl-specifier other than static, thread_­local, auto,
+      //   or cv-qualifiers, the program is ill-formed.
+      {rule::simple_declaration::
+           
decl_specifier_seq__ref_qualifier__L_SQUARE__identifier_list__R_SQUARE__initializer__SEMI,
+       specifiesStructuredBinding},
+      {rule::simple_declaration::
+           
decl_specifier_seq__L_SQUARE__identifier_list__R_SQUARE__initializer__SEMI,
+       specifiesStructuredBinding},
+
       // 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,

diff  --git a/clang-tools-extra/pseudo/lib/cxx/cxx.bnf 
b/clang-tools-extra/pseudo/lib/cxx/cxx.bnf
index 80c1b54437c07..36caf7b1e6337 100644
--- a/clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ b/clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -330,7 +330,7 @@ block-declaration := opaque-enum-declaration
 nodeclspec-function-declaration := function-declarator ;
 alias-declaration := USING IDENTIFIER = defining-type-id ;
 simple-declaration := decl-specifier-seq init-declarator-list_opt ;
-simple-declaration := decl-specifier-seq ref-qualifier_opt [ identifier-list ] 
initializer ;
+simple-declaration := decl-specifier-seq ref-qualifier_opt [ identifier-list ] 
initializer ; [guard]
 static_assert-declaration := STATIC_ASSERT ( constant-expression ) ;
 static_assert-declaration := STATIC_ASSERT ( constant-expression , 
string-literal ) ;
 empty-declaration := ;

diff  --git a/clang-tools-extra/pseudo/test/cxx/structured-binding.cpp 
b/clang-tools-extra/pseudo/test/cxx/structured-binding.cpp
new file mode 100644
index 0000000000000..1c68e928ddd62
--- /dev/null
+++ b/clang-tools-extra/pseudo/test/cxx/structured-binding.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-pseudo -grammar=cxx -source=%s --start-symbol=statement-seq 
--print-forest | FileCheck %s
+
+// Verify there is no false parse of the structured binding declaration.
+ABC[post] = abc;
+// CHECK: statement-seq~expression-statement := expression ;
+// CHECK: postfix-expression [ expr-or-braced-init-list ]


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to