Skip to content

Commit 3affefb

Browse files
committed
[clang-format] Add FunctionLikeMacros option
This allows RemoveParentheses to skip the invocations of function-like macros. Fixes #68354. Fixes #147780.
1 parent 2f1673e commit 3affefb

File tree

11 files changed

+38
-7
lines changed

11 files changed

+38
-7
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4073,6 +4073,12 @@ the configuration (without a prefix: ``Auto``).
40734073
40744074
For example: BOOST_FOREACH.
40754075

4076+
.. _FunctionLikeMacros:
4077+
4078+
**FunctionLikeMacros** (``List of Strings``) :versionbadge:`clang-format 21` :ref:`<FunctionLikeMacros>`
4079+
A vector of function-like macros whose invocations should be skipped by
4080+
``RemoveParentheses``.
4081+
40764082
.. _IfMacros:
40774083

40784084
**IfMacros** (``List of Strings``) :versionbadge:`clang-format 13` :ref:`<IfMacros>`

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,8 @@ clang-format
11321132
``enum`` enumerator lists.
11331133
- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
11341134
- Add ``SpaceAfterOperatorKeyword`` option.
1135+
- Add ``FunctionLikeMacros`` option so that their invocations are skipped by
1136+
``RemoveParentheses``.
11351137

11361138
clang-refactor
11371139
--------------

clang/include/clang/Format/Format.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,6 +2786,11 @@ struct FormatStyle {
27862786
/// \version 3.7
27872787
std::vector<std::string> ForEachMacros;
27882788

2789+
/// A vector of function-like macros whose invocations should be skipped by
2790+
/// ``RemoveParentheses``.
2791+
/// \version 21
2792+
std::vector<std::string> FunctionLikeMacros;
2793+
27892794
tooling::IncludeStyle IncludeStyle;
27902795

27912796
/// A vector of macros that should be interpreted as conditionals
@@ -5382,6 +5387,7 @@ struct FormatStyle {
53825387
R.ExperimentalAutoDetectBinPacking &&
53835388
FixNamespaceComments == R.FixNamespaceComments &&
53845389
ForEachMacros == R.ForEachMacros &&
5390+
FunctionLikeMacros == R.FunctionLikeMacros &&
53855391
IncludeStyle.IncludeBlocks == R.IncludeStyle.IncludeBlocks &&
53865392
IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories &&
53875393
IncludeStyle.IncludeIsMainRegex ==

clang/lib/Format/Format.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,7 @@ template <> struct MappingTraits<FormatStyle> {
10681068
Style.ExperimentalAutoDetectBinPacking);
10691069
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
10701070
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
1071+
IO.mapOptional("FunctionLikeMacros", Style.FunctionLikeMacros);
10711072
IO.mapOptional("IfMacros", Style.IfMacros);
10721073
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
10731074
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);

clang/lib/Format/FormatToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ namespace format {
8383
TYPE(FunctionDeclarationName) \
8484
TYPE(FunctionDeclarationLParen) \
8585
TYPE(FunctionLBrace) \
86+
TYPE(FunctionLikeMacro) \
8687
TYPE(FunctionLikeOrFreestandingMacro) \
8788
TYPE(FunctionTypeLParen) \
8889
/* The colons as part of a C11 _Generic selection */ \

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ FormatTokenLexer::FormatTokenLexer(
4343
auto Identifier = &IdentTable.get(ForEachMacro);
4444
Macros.insert({Identifier, TT_ForEachMacro});
4545
}
46+
for (const std::string &FunctionLikeMacro : Style.FunctionLikeMacros) {
47+
auto Identifier = &IdentTable.get(FunctionLikeMacro);
48+
Macros.insert({Identifier, TT_FunctionLikeMacro});
49+
}
4650
for (const std::string &IfMacro : Style.IfMacros) {
4751
auto Identifier = &IdentTable.get(IfMacro);
4852
Macros.insert({Identifier, TT_IfMacro});

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,8 @@ class AnnotatingParser {
20902090
TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,
20912091
TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
20922092
TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
2093-
TT_CompoundRequirementLBrace, TT_BracedListLBrace)) {
2093+
TT_CompoundRequirementLBrace, TT_BracedListLBrace,
2094+
TT_FunctionLikeMacro)) {
20942095
CurrentToken->setType(TT_Unknown);
20952096
}
20962097
CurrentToken->Role.reset();

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,30 +2579,34 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
25792579
/// double ampersands. This applies for all nested scopes as well.
25802580
///
25812581
/// Returns whether there is a `=` token between the parentheses.
2582-
bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
2582+
bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,
2583+
bool InMacroCall) {
25832584
assert(FormatTok->is(tok::l_paren) && "'(' expected.");
25842585
auto *LParen = FormatTok;
2586+
auto *Prev = FormatTok->Previous;
25852587
bool SeenComma = false;
25862588
bool SeenEqual = false;
25872589
bool MightBeFoldExpr = false;
25882590
nextToken();
25892591
const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2592+
if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2593+
InMacroCall = true;
25902594
do {
25912595
switch (FormatTok->Tok.getKind()) {
25922596
case tok::l_paren:
2593-
if (parseParens(AmpAmpTokenType))
2597+
if (parseParens(AmpAmpTokenType, InMacroCall))
25942598
SeenEqual = true;
25952599
if (Style.isJava() && FormatTok->is(tok::l_brace))
25962600
parseChildBlock();
25972601
break;
25982602
case tok::r_paren: {
2599-
auto *Prev = LParen->Previous;
26002603
auto *RParen = FormatTok;
26012604
nextToken();
26022605
if (Prev) {
26032606
auto OptionalParens = [&] {
2604-
if (MightBeStmtExpr || MightBeFoldExpr || Line->InMacroBody ||
2605-
SeenComma || Style.RemoveParentheses == FormatStyle::RPS_Leave ||
2607+
if (MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2608+
Line->InMacroBody ||
2609+
Style.RemoveParentheses == FormatStyle::RPS_Leave ||
26062610
RParen->getPreviousNonComment() == LParen) {
26072611
return false;
26082612
}

clang/lib/Format/UnwrappedLineParser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ class UnwrappedLineParser {
145145
bool *HasLabel = nullptr);
146146
bool tryToParseBracedList();
147147
bool parseBracedList(bool IsAngleBracket = false, bool IsEnum = false);
148-
bool parseParens(TokenType AmpAmpTokenType = TT_Unknown);
148+
bool parseParens(TokenType AmpAmpTokenType = TT_Unknown,
149+
bool InMacroCall = false);
149150
void parseSquare(bool LambdaIntroducer = false);
150151
void keepAncestorBraces();
151152
void parseUnbracedBody(bool CheckEOF = false);

clang/unittests/Format/ConfigParseTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ TEST(ConfigParseTest, ParsesConfiguration) {
940940
CHECK_PARSE("StatementMacros: [QUNUSED, QT_REQUIRE_VERSION]", StatementMacros,
941941
std::vector<std::string>({"QUNUSED", "QT_REQUIRE_VERSION"}));
942942

943+
CHECK_PARSE_LIST(FunctionLikeMacros);
943944
CHECK_PARSE_LIST(JavaImportGroups);
944945
CHECK_PARSE_LIST(Macros);
945946
CHECK_PARSE_LIST(NamespaceMacros);

0 commit comments

Comments
 (0)