forked from OSchip/llvm-project
[clang-format] Correctly annotate function names before attributes
Fixes #58827. Differential Revision: https://reviews.llvm.org/D137486
This commit is contained in:
parent
a9f9520907
commit
96e23906b5
|
@ -71,6 +71,38 @@ static bool isKeywordWithCondition(const FormatToken &Tok) {
|
||||||
tok::kw_constexpr, tok::kw_catch);
|
tok::kw_constexpr, tok::kw_catch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns \c true if the token starts a C++ attribute, \c false otherwise.
|
||||||
|
static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) {
|
||||||
|
if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square))
|
||||||
|
return false;
|
||||||
|
// The first square bracket is part of an ObjC array literal
|
||||||
|
if (Tok.Previous && Tok.Previous->is(tok::at))
|
||||||
|
return false;
|
||||||
|
const FormatToken *AttrTok = Tok.Next->Next;
|
||||||
|
if (!AttrTok)
|
||||||
|
return false;
|
||||||
|
// C++17 '[[using ns: foo, bar(baz, blech)]]'
|
||||||
|
// We assume nobody will name an ObjC variable 'using'.
|
||||||
|
if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
|
||||||
|
return true;
|
||||||
|
if (AttrTok->isNot(tok::identifier))
|
||||||
|
return false;
|
||||||
|
while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
|
||||||
|
// ObjC message send. We assume nobody will use : in a C++11 attribute
|
||||||
|
// specifier parameter, although this is technically valid:
|
||||||
|
// [[foo(:)]].
|
||||||
|
if (AttrTok->is(tok::colon) ||
|
||||||
|
AttrTok->startsSequence(tok::identifier, tok::identifier) ||
|
||||||
|
AttrTok->startsSequence(tok::r_paren, tok::identifier)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (AttrTok->is(tok::ellipsis))
|
||||||
|
return true;
|
||||||
|
AttrTok = AttrTok->Next;
|
||||||
|
}
|
||||||
|
return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
|
||||||
|
}
|
||||||
|
|
||||||
/// A parser that gathers additional information about tokens.
|
/// A parser that gathers additional information about tokens.
|
||||||
///
|
///
|
||||||
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
|
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
|
||||||
|
@ -538,34 +570,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
|
bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
|
||||||
if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
|
return isCppAttribute(Style.isCpp(), Tok);
|
||||||
return false;
|
|
||||||
// The first square bracket is part of an ObjC array literal
|
|
||||||
if (Tok.Previous && Tok.Previous->is(tok::at))
|
|
||||||
return false;
|
|
||||||
const FormatToken *AttrTok = Tok.Next->Next;
|
|
||||||
if (!AttrTok)
|
|
||||||
return false;
|
|
||||||
// C++17 '[[using ns: foo, bar(baz, blech)]]'
|
|
||||||
// We assume nobody will name an ObjC variable 'using'.
|
|
||||||
if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
|
|
||||||
return true;
|
|
||||||
if (AttrTok->isNot(tok::identifier))
|
|
||||||
return false;
|
|
||||||
while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
|
|
||||||
// ObjC message send. We assume nobody will use : in a C++11 attribute
|
|
||||||
// specifier parameter, although this is technically valid:
|
|
||||||
// [[foo(:)]].
|
|
||||||
if (AttrTok->is(tok::colon) ||
|
|
||||||
AttrTok->startsSequence(tok::identifier, tok::identifier) ||
|
|
||||||
AttrTok->startsSequence(tok::r_paren, tok::identifier)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (AttrTok->is(tok::ellipsis))
|
|
||||||
return true;
|
|
||||||
AttrTok = AttrTok->Next;
|
|
||||||
}
|
|
||||||
return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseSquare() {
|
bool parseSquare() {
|
||||||
|
@ -2844,6 +2849,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
|
||||||
}
|
}
|
||||||
if (!Next->is(tok::identifier))
|
if (!Next->is(tok::identifier))
|
||||||
return false;
|
return false;
|
||||||
|
} else if (isCppAttribute(IsCpp, *Next)) {
|
||||||
|
Next = Next->MatchingParen;
|
||||||
} else if (Next->is(tok::l_paren)) {
|
} else if (Next->is(tok::l_paren)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1047,6 +1047,16 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {
|
||||||
EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown);
|
EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) {
|
||||||
|
auto Tokens = annotate("void f [[noreturn]] ();");
|
||||||
|
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
|
||||||
|
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName);
|
||||||
|
|
||||||
|
Tokens = annotate("void f [[noreturn]] () {}");
|
||||||
|
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
|
||||||
|
EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) {
|
TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) {
|
||||||
auto Annotate = [this](llvm::StringRef Code) {
|
auto Annotate = [this](llvm::StringRef Code) {
|
||||||
return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));
|
return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));
|
||||||
|
|
Loading…
Reference in New Issue