[PATCH] D59774: [clang-format] Refine structured binding detection
Krasimir Georgiev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 25 08:02:02 PDT 2019
krasimir created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
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.
Repository:
rC Clang
https://reviews.llvm.org/D59774
Files:
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTestObjC.cpp
Index: unittests/Format/FormatTestObjC.cpp
===================================================================
--- unittests/Format/FormatTestObjC.cpp
+++ unittests/Format/FormatTestObjC.cpp
@@ -1357,6 +1357,30 @@
// verifyFormat("x = ([a foo:bar] >> b->c == 'd');");
}
+TEST_F(FormatTestObjC, DisambiguatesCallsFromStructuredBindings) {
+ verifyFormat("int f() {\n"
+ " if (a && [f arg])\n"
+ " return 0;\n"
+ "}");
+ verifyFormat("int f() {\n"
+ " if (a & [f arg])\n"
+ " return 0;\n"
+ "}");
+ verifyFormat("int f() {\n"
+ " for (auto &[elem] : list)\n"
+ " return 0;\n"
+ "}");
+ verifyFormat("int f() {\n"
+ " for (auto &&[elem] : list)\n"
+ " return 0;\n"
+ "}");
+ verifyFormat(
+ "int f() {\n"
+ " for (auto /**/ const /**/ volatile /**/ && /**/ [elem] : list)\n"
+ " return 0;\n"
+ "}");
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -13,7 +13,9 @@
//===----------------------------------------------------------------------===//
#include "TokenAnnotator.h"
+#include "FormatToken.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.def"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
@@ -39,6 +41,28 @@
return Tok.Tok.getIdentifierInfo() != nullptr;
}
+/// Returns \c true if \c Tok is the left square in a C++ structured binding.
+static bool isStructutedBindingLSquare(const FormatToken &Tok) {
+ assert(Tok.is(tok::l_square));
+ // A structured binding has the structure:
+ // attr(optional) cv-auto ref-operator(optional) [identifier-list] ...
+ // where:
+ // - cv-auto is a possibly cv-qualified specifier auto
+ // - ref-operator is either & or &&.
+ const FormatToken *Prev = Tok.getPreviousNonComment();
+ if (!Prev)
+ return false;
+ // Consume the ref-operator.
+ if (Prev->isOneOf(tok::amp, tok::ampamp)) {
+ Prev = Prev->getPreviousNonComment();
+ }
+ // Consume the cv-qualifiers.
+ while (Prev && Prev->isOneOf(tok::kw_const, tok::kw_volatile)) {
+ Prev = Prev->getPreviousNonComment();
+ }
+ return Prev && Prev->is(tok::kw_auto);
+}
+
/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
@@ -451,8 +475,9 @@
Parent->isUnaryOperator() ||
// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
- // for (auto && [A,B] : C) && structure binding seen as ObjCMethodExpr
- (Parent->isNot(tok::ampamp) &&
+ // Structured bindings and Objective-C call could look alike.
+ ((!Parent->is(tok::l_square) ||
+ !isStructutedBindingLSquare(*Parent)) &&
getBinOpPrecedence(Parent->Tok.getKind(), true, true) >
prec::Unknown));
bool ColonFound = false;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D59774.192108.patch
Type: text/x-patch
Size: 3232 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190325/1fa7b5d3/attachment-0001.bin>
More information about the cfe-commits
mailing list