[clang] [clang-format] Add SkipMacroDefinitionBody option (PR #78682)
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 19 00:21:08 PST 2024
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/78682
Closes #67991.
Co-authored-by: @tomekpaszek
>From 620e614b242055c3b8cbd81efd9bbc64a0ee4e56 Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Thu, 18 Jan 2024 23:34:13 -0800
Subject: [PATCH] [clang-format] Option to ignore macro definitions
---
clang/docs/ClangFormatStyleOptions.rst | 5 +
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Format/Format.h | 5 +
clang/lib/Format/Format.cpp | 2 +
clang/lib/Format/UnwrappedLineParser.cpp | 9 ++
clang/unittests/Format/ConfigParseTest.cpp | 1 +
clang/unittests/Format/FormatTest.cpp | 132 +++++++++++++++++++++
7 files changed, 155 insertions(+)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 8bc13e45bf2f5f..4dc0de3a90f265 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:`¶ <SkipMacroDefinitionBody>`
+ Do not format macro definition body.
+
.. _SortIncludes:
**SortIncludes** (``SortIncludesOptions``) :versionbadge:`clang-format 3.8` :ref:`¶ <SortIncludes>`
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b400d75095421c..1045fd6b92346b 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 6fd7947bd21791..bc9eecd42f9ebf 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 7c2f4dcf3d2308..ff326dc784783b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1085,6 +1085,7 @@ template <> struct MappingTraits<FormatStyle> {
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 50d41c9f57a670..c08ce86449b6ea 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 172aaab5988ce5..2a8d79359a49b4 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 c229d9bc56def8..44896c10b0b251 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
More information about the cfe-commits
mailing list