r312723 - [clang-format] Add support for C++17 structured bindings.

Marek Kurdej via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 7 07:28:32 PDT 2017


Author: mkurdej
Date: Thu Sep  7 07:28:32 2017
New Revision: 312723

URL: http://llvm.org/viewvc/llvm-project?rev=312723&view=rev
Log:
[clang-format] Add support for C++17 structured bindings.

Summary:
Before:
```
    auto[a, b] = f();
```

After:
```
    auto [a, b] = f();
```
or, if SpacesInSquareBrackets is true:
```
    auto [ a, b ] = f();
```

Reviewers: djasper

Reviewed By: djasper

Subscribers: cfe-commits, klimek

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

Modified:
    cfe/trunk/lib/Format/FormatToken.h
    cfe/trunk/lib/Format/TokenAnnotator.cpp
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=312723&r1=312722&r2=312723&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Thu Sep  7 07:28:32 2017
@@ -84,6 +84,7 @@ namespace format {
   TYPE(RegexLiteral) \
   TYPE(SelectorName) \
   TYPE(StartOfName) \
+  TYPE(StructuredBindingLSquare) \
   TYPE(TemplateCloser) \
   TYPE(TemplateOpener) \
   TYPE(TemplateString) \

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=312723&r1=312722&r2=312723&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Thu Sep  7 07:28:32 2017
@@ -310,6 +310,16 @@ private:
     return false;
   }
 
+  bool isCppStructuredBinding(const FormatToken *Tok) {
+    if (!Style.isCpp() || !Tok->is(tok::l_square))
+      return false;
+    do {
+      Tok = Tok->getPreviousNonComment();
+    } while (Tok && Tok->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,
+                                 tok::ampamp));
+    return Tok && Tok->is(tok::kw_auto);
+  }
+
   bool parseSquare() {
     if (!CurrentToken)
       return false;
@@ -344,7 +354,9 @@ private:
 
     unsigned BindingIncrease = 1;
     if (Left->is(TT_Unknown)) {
-      if (StartsObjCMethodExpr) {
+      if (isCppStructuredBinding(Left)) {
+        Left->Type = TT_StructuredBindingLSquare;
+      } else if (StartsObjCMethodExpr) {
         Left->Type = TT_ObjCMethodExpr;
       } else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
                  Contexts.back().ContextKind == tok::l_brace &&
@@ -2261,17 +2273,20 @@ bool TokenAnnotator::spaceRequiredBetwee
   if (Left.is(tok::l_square))
     return (Left.is(TT_ArrayInitializerLSquare) &&
             Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) ||
-           (Left.is(TT_ArraySubscriptLSquare) && Style.SpacesInSquareBrackets &&
-            Right.isNot(tok::r_square));
+           (Left.isOneOf(TT_ArraySubscriptLSquare,
+                         TT_StructuredBindingLSquare) &&
+            Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
   if (Right.is(tok::r_square))
     return Right.MatchingParen &&
            ((Style.SpacesInContainerLiterals &&
              Right.MatchingParen->is(TT_ArrayInitializerLSquare)) ||
             (Style.SpacesInSquareBrackets &&
-             Right.MatchingParen->is(TT_ArraySubscriptLSquare)));
+             Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
+                                          TT_StructuredBindingLSquare)));
   if (Right.is(tok::l_square) &&
       !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
-                     TT_DesignatedInitializerLSquare) &&
+                     TT_DesignatedInitializerLSquare,
+                     TT_StructuredBindingLSquare) &&
       !Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
     return false;
   if (Left.is(tok::l_brace) && Right.is(tok::r_brace))

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=312723&r1=312722&r2=312723&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Thu Sep  7 07:28:32 2017
@@ -11452,6 +11452,31 @@ TEST_F(FormatTest, DoNotFormatLikelyXml)
             format(" <!-- >; -->", getGoogleStyle()));
 }
 
+TEST_F(FormatTest, StructuredBindings) {
+  // Structured bindings is a C++17 feature.
+  // all modes, including C++11, C++14 and C++17
+  verifyFormat("auto [a, b] = f();");
+  EXPECT_EQ("auto [a, b] = f();", format("auto[a, b] = f();"));
+  EXPECT_EQ("const auto [a, b] = f();", format("const   auto[a, b] = f();"));
+  EXPECT_EQ("auto const [a, b] = f();", format("auto  const[a, b] = f();"));
+  EXPECT_EQ("auto const volatile [a, b] = f();",
+            format("auto  const   volatile[a, b] = f();"));
+  EXPECT_EQ("auto [a, b, c] = f();", format("auto   [  a  ,  b,c   ] = f();"));
+  EXPECT_EQ("auto & [a, b, c] = f();",
+            format("auto   &[  a  ,  b,c   ] = f();"));
+  EXPECT_EQ("auto && [a, b, c] = f();",
+            format("auto   &&[  a  ,  b,c   ] = f();"));
+  EXPECT_EQ("auto const & [a, b] = f();", format("auto  const&[a, b] = f();"));
+  EXPECT_EQ("auto const volatile && [a, b] = f();",
+            format("auto  const  volatile  &&[a, b] = f();"));
+  EXPECT_EQ("auto && [a, b] = f();", format("auto  &&[a, b] = f();"));
+
+  format::FormatStyle Spaces = format::getLLVMStyle();
+  Spaces.SpacesInSquareBrackets = true;
+  verifyFormat("auto [ a, b ] = f();", Spaces);
+  verifyFormat("auto && [ a, b ] = f();", Spaces);
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang




More information about the cfe-commits mailing list