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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
|
||||
|
@ -538,34 +570,7 @@ private:
|
|||
}
|
||||
|
||||
bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
|
||||
if (!Style.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);
|
||||
return isCppAttribute(Style.isCpp(), Tok);
|
||||
}
|
||||
|
||||
bool parseSquare() {
|
||||
|
@ -2844,6 +2849,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
|
|||
}
|
||||
if (!Next->is(tok::identifier))
|
||||
return false;
|
||||
} else if (isCppAttribute(IsCpp, *Next)) {
|
||||
Next = Next->MatchingParen;
|
||||
} else if (Next->is(tok::l_paren)) {
|
||||
break;
|
||||
} else {
|
||||
|
|
|
@ -1047,6 +1047,16 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {
|
|||
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) {
|
||||
auto Annotate = [this](llvm::StringRef Code) {
|
||||
return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));
|
||||
|
|
Loading…
Reference in New Issue