Skip to content

Commit fc67176

Browse files
committedMar 25, 2019
[clang-format] Refine structured binding detection
Summary: Revision r356575 had the unfortunate consequence that now clang-format never detects an ObjC call expression after `&&`. This patch tries harder to distinguish between C++17 structured bindings and ObjC call expressions and adds a few regression tests. Reviewers: klimek Reviewed By: klimek Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D59774 llvm-svn: 356928
1 parent 7d3225c commit fc67176

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed
 

‎clang/lib/Format/TokenAnnotator.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "TokenAnnotator.h"
16+
#include "FormatToken.h"
1617
#include "clang/Basic/SourceManager.h"
1718
#include "llvm/ADT/SmallPtrSet.h"
1819
#include "llvm/Support/Debug.h"
@@ -440,25 +441,24 @@ class AnnotatingParser {
440441
Contexts.back().InCSharpAttributeSpecifier;
441442

442443
bool InsideInlineASM = Line.startsWith(tok::kw_asm);
444+
bool IsCppStructuredBinding = Left->isCppStructuredBinding(Style);
443445
bool StartsObjCMethodExpr =
444-
!InsideInlineASM && !CppArrayTemplates && Style.isCpp() &&
445-
!IsCpp11AttributeSpecifier && Contexts.back().CanBeExpression &&
446-
Left->isNot(TT_LambdaLSquare) &&
446+
!IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
447+
Style.isCpp() && !IsCpp11AttributeSpecifier &&
448+
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
447449
!CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
448450
(!Parent ||
449451
Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
450452
tok::kw_return, tok::kw_throw) ||
451453
Parent->isUnaryOperator() ||
452454
// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
453455
Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
454-
// for (auto && [A,B] : C) && structure binding seen as ObjCMethodExpr
455-
(Parent->isNot(tok::ampamp) &&
456-
getBinOpPrecedence(Parent->Tok.getKind(), true, true) >
457-
prec::Unknown));
456+
(getBinOpPrecedence(Parent->Tok.getKind(), true, true) >
457+
prec::Unknown));
458458
bool ColonFound = false;
459459

460460
unsigned BindingIncrease = 1;
461-
if (Left->isCppStructuredBinding(Style)) {
461+
if (IsCppStructuredBinding) {
462462
Left->Type = TT_StructuredBindingLSquare;
463463
} else if (Left->is(TT_Unknown)) {
464464
if (StartsObjCMethodExpr) {

‎clang/unittests/Format/FormatTestObjC.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,30 @@ TEST_F(FormatTestObjC, DisambiguatesCallsFromCppLambdas) {
13571357
// verifyFormat("x = ([a foo:bar] >> b->c == 'd');");
13581358
}
13591359

1360+
TEST_F(FormatTestObjC, DisambiguatesCallsFromStructuredBindings) {
1361+
verifyFormat("int f() {\n"
1362+
" if (a && [f arg])\n"
1363+
" return 0;\n"
1364+
"}");
1365+
verifyFormat("int f() {\n"
1366+
" if (a & [f arg])\n"
1367+
" return 0;\n"
1368+
"}");
1369+
verifyFormat("int f() {\n"
1370+
" for (auto &[elem] : list)\n"
1371+
" return 0;\n"
1372+
"}");
1373+
verifyFormat("int f() {\n"
1374+
" for (auto &&[elem] : list)\n"
1375+
" return 0;\n"
1376+
"}");
1377+
verifyFormat(
1378+
"int f() {\n"
1379+
" for (auto /**/ const /**/ volatile /**/ && /**/ [elem] : list)\n"
1380+
" return 0;\n"
1381+
"}");
1382+
}
1383+
13601384
} // end namespace
13611385
} // end namespace format
13621386
} // end namespace clang

0 commit comments

Comments
 (0)