Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4073,6 +4073,12 @@ the configuration (without a prefix: ``Auto``).

For example: BOOST_FOREACH.

.. _FunctionLikeMacros:

**FunctionLikeMacros** (``List of Strings``) :versionbadge:`clang-format 21` :ref:`¶ <FunctionLikeMacros>`
A vector of function-like macros whose invocations should be skipped by
``RemoveParentheses``.

.. _IfMacros:

**IfMacros** (``List of Strings``) :versionbadge:`clang-format 13` :ref:`¶ <IfMacros>`
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,8 @@ clang-format
``enum`` enumerator lists.
- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
- Add ``SpaceAfterOperatorKeyword`` option.
- Add ``FunctionLikeMacros`` option so that their invocations are skipped by
``RemoveParentheses``.

clang-refactor
--------------
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2786,6 +2786,11 @@ struct FormatStyle {
/// \version 3.7
std::vector<std::string> ForEachMacros;

/// A vector of function-like macros whose invocations should be skipped by
/// ``RemoveParentheses``.
/// \version 21
std::vector<std::string> FunctionLikeMacros;

tooling::IncludeStyle IncludeStyle;

/// A vector of macros that should be interpreted as conditionals
Expand Down Expand Up @@ -5382,6 +5387,7 @@ struct FormatStyle {
R.ExperimentalAutoDetectBinPacking &&
FixNamespaceComments == R.FixNamespaceComments &&
ForEachMacros == R.ForEachMacros &&
FunctionLikeMacros == R.FunctionLikeMacros &&
IncludeStyle.IncludeBlocks == R.IncludeStyle.IncludeBlocks &&
IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories &&
IncludeStyle.IncludeIsMainRegex ==
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
IO.mapOptional("FunctionLikeMacros", Style.FunctionLikeMacros);
IO.mapOptional("IfMacros", Style.IfMacros);
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ namespace format {
TYPE(FunctionDeclarationName) \
TYPE(FunctionDeclarationLParen) \
TYPE(FunctionLBrace) \
TYPE(FunctionLikeMacro) \
TYPE(FunctionLikeOrFreestandingMacro) \
TYPE(FunctionTypeLParen) \
/* The colons as part of a C11 _Generic selection */ \
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ FormatTokenLexer::FormatTokenLexer(
auto Identifier = &IdentTable.get(ForEachMacro);
Macros.insert({Identifier, TT_ForEachMacro});
}
for (const std::string &FunctionLikeMacro : Style.FunctionLikeMacros) {
auto Identifier = &IdentTable.get(FunctionLikeMacro);
Macros.insert({Identifier, TT_FunctionLikeMacro});
}
for (const std::string &IfMacro : Style.IfMacros) {
auto Identifier = &IdentTable.get(IfMacro);
Macros.insert({Identifier, TT_IfMacro});
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2090,7 +2090,8 @@ class AnnotatingParser {
TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,
TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
TT_CompoundRequirementLBrace, TT_BracedListLBrace)) {
TT_CompoundRequirementLBrace, TT_BracedListLBrace,
TT_FunctionLikeMacro)) {
CurrentToken->setType(TT_Unknown);
}
CurrentToken->Role.reset();
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2579,30 +2579,34 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
/// double ampersands. This applies for all nested scopes as well.
///
/// Returns whether there is a `=` token between the parentheses.
bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,
bool InMacroCall) {
assert(FormatTok->is(tok::l_paren) && "'(' expected.");
auto *LParen = FormatTok;
auto *Prev = FormatTok->Previous;
bool SeenComma = false;
bool SeenEqual = false;
bool MightBeFoldExpr = false;
nextToken();
const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
InMacroCall = true;
do {
switch (FormatTok->Tok.getKind()) {
case tok::l_paren:
if (parseParens(AmpAmpTokenType))
if (parseParens(AmpAmpTokenType, InMacroCall))
SeenEqual = true;
if (Style.isJava() && FormatTok->is(tok::l_brace))
parseChildBlock();
break;
case tok::r_paren: {
auto *Prev = LParen->Previous;
auto *RParen = FormatTok;
nextToken();
if (Prev) {
auto OptionalParens = [&] {
if (MightBeStmtExpr || MightBeFoldExpr || Line->InMacroBody ||
SeenComma || Style.RemoveParentheses == FormatStyle::RPS_Leave ||
if (MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
Line->InMacroBody ||
Style.RemoveParentheses == FormatStyle::RPS_Leave ||
RParen->getPreviousNonComment() == LParen) {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/UnwrappedLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ class UnwrappedLineParser {
bool *HasLabel = nullptr);
bool tryToParseBracedList();
bool parseBracedList(bool IsAngleBracket = false, bool IsEnum = false);
bool parseParens(TokenType AmpAmpTokenType = TT_Unknown);
bool parseParens(TokenType AmpAmpTokenType = TT_Unknown,
bool InMacroCall = false);
void parseSquare(bool LambdaIntroducer = false);
void keepAncestorBraces();
void parseUnbracedBody(bool CheckEOF = false);
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,7 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("StatementMacros: [QUNUSED, QT_REQUIRE_VERSION]", StatementMacros,
std::vector<std::string>({"QUNUSED", "QT_REQUIRE_VERSION"}));

CHECK_PARSE_LIST(FunctionLikeMacros);
CHECK_PARSE_LIST(JavaImportGroups);
CHECK_PARSE_LIST(Macros);
CHECK_PARSE_LIST(NamespaceMacros);
Expand Down
4 changes: 4 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28479,6 +28479,10 @@ TEST_F(FormatTest, RemoveParentheses) {
verifyFormat("MOCK_METHOD(void, Function, (), override);",
"MOCK_METHOD(void, Function, (), (override));", Style);

Style.FunctionLikeMacros.push_back("MOCK_METHOD");
verifyFormat("MOCK_METHOD((int), func, ((std::map<int, int>)), (override));",
Style);

Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
verifyFormat("#define Return0 return (0);", Style);
verifyFormat("return 0;", "return (0);", Style);
Expand Down
Loading