summaryrefslogtreecommitdiff
path: root/clang-tools-extra/pseudo
diff options
context:
space:
mode:
authorHaojian Wu <hokein.wu@gmail.com>2022-08-19 21:55:39 +0200
committerHaojian Wu <hokein.wu@gmail.com>2022-08-23 15:25:52 +0200
commitf7dc91ad5609fab02cb805861dd232cab492340d (patch)
treedfa8ee2420c562959c4ebb88fabe28e22f480a0e /clang-tools-extra/pseudo
parent562accddaaa243e9d4772f1d1ff1389f90594df2 (diff)
downloadllvm-f7dc91ad5609fab02cb805861dd232cab492340d.tar.gz
[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
Diffstat (limited to 'clang-tools-extra/pseudo')
-rw-r--r--clang-tools-extra/pseudo/lib/cxx/CXX.cpp33
-rw-r--r--clang-tools-extra/pseudo/lib/cxx/cxx.bnf2
-rw-r--r--clang-tools-extra/pseudo/test/cxx/structured-binding.cpp6
3 files changed, 40 insertions, 1 deletions
diff --git a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp
index 668c4d1bfcb6..46d837aec44a 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 80c1b54437c0..36caf7b1e633 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 000000000000..1c68e928ddd6
--- /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 ]