forked from OSchip/llvm-project
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. llvm-svn: 313742
This commit is contained in:
parent
94444b9a07
commit
e411aa85ac
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -356,7 +356,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
|||
// 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::parseStructuralElement() {
|
|||
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::tryToParseLambda() {
|
|||
}
|
||||
|
||||
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::addUnwrappedLine() {
|
|||
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 LevelDifference) {
|
|||
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(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue