mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 08:30:34 +08:00
[clang-format] Fix an ObjC regression introduced with new [[likely]][[unlikely]] support in if/else clauses
Summary:
{D80144} introduce an ObjC regression
Only parse the `[]` if what follows is really an attribute
Reviewers: krasimir, JakeMerdichAMD
Reviewed By: krasimir
Subscribers: rdwampler, aaron.ballman, curdeius, cfe-commits
Tags: #clang, #clang-format
Differential Revision: https://reviews.llvm.org/D80547
This commit is contained in:
@@ -1962,7 +1962,7 @@ void UnwrappedLineParser::parseIfThenElse() {
|
||||
if (FormatTok->Tok.is(tok::l_paren))
|
||||
parseParens();
|
||||
// handle [[likely]] / [[unlikely]]
|
||||
if (FormatTok->is(tok::l_square))
|
||||
if (FormatTok->is(tok::l_square) && tryToParseSimpleAttribute())
|
||||
parseSquare();
|
||||
bool NeedsUnwrappedLine = false;
|
||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||
@@ -1981,7 +1981,7 @@ void UnwrappedLineParser::parseIfThenElse() {
|
||||
if (FormatTok->Tok.is(tok::kw_else)) {
|
||||
nextToken();
|
||||
// handle [[likely]] / [[unlikely]]
|
||||
if (FormatTok->is(tok::l_square))
|
||||
if (FormatTok->Tok.is(tok::l_square) && tryToParseSimpleAttribute())
|
||||
parseSquare();
|
||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||
@@ -2343,6 +2343,51 @@ bool UnwrappedLineParser::parseEnum() {
|
||||
// "} n, m;" will end up in one unwrapped line.
|
||||
}
|
||||
|
||||
namespace {
|
||||
// A class used to set and restore the Token position when peeking
|
||||
// ahead in the token source.
|
||||
class ScopedTokenPosition {
|
||||
unsigned StoredPosition;
|
||||
FormatTokenSource *Tokens;
|
||||
|
||||
public:
|
||||
ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
|
||||
assert(Tokens && "Tokens expected to not be null");
|
||||
StoredPosition = Tokens->getPosition();
|
||||
}
|
||||
|
||||
~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Look to see if we have [[ by looking ahead, if
|
||||
// its not then rewind to the original position.
|
||||
bool UnwrappedLineParser::tryToParseSimpleAttribute() {
|
||||
ScopedTokenPosition AutoPosition(Tokens);
|
||||
FormatToken *Tok = Tokens->getNextToken();
|
||||
// We already read the first [ check for the second.
|
||||
if (Tok && !Tok->is(tok::l_square)) {
|
||||
return false;
|
||||
}
|
||||
// Double check that the attribute is just something
|
||||
// fairly simple.
|
||||
while (Tok) {
|
||||
if (Tok->is(tok::r_square)) {
|
||||
break;
|
||||
}
|
||||
Tok = Tokens->getNextToken();
|
||||
}
|
||||
Tok = Tokens->getNextToken();
|
||||
if (Tok && !Tok->is(tok::r_square)) {
|
||||
return false;
|
||||
}
|
||||
Tok = Tokens->getNextToken();
|
||||
if (Tok && Tok->is(tok::semi)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::parseJavaEnumBody() {
|
||||
// Determine whether the enum is simple, i.e. does not have a semicolon or
|
||||
// constants with class bodies. Simple enums can be formatted like braced
|
||||
|
||||
@@ -134,6 +134,7 @@ private:
|
||||
bool tryToParseLambdaIntroducer();
|
||||
bool tryToParsePropertyAccessor();
|
||||
void tryToParseJSFunction();
|
||||
bool tryToParseSimpleAttribute();
|
||||
void addUnwrappedLine();
|
||||
bool eof() const;
|
||||
// LevelDifference is the difference of levels after and before the current
|
||||
|
||||
@@ -16513,6 +16513,11 @@ TEST_F(FormatTest, LikelyUnlikely) {
|
||||
" return 42;\n"
|
||||
"}\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("if (argc > 5) [[gnu::unused]] {\n"
|
||||
" return 29;\n"
|
||||
"}",
|
||||
Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, LLVMDefaultStyle) {
|
||||
|
||||
@@ -1434,6 +1434,25 @@ TEST_F(FormatTestObjC, BreakLineBeforeNestedBlockParam) {
|
||||
" }]");
|
||||
}
|
||||
|
||||
TEST_F(FormatTestObjC, IfNotUnlikely) {
|
||||
Style = getGoogleStyle(FormatStyle::LK_ObjC);
|
||||
|
||||
verifyFormat("if (argc < 5) [obj func:arg];");
|
||||
verifyFormat("if (argc < 5) [[obj1 method1:arg1] method2:arg2];");
|
||||
verifyFormat("if (argc < 5) [[foo bar] baz:i[0]];");
|
||||
verifyFormat("if (argc < 5) [[foo bar] baz:i[0]][1];");
|
||||
|
||||
verifyFormat("if (argc < 5)\n"
|
||||
" [obj func:arg];\n"
|
||||
"else\n"
|
||||
" [obj func:arg2];");
|
||||
|
||||
verifyFormat("if (argc < 5) [[unlikely]]\n"
|
||||
" [obj func:arg];\n"
|
||||
"else [[likely]]\n"
|
||||
" [obj func:arg2];");
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
} // end namespace format
|
||||
} // end namespace clang
|
||||
|
||||
Reference in New Issue
Block a user