[PATCH] D35743: [clang-format] Handle Structured binding declaration in C++17

2017-09-18 Thread Manuel Klimek via Phabricator via cfe-commits
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

2017-09-15 Thread Chih-Hung Hsieh via Phabricator via cfe-commits
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

2017-08-14 Thread Chih-Hung Hsieh via Phabricator via cfe-commits
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

2017-08-10 Thread Yan Wang via Phabricator via cfe-commits
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

2017-08-01 Thread Daniel Jasper via Phabricator via cfe-commits
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

2017-08-01 Thread Yan Wang via Phabricator via cfe-commits
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

2017-07-31 Thread Daniel Jasper via Phabricator via cfe-commits
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

2017-07-31 Thread Yan Wang via Phabricator via cfe-commits
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

2017-07-21 Thread Yan Wang via Phabricator via cfe-commits
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