Skip to content

Commit 988a3fa

Browse files
owencazahiraam
authored andcommitted
[clang-format] Handle variable declarations in BreakAfterAttributes (llvm#71935)
Also fixed a bug in `isStartOfName()` and cleaned up some old test cases. Fixed llvm#71563. This is a rework of llvm#71755.
1 parent c635241 commit 988a3fa

File tree

4 files changed

+75
-25
lines changed

4 files changed

+75
-25
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,8 +2049,8 @@ the configuration (without a prefix: ``Auto``).
20492049
.. _BreakAfterAttributes:
20502050

20512051
**BreakAfterAttributes** (``AttributeBreakingStyle``) :versionbadge:`clang-format 16` :ref:`<BreakAfterAttributes>`
2052-
Break after a group of C++11 attributes before a function
2053-
declaration/definition name.
2052+
Break after a group of C++11 attributes before a variable/function
2053+
(including constructor/destructor) declaration/definition name.
20542054

20552055
Possible values:
20562056

@@ -2059,6 +2059,10 @@ the configuration (without a prefix: ``Auto``).
20592059

20602060
.. code-block:: c++
20612061

2062+
[[maybe_unused]]
2063+
const int i;
2064+
[[gnu::const]] [[maybe_unused]]
2065+
int j;
20622066
[[nodiscard]]
20632067
inline int f();
20642068
[[gnu::const]] [[nodiscard]]
@@ -2069,6 +2073,9 @@ the configuration (without a prefix: ``Auto``).
20692073

20702074
.. code-block:: c++
20712075

2076+
[[maybe_unused]] const int i;
2077+
[[gnu::const]] [[maybe_unused]]
2078+
int j;
20722079
[[nodiscard]] inline int f();
20732080
[[gnu::const]] [[nodiscard]]
20742081
int g();
@@ -2078,6 +2085,8 @@ the configuration (without a prefix: ``Auto``).
20782085

20792086
.. code-block:: c++
20802087

2088+
[[maybe_unused]] const int i;
2089+
[[gnu::const]] [[maybe_unused]] int j;
20812090
[[nodiscard]] inline int f();
20822091
[[gnu::const]] [[nodiscard]] int g();
20832092

clang/include/clang/Format/Format.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,10 @@ struct FormatStyle {
14281428
enum AttributeBreakingStyle : int8_t {
14291429
/// Always break after attributes.
14301430
/// \code
1431+
/// [[maybe_unused]]
1432+
/// const int i;
1433+
/// [[gnu::const]] [[maybe_unused]]
1434+
/// int j;
14311435
/// [[nodiscard]]
14321436
/// inline int f();
14331437
/// [[gnu::const]] [[nodiscard]]
@@ -1436,21 +1440,26 @@ struct FormatStyle {
14361440
ABS_Always,
14371441
/// Leave the line breaking after attributes as is.
14381442
/// \code
1443+
/// [[maybe_unused]] const int i;
1444+
/// [[gnu::const]] [[maybe_unused]]
1445+
/// int j;
14391446
/// [[nodiscard]] inline int f();
14401447
/// [[gnu::const]] [[nodiscard]]
14411448
/// int g();
14421449
/// \endcode
14431450
ABS_Leave,
14441451
/// Never break after attributes.
14451452
/// \code
1453+
/// [[maybe_unused]] const int i;
1454+
/// [[gnu::const]] [[maybe_unused]] int j;
14461455
/// [[nodiscard]] inline int f();
14471456
/// [[gnu::const]] [[nodiscard]] int g();
14481457
/// \endcode
14491458
ABS_Never,
14501459
};
14511460

1452-
/// Break after a group of C++11 attributes before a function
1453-
/// declaration/definition name.
1461+
/// Break after a group of C++11 attributes before a variable/function
1462+
/// (including constructor/destructor) declaration/definition name.
14541463
/// \version 16
14551464
AttributeBreakingStyle BreakAfterAttributes;
14561465

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,10 @@ class AnnotatingParser {
19971997
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
19981998
Contexts.back().FirstStartOfName = &Current;
19991999
Current.setType(TT_StartOfName);
2000+
if (auto *PrevNonComment = Current.getPreviousNonComment();
2001+
PrevNonComment && PrevNonComment->is(TT_StartOfName)) {
2002+
PrevNonComment->setType(TT_Unknown);
2003+
}
20002004
} else if (Current.is(tok::semi)) {
20012005
// Reset FirstStartOfName after finding a semicolon so that a for loop
20022006
// with multiple increment statements is not confused with a for loop
@@ -2184,6 +2188,11 @@ class AnnotatingParser {
21842188
if (Tok.isNot(tok::identifier) || !Tok.Previous)
21852189
return false;
21862190

2191+
if (const auto *NextNonComment = Tok.getNextNonComment();
2192+
!NextNonComment || NextNonComment->isPointerOrReference()) {
2193+
return false;
2194+
}
2195+
21872196
if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,
21882197
Keywords.kw_as)) {
21892198
return false;
@@ -3438,10 +3447,15 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34383447
if (AlignArrayOfStructures)
34393448
calculateArrayInitializerColumnList(Line);
34403449

3450+
const bool IsCpp = Style.isCpp();
3451+
bool SeenName = false;
34413452
bool LineIsFunctionDeclaration = false;
34423453
FormatToken *ClosingParen = nullptr;
3443-
for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
3444-
Tok = Tok->Next) {
3454+
FormatToken *AfterLastAttribute = nullptr;
3455+
3456+
for (auto *Tok = Current; Tok; Tok = Tok->Next) {
3457+
if (Tok->is(TT_StartOfName))
3458+
SeenName = true;
34453459
if (Tok->Previous->EndsCppAttributeGroup)
34463460
AfterLastAttribute = Tok;
34473461
if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
@@ -3451,16 +3465,19 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34513465
LineIsFunctionDeclaration = true;
34523466
Tok->setFinalizedType(TT_FunctionDeclarationName);
34533467
}
3454-
if (AfterLastAttribute &&
3455-
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
3456-
AfterLastAttribute->MustBreakBefore = true;
3457-
Line.ReturnTypeWrapped = true;
3458-
}
3468+
SeenName = true;
34593469
break;
34603470
}
34613471
}
34623472

3463-
if (Style.isCpp()) {
3473+
if (IsCpp && SeenName && AfterLastAttribute &&
3474+
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
3475+
AfterLastAttribute->MustBreakBefore = true;
3476+
if (LineIsFunctionDeclaration)
3477+
Line.ReturnTypeWrapped = true;
3478+
}
3479+
3480+
if (IsCpp) {
34643481
if (!LineIsFunctionDeclaration) {
34653482
// Annotate */&/&& in `operator` function calls as binary operators.
34663483
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {

clang/unittests/Format/FormatTest.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8479,18 +8479,25 @@ TEST_F(FormatTest, BreaksFunctionDeclarationsWithTrailingTokens) {
84798479
" aaaaaaaaaaaaaaaaaaaaaaaaa));");
84808480
verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
84818481
" __attribute__((unused));");
8482-
verifyGoogleFormat(
8482+
8483+
Style = getGoogleStyle();
8484+
Style.AttributeMacros.push_back("GUARDED_BY");
8485+
verifyFormat(
84838486
"bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
8484-
" GUARDED_BY(aaaaaaaaaaaa);");
8485-
verifyGoogleFormat(
8487+
" GUARDED_BY(aaaaaaaaaaaa);",
8488+
Style);
8489+
verifyFormat(
84868490
"bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
8487-
" GUARDED_BY(aaaaaaaaaaaa);");
8488-
verifyGoogleFormat(
8491+
" GUARDED_BY(aaaaaaaaaaaa);",
8492+
Style);
8493+
verifyFormat(
84898494
"bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa GUARDED_BY(aaaaaaaaaaaa) =\n"
8490-
" aaaaaaaa::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
8491-
verifyGoogleFormat(
8495+
" aaaaaaaa::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
8496+
Style);
8497+
verifyFormat(
84928498
"bool aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa GUARDED_BY(aaaaaaaaaaaa) =\n"
8493-
" aaaaaaaaaaaaaaaaaaaaaaaaa;");
8499+
" aaaaaaaaaaaaaaaaaaaaaaaaa;",
8500+
Style);
84948501
}
84958502

84968503
TEST_F(FormatTest, FunctionAnnotations) {
@@ -26192,9 +26199,10 @@ TEST_F(FormatTest, RemoveSemicolon) {
2619226199
}
2619326200

2619426201
TEST_F(FormatTest, BreakAfterAttributes) {
26195-
FormatStyle Style = getLLVMStyle();
26196-
26197-
constexpr StringRef Code("[[nodiscard]] inline int f(int &i);\n"
26202+
constexpr StringRef Code("[[maybe_unused]] const int i;\n"
26203+
"[[foo([[]])]] [[maybe_unused]]\n"
26204+
"int j;\n"
26205+
"[[nodiscard]] inline int f(int &i);\n"
2619826206
"[[foo([[]])]] [[nodiscard]]\n"
2619926207
"int g(int &i);\n"
2620026208
"[[nodiscard]]\n"
@@ -26207,11 +26215,14 @@ TEST_F(FormatTest, BreakAfterAttributes) {
2620726215
" return 1;\n"
2620826216
"}");
2620926217

26218+
FormatStyle Style = getLLVMStyle();
2621026219
EXPECT_EQ(Style.BreakAfterAttributes, FormatStyle::ABS_Leave);
2621126220
verifyNoChange(Code, Style);
2621226221

2621326222
Style.BreakAfterAttributes = FormatStyle::ABS_Never;
26214-
verifyFormat("[[nodiscard]] inline int f(int &i);\n"
26223+
verifyFormat("[[maybe_unused]] const int i;\n"
26224+
"[[foo([[]])]] [[maybe_unused]] int j;\n"
26225+
"[[nodiscard]] inline int f(int &i);\n"
2621526226
"[[foo([[]])]] [[nodiscard]] int g(int &i);\n"
2621626227
"[[nodiscard]] inline int f(int &i) {\n"
2621726228
" i = 1;\n"
@@ -26224,7 +26235,11 @@ TEST_F(FormatTest, BreakAfterAttributes) {
2622426235
Code, Style);
2622526236

2622626237
Style.BreakAfterAttributes = FormatStyle::ABS_Always;
26227-
verifyFormat("[[nodiscard]]\n"
26238+
verifyFormat("[[maybe_unused]]\n"
26239+
"const int i;\n"
26240+
"[[foo([[]])]] [[maybe_unused]]\n"
26241+
"int j;\n"
26242+
"[[nodiscard]]\n"
2622826243
"inline int f(int &i);\n"
2622926244
"[[foo([[]])]] [[nodiscard]]\n"
2623026245
"int g(int &i);\n"

0 commit comments

Comments
 (0)