Skip to content

Commit

Permalink
[clang-format] Correctly annotate designated initializer with PP if (#…
Browse files Browse the repository at this point in the history
…65409)

When encountering braces, such as those of a designated initializer,
clang-format scans ahead to see what is contained within the braces. If
it found a statement, like an if-statement of for-loop, it would deem
the braces as not an initializer, but as a block instead.

However, this heuristic incorrectly included a preprocessor `#if` line
as an if-statement. This manifested in strange results and discrepancies
between `#ifdef` and `#if defined`.

With this patch, `if` is now ignored if it is preceeded by `#`.

Fixes most of #56685
  • Loading branch information
rymiel committed Sep 7, 2023
1 parent 80f0dc3 commit e9ed1aa
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
5 changes: 4 additions & 1 deletion clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,12 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
if (Tok->isNot(TT_StatementMacro))
break;
[[fallthrough]];
case tok::kw_if:
if (PrevTok->is(tok::hash))
break;
[[fallthrough]];
case tok::at:
case tok::semi:
case tok::kw_if:
case tok::kw_while:
case tok::kw_for:
case tok::kw_switch:
Expand Down
35 changes: 35 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,41 @@ TEST_F(TokenAnnotatorTest, UnderstandsNestedBlocks) {
EXPECT_BRACE_KIND(Tokens[10], BK_Block);
}

TEST_F(TokenAnnotatorTest, UnderstandDesignatedInitializers) {
auto Tokens = annotate("SomeStruct { .a = 1 };");
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
EXPECT_TOKEN(Tokens[2], tok::period, TT_DesignatedInitializerPeriod);

Tokens = annotate("SomeStruct { .a = 1, .b = 2 };");
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
EXPECT_TOKEN(Tokens[2], tok::period, TT_DesignatedInitializerPeriod);
EXPECT_TOKEN(Tokens[7], tok::period, TT_DesignatedInitializerPeriod);

Tokens = annotate("SomeStruct {\n"
"#ifdef FOO\n"
" .a = 1,\n"
"#endif\n"
" .b = 2\n"
"};");
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
EXPECT_TOKEN(Tokens[5], tok::period, TT_DesignatedInitializerPeriod);
EXPECT_TOKEN(Tokens[12], tok::period, TT_DesignatedInitializerPeriod);

Tokens = annotate("SomeStruct {\n"
"#if defined FOO\n"
" .a = 1,\n"
"#endif\n"
" .b = 2\n"
"};");
ASSERT_EQ(Tokens.size(), 20u) << Tokens;
EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
EXPECT_TOKEN(Tokens[6], tok::period, TT_DesignatedInitializerPeriod);
EXPECT_TOKEN(Tokens[13], tok::period, TT_DesignatedInitializerPeriod);
}

} // namespace
} // namespace format
} // namespace clang

0 comments on commit e9ed1aa

Please sign in to comment.