llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-format Author: Owen Pan (owenca) <details> <summary>Changes</summary> This allows RemoveParentheses to skip the invocations of function-like macros. Fixes #<!-- -->68354. Fixes #<!-- -->147780. --- Full diff: https://github.com/llvm/llvm-project/pull/148345.diff 11 Files Affected: - (modified) clang/docs/ClangFormatStyleOptions.rst (+6) - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/include/clang/Format/Format.h (+6) - (modified) clang/lib/Format/Format.cpp (+1) - (modified) clang/lib/Format/FormatToken.h (+1) - (modified) clang/lib/Format/FormatTokenLexer.cpp (+4) - (modified) clang/lib/Format/TokenAnnotator.cpp (+2-1) - (modified) clang/lib/Format/UnwrappedLineParser.cpp (+9-5) - (modified) clang/lib/Format/UnwrappedLineParser.h (+2-1) - (modified) clang/unittests/Format/ConfigParseTest.cpp (+1) - (modified) clang/unittests/Format/FormatTest.cpp (+4) ``````````diff diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index ab374c1886165..b2fb14c1b3011 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -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>` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e81a3d4976cf8..a26b0e4cc8d2c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 -------------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 74b516fe4f071..7e7eb21e2a3ba 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -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 @@ -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 == diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 4956607602be0..30eab05117b76 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -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); diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 94014aee3221f..9252a795a0b5e 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -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 */ \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index d8ee5cb90aaa4..3cdcbd15cd739 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -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}); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index aab8f054655fe..739209a5681f8 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -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(); diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 7e8634aeec4e0..91b8fdc8a3c38 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -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; } diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 2d1492c1a6b8c..8e29680ff244b 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -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); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index aedfdd151d6d3..c2058fb46cc45 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -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); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 944e7c3fb152a..789d822853e26 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -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); `````````` </details> https://github.com/llvm/llvm-project/pull/148345 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits