diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 8bc13e45bf2f5..4dc0de3a90f26 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4999,6 +4999,11 @@ the configuration (without a prefix: ``Auto``). int bar; int bar; } // namespace b } // namespace b +.. _SkipMacroDefinitionBody: + +**SkipMacroDefinitionBody** (``Boolean``) :versionbadge:`clang-format 18` :ref:`¶ ` + Do not format macro definition body. + .. _SortIncludes: **SortIncludes** (``SortIncludesOptions``) :versionbadge:`clang-format 3.8` :ref:`¶ ` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b400d75095421..1045fd6b92346 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1202,6 +1202,7 @@ clang-format - Add ``PenaltyBreakScopeResolution`` option. - Add ``.clang-format-ignore`` files. - Add ``AlignFunctionPointers`` sub-option for ``AlignConsecutiveDeclarations``. +- Add ``SkipMacroDefinitionBody`` option. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 6fd7947bd2179..bc9eecd42f9eb 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -3932,6 +3932,10 @@ struct FormatStyle { /// \version 13 unsigned ShortNamespaceLines; + /// Do not format macro definition body. + /// \version 18 + bool SkipMacroDefinitionBody; + /// Include sorting options. enum SortIncludesOptions : int8_t { /// Includes are never sorted. @@ -4895,6 +4899,7 @@ struct FormatStyle { RequiresExpressionIndentation == R.RequiresExpressionIndentation && SeparateDefinitionBlocks == R.SeparateDefinitionBlocks && ShortNamespaceLines == R.ShortNamespaceLines && + SkipMacroDefinitionBody == R.SkipMacroDefinitionBody && SortIncludes == R.SortIncludes && SortJavaStaticImport == R.SortJavaStaticImport && SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 7c2f4dcf3d230..ff326dc784783 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1085,6 +1085,7 @@ template <> struct MappingTraits { Style.RequiresExpressionIndentation); IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks); IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); + IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody); IO.mapOptional("SortIncludes", Style.SortIncludes); IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); @@ -1556,6 +1557,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; LLVMStyle.ShortNamespaceLines = 1; + LLVMStyle.SkipMacroDefinitionBody = false; LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 50d41c9f57a67..c08ce86449b6e 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1170,6 +1170,15 @@ void UnwrappedLineParser::parsePPDefine() { assert((int)Line->PPLevel >= 0); Line->InMacroBody = true; + if (Style.SkipMacroDefinitionBody) { + do { + FormatTok->Finalized = true; + nextToken(); + } while (!eof()); + addUnwrappedLine(); + return; + } + if (FormatTok->is(tok::identifier) && Tokens->peekNextToken()->is(tok::colon)) { nextToken(); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 172aaab5988ce..2a8d79359a49b 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -184,6 +184,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(ReflowComments); CHECK_PARSE_BOOL(RemoveBracesLLVM); CHECK_PARSE_BOOL(RemoveSemicolon); + CHECK_PARSE_BOOL(SkipMacroDefinitionBody); CHECK_PARSE_BOOL(SpacesInSquareBrackets); CHECK_PARSE_BOOL(SpaceInEmptyBlock); CHECK_PARSE_BOOL(SpacesInContainerLiterals); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index c229d9bc56def..44896c10b0b25 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24387,6 +24387,138 @@ TEST_F(FormatTest, WhitespaceSensitiveMacros) { verifyNoChange("FOO(String-ized&Messy+But: :Still=Intentional);", Style); } +TEST_F(FormatTest, SkipMacroDefinitionBody) { + auto Style = getLLVMStyle(); + Style.SkipMacroDefinitionBody = true; + + verifyFormat("#define A", "#define A", Style); + verifyFormat("#define A a aa", "#define A a aa", Style); + verifyNoChange("#define A b", Style); + verifyNoChange("#define A ( args )", Style); + verifyNoChange("#define A ( args ) = func ( args )", Style); + verifyNoChange("#define A ( args ) { int a = 1 ; }", Style); + verifyNoChange("#define A ( args ) \\\n" + " {\\\n" + " int a = 1 ;\\\n" + "}", + Style); + + verifyNoChange("#define A x:", Style); + verifyNoChange("#define A a. b", Style); + + // Surrounded with formatted code. + verifyFormat("int a;\n" + "#define A a\n" + "int a;", + "int a ;\n" + "#define A a\n" + "int a ;", + Style); + + // Columns are not broken when a limit is set. + Style.ColumnLimit = 10; + verifyFormat("#define A a a a a", " # define A a a a a ", Style); + verifyNoChange("#define A a a a a", Style); + + Style.ColumnLimit = 15; + verifyFormat("#define A // a\n" + " // very\n" + " // long\n" + " // comment", + "#define A //a very long comment", Style); + Style.ColumnLimit = 0; + + // Multiline definition. + verifyNoChange("#define A \\\n" + "Line one with spaces . \\\n" + " Line two.", + Style); + verifyNoChange("#define A \\\n" + "a a \\\n" + "a \\\n" + "a", + Style); + Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; + verifyNoChange("#define A \\\n" + "a a \\\n" + "a \\\n" + "a", + Style); + Style.AlignEscapedNewlines = FormatStyle::ENAS_Right; + verifyNoChange("#define A \\\n" + "a a \\\n" + "a \\\n" + "a", + Style); + + // Adjust indendations but don't change the definition. + Style.IndentPPDirectives = FormatStyle::PPDIS_None; + verifyNoChange("#if A\n" + "#define A a\n" + "#endif", + Style); + verifyFormat("#if A\n" + "#define A a\n" + "#endif", + "#if A\n" + " #define A a\n" + "#endif", + Style); + Style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash; + verifyNoChange("#if A\n" + "# define A a\n" + "#endif", + Style); + verifyFormat("#if A\n" + "# define A a\n" + "#endif", + "#if A\n" + " #define A a\n" + "#endif", + Style); + Style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash; + verifyNoChange("#if A\n" + " #define A a\n" + "#endif", + Style); + verifyFormat("#if A\n" + " #define A a\n" + "#endif", + "#if A\n" + " # define A a\n" + "#endif", + Style); + + Style.IndentPPDirectives = FormatStyle::PPDIS_None; + // SkipMacroDefinitionBody should not affect other PP directives + verifyFormat("#if !defined(A)\n" + "#define A a\n" + "#endif", + "#if ! defined ( A )\n" + " #define A a\n" + "#endif", + Style); + + // With comments. + verifyFormat("/* */ #define A a // a a", "/* */ # define A a // a a", + Style); + verifyNoChange("/* */ #define A a // a a", Style); + + verifyFormat("int a; // a\n" + "#define A // a\n" + "int aaa; // a", + "int a; // a\n" + "#define A // a\n" + "int aaa; // a", + Style); + + // multiline macro definitions + verifyNoChange("#define A a\\\n" + " A a \\\n " + " A a", + Style); +} + TEST_F(FormatTest, VeryLongNamespaceCommentSplit) { // These tests are not in NamespaceEndCommentsFixerTest because that doesn't // test its interaction with line wrapping