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 && 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: 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};