[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
klimek added a comment. In https://reviews.llvm.org/D35743#841197, @chh wrote: > Daniel, Manuel, I will take over this CL since Yan has finished his > internship at Google., > Yan's latest patch to tryToParseLambda looks acceptable to me. > I think it should take care of new kw_auto in additional to kw_new, > ke_delete, etc. > > Could you suggest if there is any better way to handle the new syntax? An alternative would be to look for auto (&&?)? [ with look-ahead, but I agree that this fits the "we try to parse a lambda introducer with look-behind" strategy we've so far been taking, so I'm fine with this approach. https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
chh added a comment. ping. https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
chh added a comment. Daniel, Manuel, I will take over this CL since Yan has finished his internship at Google., Yan's latest patch to tryToParseLambda looks acceptable to me. I think it should take care of new kw_auto in additional to kw_new, ke_delete, etc. Could you suggest if there is any better way to handle the new syntax? Thanks. https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
yawanng updated this revision to Diff 110640. yawanng added a comment. Show full context. https://reviews.llvm.org/D35743 Files: lib/Format/TokenAnnotator.cpp lib/Format/UnwrappedLineParser.cpp lib/Format/UnwrappedLineParser.h unittests/Format/FormatTest.cpp Index: unittests/Format/FormatTest.cpp === --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -11085,6 +11085,41 @@ EXPECT_EQ("auto c = u8'a';", format("auto c = u8'a';")); } +TEST_F(FormatTest, StructuredBindingDeclaration) { + // structured-binding-declaration is a C++17 feature. + EXPECT_EQ("auto [x, y] = a;", format("auto[x, y] = a;")); + EXPECT_EQ("auto &[x, y] = a;", format("auto & [x, y] = a;")); + EXPECT_EQ("auto &&[x, y] = a;", format("auto && [x, y] = a;")); + EXPECT_EQ("auto &&[x, y] = a;", format("auto && [x, y] = a;")); + EXPECT_EQ("auto [x] = a;", format("auto[x] = a;")); + EXPECT_EQ("auto &[x] = a;", format("auto & [x] = a;")); + EXPECT_EQ("auto &&[x] = a;", format("auto && [x] = a;")); + EXPECT_EQ("const auto [x, y] = f();", format("const auto[x, y] = f();")); + EXPECT_EQ("const auto &[x, y] = f();", format("const auto & [x, y] = f();")); + EXPECT_EQ("const auto &&[x, y] = f();", format("const auto && [x, y] = f();")); + EXPECT_EQ("auto [x, y] = A{};", format("auto[x,y] = A{};")); + EXPECT_EQ("auto &[x, y] = A{};", format("auto & [x,y] = A{};")); + EXPECT_EQ("auto &&[x, y] = A{};", format("auto && [x,y] = A{};")); + EXPECT_EQ("for (const auto &&[a, b] : some_range) {\n" +"}", +format("for (const auto && [a, b] : some_range) {\n" +"}")); + EXPECT_EQ("for (const auto &[a, b] : some_range) {\n" +"}", +format("for (const auto & [a, b] : some_range) {\n" +"}")); + EXPECT_EQ("for (const auto [a, b] : some_range) {\n" +"}", +format("for (const auto[a, b] : some_range) {\n" +"}")); + EXPECT_EQ("auto [x, y](expr);", format("auto[x,y] (expr);")); + EXPECT_EQ("auto &[x, y](expr);", format("auto & [x,y](expr);")); + EXPECT_EQ("auto &&[x, y](expr);", format("auto && [x,y](expr);")); + EXPECT_EQ("auto [x, y]{expr};", format("auto[x,y] {expr};")); + EXPECT_EQ("auto &[x, y]{expr};", format("auto & [x,y] {expr};")); + EXPECT_EQ("auto &&[x, y]{expr};", format("auto && [x,y] {expr};")); +} + } // end namespace } // end namespace format } // end namespace clang Index: lib/Format/UnwrappedLineParser.h === --- lib/Format/UnwrappedLineParser.h +++ lib/Format/UnwrappedLineParser.h @@ -125,6 +125,7 @@ bool eof() const; void nextToken(); const FormatToken *getPreviousToken(); + const FormatToken *getPrePreviousToken(); void readToken(); // Decides which comment tokens should be added to the current line and which Index: lib/Format/UnwrappedLineParser.cpp === --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -1211,9 +1211,12 @@ return false; } const FormatToken* Previous = getPreviousToken(); + const FormatToken* PrePrevious = getPrePreviousToken(); if (Previous && (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, - tok::kw_delete) || + tok::kw_delete, tok::kw_auto) || + (PrePrevious && Previous->isOneOf(tok::amp, tok::ampamp) && +PrePrevious->is(tok::kw_auto)) || Previous->closesScope() || Previous->isSimpleTypeSpecifier())) { nextToken(); return false; @@ -2306,6 +2309,12 @@ return Line->Tokens.back().Tok; } +const FormatToken *UnwrappedLineParser::getPrePreviousToken() { + if (!Line || Line->Tokens.size() < 2) +return nullptr; + return std::prev(Line->Tokens.end(), 2)->Tok; +} + void UnwrappedLineParser::distributeComments( const SmallVectorImpl &Comments, const FormatToken *NextTok) { Index: lib/Format/TokenAnnotator.cpp === --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -330,8 +330,15 @@ (Contexts.back().CanBeExpression || Contexts.back().IsExpression || Contexts.back().InTemplateArgument); +bool CppStructuredBindingDecl = +!CppArrayTemplates && Style.isCpp() && Parent && +(Parent->is(tok::kw_auto) || + (Parent->isOneOf(tok::amp, tok::ampamp) && + Parent->getPreviousNonComment() && + Parent->getPreviousNonComment()->is(tok::kw_auto))); + bool StartsObjCMethodExpr = -!CppArrayTemplates && Style.isCpp() && +!CppStructuredBindingDecl && !CppArrayTemplates && Style.isCpp() && Contexts.back().CanBeExpression && Left->isNot(TT_Lambd
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
djasper added a comment. Generally, please upload patches with full context to phabricator. (or use arc) I think this approach is a bit inside out. We are in a codepath where we try to find a lambda introducer and we the look one or two tokens back to see that we aren't as we have seen "auto". I wonder whether we could instead see "auto" and understand that now we have to parse a declaration. Manuel, any thoughts? https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
yawanng updated this revision to Diff 109222. yawanng added a comment. Move tests to unitest and fix a bug. https://reviews.llvm.org/D35743 Files: lib/Format/TokenAnnotator.cpp lib/Format/UnwrappedLineParser.cpp lib/Format/UnwrappedLineParser.h unittests/Format/FormatTest.cpp Index: unittests/Format/FormatTest.cpp === --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -11085,6 +11085,41 @@ EXPECT_EQ("auto c = u8'a';", format("auto c = u8'a';")); } +TEST_F(FormatTest, StructuredBindingDeclaration) { + // structured-binding-declaration is a C++17 feature. + EXPECT_EQ("auto [x, y] = a;", format("auto[x, y] = a;")); + EXPECT_EQ("auto &[x, y] = a;", format("auto & [x, y] = a;")); + EXPECT_EQ("auto &&[x, y] = a;", format("auto && [x, y] = a;")); + EXPECT_EQ("auto &&[x, y] = a;", format("auto && [x, y] = a;")); + EXPECT_EQ("auto [x] = a;", format("auto[x] = a;")); + EXPECT_EQ("auto &[x] = a;", format("auto & [x] = a;")); + EXPECT_EQ("auto &&[x] = a;", format("auto && [x] = a;")); + EXPECT_EQ("const auto [x, y] = f();", format("const auto[x, y] = f();")); + EXPECT_EQ("const auto &[x, y] = f();", format("const auto & [x, y] = f();")); + EXPECT_EQ("const auto &&[x, y] = f();", format("const auto && [x, y] = f();")); + EXPECT_EQ("auto [x, y] = A{};", format("auto[x,y] = A{};")); + EXPECT_EQ("auto &[x, y] = A{};", format("auto & [x,y] = A{};")); + EXPECT_EQ("auto &&[x, y] = A{};", format("auto && [x,y] = A{};")); + EXPECT_EQ("for (const auto &&[a, b] : some_range) {\n" +"}", +format("for (const auto && [a, b] : some_range) {\n" +"}")); + EXPECT_EQ("for (const auto &[a, b] : some_range) {\n" +"}", +format("for (const auto & [a, b] : some_range) {\n" +"}")); + EXPECT_EQ("for (const auto [a, b] : some_range) {\n" +"}", +format("for (const auto[a, b] : some_range) {\n" +"}")); + EXPECT_EQ("auto [x, y](expr);", format("auto[x,y] (expr);")); + EXPECT_EQ("auto &[x, y](expr);", format("auto & [x,y](expr);")); + EXPECT_EQ("auto &&[x, y](expr);", format("auto && [x,y](expr);")); + EXPECT_EQ("auto [x, y]{expr};", format("auto[x,y] {expr};")); + EXPECT_EQ("auto &[x, y]{expr};", format("auto & [x,y] {expr};")); + EXPECT_EQ("auto &&[x, y]{expr};", format("auto && [x,y] {expr};")); +} + } // end namespace } // end namespace format } // end namespace clang Index: lib/Format/UnwrappedLineParser.h === --- lib/Format/UnwrappedLineParser.h +++ lib/Format/UnwrappedLineParser.h @@ -125,6 +125,7 @@ bool eof() const; void nextToken(); const FormatToken *getPreviousToken(); + const FormatToken *getPrePreviousToken(); void readToken(); // Decides which comment tokens should be added to the current line and which Index: lib/Format/UnwrappedLineParser.cpp === --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -1211,9 +1211,12 @@ return false; } const FormatToken* Previous = getPreviousToken(); + const FormatToken* PrePrevious = getPrePreviousToken(); if (Previous && (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, - tok::kw_delete) || + tok::kw_delete, tok::kw_auto) || + (PrePrevious && Previous->isOneOf(tok::amp, tok::ampamp) && +PrePrevious->is(tok::kw_auto)) || Previous->closesScope() || Previous->isSimpleTypeSpecifier())) { nextToken(); return false; @@ -2306,6 +2309,12 @@ return Line->Tokens.back().Tok; } +const FormatToken *UnwrappedLineParser::getPrePreviousToken() { + if (!Line || Line->Tokens.size() < 2) +return nullptr; + return std::prev(Line->Tokens.end(), 2)->Tok; +} + void UnwrappedLineParser::distributeComments( const SmallVectorImpl &Comments, const FormatToken *NextTok) { Index: lib/Format/TokenAnnotator.cpp === --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -330,8 +330,15 @@ (Contexts.back().CanBeExpression || Contexts.back().IsExpression || Contexts.back().InTemplateArgument); +bool CppStructuredBindingDecl = +!CppArrayTemplates && Style.isCpp() && Parent && +(Parent->is(tok::kw_auto) || + (Parent->isOneOf(tok::amp, tok::ampamp) && + Parent->getPreviousNonComment() && + Parent->getPreviousNonComment()->is(tok::kw_auto))); + bool StartsObjCMethodExpr = -!CppArrayTemplates && Style.isCpp() && +!CppStructuredBindingDecl && !CppArrayTemplates && Style.isCpp() && Contexts.back().CanBeExpression && Le
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
djasper added a comment. Please add all the tests into unittests/Format/FormatTest.cpp instead. We use FileCheck-based tests only to verify the behavior of the clang-format binary itself. https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
yawanng added a comment. Ping. https://reviews.llvm.org/D35743 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17
yawanng created this revision. yawanng added a project: clang-tools-extra. Herald added a subscriber: klimek. Add handling for Structured binding declaration in C++17 in clang-format. For example: auto [x,y] = a; auto &[xr, yr] = a; auto &&[xrr, yrr] = a; https://reviews.llvm.org/D35743 Files: lib/Format/TokenAnnotator.cpp lib/Format/UnwrappedLineParser.cpp test/Format/structured-binding-declaration.cpp Index: test/Format/structured-binding-declaration.cpp === --- /dev/null +++ test/Format/structured-binding-declaration.cpp @@ -0,0 +1,54 @@ +// RUN: grep -Ev "// *[A-Z-]+:" %s | clang-format -style=LLVM \ +// RUN: | FileCheck -strict-whitespace %s + +// CHECK: {{^auto\ \[x,\ y\]\ =\ a;}} +auto[x, y] = a; +// CHECK: {{^auto\ \&\[x,\ y\]\ =\ a;}} +auto & [x, y] = a; +// CHECK: {{^auto\ \&\&\[x,\ y\]\ =\ a;}} +auto && [x, y] = a; + +// CHECK: {{^auto\ \[x\]\ =\ a;}} +auto[x] = a; +// CHECK: {{^auto\ \&\[x\]\ =\ a;}} +auto & [x] = a; +// CHECK: {{^auto\ \&\&\[x\]\ =\ a;}} +auto && [x] = a; + +// CHECK: {{^const\ auto\ \[x,\ y\]\ =\ f\(\);}} +const auto[x, y] = f(); +// CHECK: {{^const\ auto\ \&\[x,\ y\]\ =\ f\(\);}} +const auto & [x, y] = f(); +// CHECK: {{^const\ auto\ \&\&\[x,\ y\]\ =\ f\(\);}} +const auto &&[x, y] = f(); + +// CHECK: {{^auto\ \[x,\ y\]\ =\ A\{\};}} +auto[x,y] = A{}; +// CHECK: {{^auto\ \&\[x,\ y\]\ =\ A\{\};}} +auto & [x,y] = A{}; +// CHECK: {{^auto\ \&\&\[x,\ y\]\ =\ A\{\};}} +auto && [x,y] = A{}; + +// CHECK: {{^for\ \(const\ auto\ \&\&\[a,\ b\]\ :\ some_range\)\ \{}} +for (const auto && [a, b] : some_range) { +} +// CHECK: {{^for\ \(const\ auto\ \&\[a,\ b\]\ :\ some_range\)\ \{}} +for (const auto &[a, b] : some_range) { +} +// CHECK: {{^for\ \(const\ auto\ \[a,\ b\]\ :\ some_range\)\ \{}} +for (const auto[a, b] : some_range) { +} + +// CHECK: {{^auto\ \[x,\ y\]\(expr\);}} +auto[x,y] (expr); +// CHECK: {{^auto\ \&\[x,\ y\]\(expr\);}} +auto & [x,y](expr); +// CHECK: {{^auto\ \&\&\[x,\ y\]\(expr\);}} +auto && [x,y](expr); + +// CHECK: {{^auto\ \[x,\ y\]\{expr\};}} +auto[x,y] {expr}; +// CHECK: {{^auto\ \&\[x,\ y\]\{expr\};}} +auto & [x,y] {expr}; +// CHECK: {{^auto\ \&\&\[x,\ y\]\{expr\};}} +auto && [x,y] {expr}; Index: lib/Format/UnwrappedLineParser.cpp === --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -1213,7 +1213,7 @@ const FormatToken* Previous = getPreviousToken(); if (Previous && (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, - tok::kw_delete) || + tok::kw_delete, tok::kw_auto, tok::ampamp, tok::amp) || Previous->closesScope() || Previous->isSimpleTypeSpecifier())) { nextToken(); return false; Index: lib/Format/TokenAnnotator.cpp === --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -330,8 +330,12 @@ (Contexts.back().CanBeExpression || Contexts.back().IsExpression || Contexts.back().InTemplateArgument); +bool CppStructuredBindingDecl = +!CppArrayTemplates && Style.isCpp() && Parent && +Parent->isOneOf(tok::kw_auto, tok::amp, tok::ampamp); + bool StartsObjCMethodExpr = -!CppArrayTemplates && Style.isCpp() && +!CppStructuredBindingDecl && !CppArrayTemplates && Style.isCpp() && Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && CurrentToken->isNot(tok::l_brace) && (!Parent || @@ -344,7 +348,10 @@ unsigned BindingIncrease = 1; if (Left->is(TT_Unknown)) { - if (StartsObjCMethodExpr) { + if (CppStructuredBindingDecl) { +Left->Type = Parent->is(tok::kw_auto) ? TT_DesignatedInitializerLSquare + : TT_ArraySubscriptLSquare; + } else if (StartsObjCMethodExpr) { Left->Type = TT_ObjCMethodExpr; } else if (Style.Language == FormatStyle::LK_JavaScript && Parent && Contexts.back().ContextKind == tok::l_brace && ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits