r313742 - Fix clang-format's detection of structured bindings.
Manuel Klimek via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 20 02:29:37 PDT 2017
Author: klimek
Date: Wed Sep 20 02:29:37 2017
New Revision: 313742
URL: http://llvm.org/viewvc/llvm-project?rev=313742&view=rev
Log:
Fix clang-format's detection of structured bindings.
Correctly determine when [ is part of a structured binding instead of a
lambda.
To be able to reuse the implementation already available, this patch also:
- sets the Previous link of FormatTokens in the UnwrappedLineParser
- moves the isCppStructuredBinding function into FormatToken
Before:
auto const const &&[x, y] { A *i };
After:
auto const const && [x, y]{A * i};
Fixing formatting of the type of the structured binding is still missing.
Modified:
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.h
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=313742&r1=313741&r2=313742&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Wed Sep 20 02:29:37 2017
@@ -472,6 +472,19 @@ struct FormatToken {
Style.Language == FormatStyle::LK_TextProto));
}
+ /// \brief Returns whether the token is the left square bracket of a C++
+ /// structured binding declaration.
+ bool isCppStructuredBinding(const FormatStyle &Style) const {
+ if (!Style.isCpp() || isNot(tok::l_square))
+ return false;
+ const FormatToken* T = this;
+ do {
+ T = T->getPreviousNonComment();
+ } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,
+ tok::ampamp));
+ return T && T->is(tok::kw_auto);
+ }
+
/// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {
if (is(TT_TemplateString) && closesScope())
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=313742&r1=313741&r2=313742&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Sep 20 02:29:37 2017
@@ -310,16 +310,6 @@ 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;
@@ -354,7 +344,7 @@ private:
unsigned BindingIncrease = 1;
if (Left->is(TT_Unknown)) {
- if (isCppStructuredBinding(Left)) {
+ if (Left->isCppStructuredBinding(Style)) {
Left->Type = TT_StructuredBindingLSquare;
} else if (StartsObjCMethodExpr) {
Left->Type = TT_ObjCMethodExpr;
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=313742&r1=313741&r2=313742&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed Sep 20 02:29:37 2017
@@ -356,7 +356,7 @@ void UnwrappedLineParser::calculateBrace
// definitions, too.
unsigned StoredPosition = Tokens->getPosition();
FormatToken *Tok = FormatTok;
- const FormatToken *PrevTok = getPreviousToken();
+ const FormatToken *PrevTok = Tok->Previous;
// Keep a stack of positions of lbrace tokens. We will
// update information about whether an lbrace starts a
// braced init list or a different block during the loop.
@@ -1100,7 +1100,7 @@ void UnwrappedLineParser::parseStructura
break;
}
do {
- const FormatToken *Previous = getPreviousToken();
+ const FormatToken *Previous = FormatTok->Previous;
switch (FormatTok->Tok.getKind()) {
case tok::at:
nextToken();
@@ -1356,10 +1356,11 @@ bool UnwrappedLineParser::tryToParseLamb
}
bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
- const FormatToken* Previous = getPreviousToken();
+ const FormatToken* Previous = FormatTok->Previous;
if (Previous &&
(Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
tok::kw_delete) ||
+ FormatTok->isCppStructuredBinding(Style) ||
Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
nextToken();
return false;
@@ -2232,6 +2233,8 @@ void UnwrappedLineParser::addUnwrappedLi
std::make_move_iterator(PreprocessorDirectives.end()));
PreprocessorDirectives.clear();
}
+ // Disconnect the current token from the last token on the previous line.
+ FormatTok->Previous = nullptr;
}
bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); }
@@ -2378,18 +2381,12 @@ void UnwrappedLineParser::nextToken(int
return;
flushComments(isOnNewLine(*FormatTok));
pushToken(FormatTok);
+ FormatToken* Previous = FormatTok;
if (Style.Language != FormatStyle::LK_JavaScript)
readToken(LevelDifference);
else
readTokenWithJavaScriptASI();
-}
-
-const FormatToken *UnwrappedLineParser::getPreviousToken() {
- // FIXME: This is a dirty way to access the previous token. Find a better
- // solution.
- if (!Line || Line->Tokens.empty())
- return nullptr;
- return Line->Tokens.back().Tok;
+ FormatTok->Previous = Previous;
}
void UnwrappedLineParser::distributeComments(
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=313742&r1=313741&r2=313742&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Wed Sep 20 02:29:37 2017
@@ -129,7 +129,6 @@ private:
// - if the token is '}' and closes a block, LevelDifference is -1.
void nextToken(int LevelDifference = 0);
void readToken(int LevelDifference = 0);
- const FormatToken *getPreviousToken();
// Decides which comment tokens should be added to the current line and which
// should be added as comments before the next token.
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=313742&r1=313741&r2=313742&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Wed Sep 20 02:29:37 2017
@@ -11588,6 +11588,11 @@ TEST_F(FormatTest, StructuredBindings) {
format("auto const volatile &&[a, b] = f();"));
EXPECT_EQ("auto && [a, b] = f();", format("auto &&[a, b] = f();"));
+ // Make sure we don't mistake structured bindings for lambdas.
+ verifyFormat("auto [a, b]{A * i};");
+ verifyFormat("auto const [a, b]{A * i};");
+ verifyFormat("auto const && [a, b]{A * i};");
+
format::FormatStyle Spaces = format::getLLVMStyle();
Spaces.SpacesInSquareBrackets = true;
verifyFormat("auto [ a, b ] = f();", Spaces);
More information about the cfe-commits
mailing list