Skip to content

Commit 5c36f43

Browse files
authored
[clang-format] Handle variable declarations in BreakAfterAttributes (#71755)
Also cleaned up some old test cases. Fixes #71563.
1 parent fdbff88 commit 5c36f43

File tree

4 files changed

+66
-28
lines changed

4 files changed

+66
-28
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: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,10 @@ class AnnotatingParser {
20002000
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
20012001
Contexts.back().FirstStartOfName = &Current;
20022002
Current.setType(TT_StartOfName);
2003+
if (auto *PrevNonComment = Current.getPreviousNonComment();
2004+
PrevNonComment && PrevNonComment->is(TT_StartOfName)) {
2005+
PrevNonComment->setType(TT_Unknown);
2006+
}
20032007
} else if (Current.is(tok::semi)) {
20042008
// Reset FirstStartOfName after finding a semicolon so that a for loop
20052009
// with multiple increment statements is not confused with a for loop
@@ -3258,7 +3262,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
32583262
if (Current.is(TT_FunctionDeclarationName))
32593263
return true;
32603264

3261-
if (!Current.Tok.getIdentifierInfo())
3265+
if (!Current.Tok.getIdentifierInfo() || Current.is(TT_CtorDtorDeclName))
32623266
return false;
32633267

32643268
auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
@@ -3441,29 +3445,30 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
34413445
if (AlignArrayOfStructures)
34423446
calculateArrayInitializerColumnList(Line);
34433447

3448+
const bool IsCpp = Style.isCpp();
34443449
bool LineIsFunctionDeclaration = false;
34453450
FormatToken *ClosingParen = nullptr;
34463451
for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
34473452
Tok = Tok->Next) {
34483453
if (Tok->Previous->EndsCppAttributeGroup)
34493454
AfterLastAttribute = Tok;
3450-
if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
3451-
IsCtorOrDtor ||
3452-
isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
3453-
if (!IsCtorOrDtor) {
3454-
LineIsFunctionDeclaration = true;
3455-
Tok->setFinalizedType(TT_FunctionDeclarationName);
3456-
}
3457-
if (AfterLastAttribute &&
3455+
if (isFunctionDeclarationName(IsCpp, *Tok, Line, ClosingParen)) {
3456+
LineIsFunctionDeclaration = true;
3457+
Tok->setFinalizedType(TT_FunctionDeclarationName);
3458+
}
3459+
if (LineIsFunctionDeclaration ||
3460+
Tok->isOneOf(TT_CtorDtorDeclName, TT_StartOfName)) {
3461+
if (IsCpp && AfterLastAttribute &&
34583462
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
34593463
AfterLastAttribute->MustBreakBefore = true;
3460-
Line.ReturnTypeWrapped = true;
3464+
if (LineIsFunctionDeclaration)
3465+
Line.ReturnTypeWrapped = true;
34613466
}
34623467
break;
34633468
}
34643469
}
34653470

3466-
if (Style.isCpp()) {
3471+
if (IsCpp) {
34673472
if (!LineIsFunctionDeclaration) {
34683473
// Annotate */&/&& in `operator` function calls as binary operators.
34693474
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)