[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