[PATCH] D132260: [pseudo] Eliminate a false parse of structured binding declaration.
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGf7dc91ad5609: [pseudo] Eliminate a false parse of structured binding declaration. (authored by hokein). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D132260/new/ https://reviews.llvm.org/D132260 Files: clang-tools-extra/pseudo/lib/cxx/CXX.cpp clang-tools-extra/pseudo/lib/cxx/cxx.bnf clang-tools-extra/pseudo/test/cxx/structured-binding.cpp Index: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp === --- /dev/null +++ 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 ] 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 @@ -330,7 +330,7 @@ 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 := ; 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 @@ -161,6 +161,27 @@ return symbolToToken(P.Lookahead) != tok::kw_else; } +bool specifiesStructuredBinding(const GuardParams ) { + const auto DSS = P.RHS[0]; + assert(DSS->symbol() == Symbol::decl_specifier_seq); + + auto Length = P.RHS[1]->startTokenIndex() - DSS->startTokenIndex(); + for (const auto : + 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 @@ {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, Index: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp === --- /dev/null +++ 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 ] 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 @@ -330,7 +330,7 @@ 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 ;
[PATCH] D132260: [pseudo] Eliminate a false parse of structured binding declaration.
hokein updated this revision to Diff 454816. hokein marked 3 inline comments as done. hokein added a comment. address comments Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D132260/new/ https://reviews.llvm.org/D132260 Files: clang-tools-extra/pseudo/lib/cxx/CXX.cpp clang-tools-extra/pseudo/lib/cxx/cxx.bnf clang-tools-extra/pseudo/test/cxx/structured-binding.cpp Index: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp === --- /dev/null +++ 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 ] 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 @@ -330,7 +330,7 @@ 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 := ; 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 @@ -161,6 +161,27 @@ return symbolToToken(P.Lookahead) != tok::kw_else; } +bool specifiesStructuredBinding(const GuardParams ) { + const auto DSS = P.RHS[0]; + assert(DSS->symbol() == Symbol::decl_specifier_seq); + + auto Length = P.RHS[1]->startTokenIndex() - DSS->startTokenIndex(); + for (const auto : + 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 @@ {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, Index: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp === --- /dev/null +++ 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 ] 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 @@ -330,7 +330,7 @@ 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 :=
[PATCH] D132260: [pseudo] Eliminate a false parse of structured binding declaration.
sammccall accepted this revision. sammccall added inline comments. This revision is now accepted and ready to land. Comment at: clang-tools-extra/pseudo/lib/cxx/CXX.cpp:164 +bool isStructuredBinding(const ForestNode* N) { + assert(N->symbol() == Symbol::decl_specifier_seq); nit: specifiesStructuredBinding? (because the structured binding itself is something bigger) Comment at: clang-tools-extra/pseudo/lib/cxx/CXX.cpp:166 + assert(N->symbol() == Symbol::decl_specifier_seq); + for (const auto : N->descendants()) { +if (Child.kind() == ForestNode::Terminal) { If you're going to iterate over tokens, it seems more direct (and cheaper) to do it directly: `for (const Tok& : P.Tokens.tokens(RHS[0].startTokenIndex(), RHS[1].startTokenIndex()))` Comment at: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp:1 + +// RUN: clang-pseudo -grammar=cxx -source=%s --start-symbol=statement-seq --print-forest | FileCheck %s nit: drop blank line Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D132260/new/ https://reviews.llvm.org/D132260 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D132260: [pseudo] Eliminate a false parse of structured binding declaration.
hokein created this revision. hokein added a reviewer: sammccall. Herald added a project: All. hokein requested review of this revision. Herald added a subscriber: alextsao1999. Herald added a project: clang-tools-extra. 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; } Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D132260 Files: clang-tools-extra/pseudo/lib/cxx/CXX.cpp clang-tools-extra/pseudo/lib/cxx/cxx.bnf clang-tools-extra/pseudo/test/cxx/structured-binding.cpp Index: clang-tools-extra/pseudo/test/cxx/structured-binding.cpp === --- /dev/null +++ clang-tools-extra/pseudo/test/cxx/structured-binding.cpp @@ -0,0 +1,7 @@ + +// 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 ] 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 @@ -330,7 +330,7 @@ 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 := ; 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 @@ -161,6 +161,26 @@ return symbolToToken(P.Lookahead) != tok::kw_else; } +bool isStructuredBinding(const ForestNode* N) { + assert(N->symbol() == Symbol::decl_specifier_seq); + for (const auto : N->descendants()) { +if (Child.kind() == ForestNode::Terminal) { + auto Kind = symbolToToken(Child.symbol()); + switch (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 +340,18 @@ {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, + GUARD(isStructuredBinding(P.RHS[0]))}, + {rule::simple_declaration:: + decl_specifier_seq__L_SQUARE__identifier_list__R_SQUARE__initializer__SEMI, + GUARD(isStructuredBinding(P.RHS[0]))}, + // 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/test/cxx/structured-binding.cpp === --- /dev/null +++ clang-tools-extra/pseudo/test/cxx/structured-binding.cpp @@ -0,0 +1,7 @@ + +// 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 ] 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 @@ -330,7 +330,7 @@ nodeclspec-function-declaration := function-declarator ; alias-declaration := USING IDENTIFIER = defining-type-id ; simple-declaration := decl-specifier-seq