[clang-format] Option to ignore macro definitions by tomekpaszek · Pull Request #70338 · llvm/llvm-project (original) (raw)
@llvm/pr-subscribers-clang
Author: Tomek (tomekpaszek)
Changes
Sometimes macro definitions contain a layout we don't want to change in any context. This PR adds a new style option IgnorePPDefinitions that prevents clang-format from touching PP directives.
This PR addresses issue #67991
Full diff: https://github.com/llvm/llvm-project/pull/70338.diff
7 Files Affected:
- (modified) clang/docs/ClangFormatStyleOptions.rst (+5)
- (modified) clang/include/clang/Format/Format.h (+5)
- (modified) clang/lib/Format/Format.cpp (+2)
- (modified) clang/lib/Format/UnwrappedLineFormatter.cpp (+2)
- (modified) clang/lib/Format/UnwrappedLineParser.cpp (+8)
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+1)
- (modified) clang/unittests/Format/FormatTest.cpp (+47)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 21342e1b89ea866..80565620d8f24bf 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3160,6 +3160,11 @@ the configuration (without a prefix: Auto).
For example: KJ_IF_MAYBE <https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes>_
+.. _IgnorePPDefinitions:
+
+IgnorePPDefinitions (Boolean) :versionbadge:clang-format 18 :ref:¶ <IgnorePPDefinitions>
Ignore formatting in preprocessor definitions.
.. _IncludeBlocks:
IncludeBlocks (
IncludeBlocksStyle) :versionbadge:clang-format 6:ref:¶ <IncludeBlocks>
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 3e9d1915badd87f..3af7241441c8b13 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2442,6 +2442,10 @@ struct FormatStyle { /// https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes`_ /// \version 13 std::vectorstd::string IfMacros;
/// Ignore formatting in preprocessor definitions.
/// \version 18
bool IgnorePPDefinitions;
/// Specify whether access modifiers should have their own indentation level. ///
@@ -4719,6 +4723,7 @@ struct FormatStyle { R.IncludeStyle.IncludeIsMainRegex && IncludeStyle.IncludeIsMainSourceRegex == R.IncludeStyle.IncludeIsMainSourceRegex &&
IgnorePPDefinitions == R.IgnorePPDefinitions && IndentAccessModifiers == R.IndentAccessModifiers && IndentCaseBlocks == R.IndentCaseBlocks && IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index edb33f4af4defef..6e5ec754dfdcdd9 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1000,6 +1000,7 @@ template <> struct MappingTraits { IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); IO.mapOptional("ForEachMacros", Style.ForEachMacros); IO.mapOptional("IfMacros", Style.IfMacros);
- IO.mapOptional("IgnorePPDefinitions", Style.IgnorePPDefinitions); IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks); IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories); IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); @@ -1504,6 +1505,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
- LLVMStyle.IgnorePPDefinitions = false; LLVMStyle.IncludeStyle.IncludeCategories = { {"^"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, {"^(<|"(gtest|gmock|isl|json)/)", 3, 0, false},
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 280485d9a90d1bf..bbf6383ff7673f6 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1355,6 +1355,8 @@ unsigned UnwrappedLineFormatter::format( bool FixIndentation = (FixBadIndentation || ContinueFormatting) && Indent != TheLine.First->OriginalColumn; bool ShouldFormat = TheLine.Affected || FixIndentation;
if (Style.IgnorePPDefinitions && TheLine.Type == LT_PreprocessorDirective)
ShouldFormat = false;// We cannot format this line; if the reason is that the line had a // parsing error, remember that. if (ShouldFormat && TheLine.Type == LT_Invalid && Status) { diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 488d8dc07b1eae3..07cf966a08ff5e5 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1134,6 +1134,14 @@ void UnwrappedLineParser::parsePPDefine() { return; }
if (Style.IgnorePPDefinitions) {
do {
nextToken();} while (!eof());
addUnwrappedLine();
return;
}
if (IncludeGuard == IG_IfNdefed && IncludeGuardToken->TokenText == FormatTok->TokenText) { IncludeGuard = IG_Defined;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index f90ed178d99c286..7ce9ae26b36fbb9 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -166,6 +166,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(DerivePointerAlignment); CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding"); CHECK_PARSE_BOOL(DisableFormat);
- CHECK_PARSE_BOOL(IgnorePPDefinitions); CHECK_PARSE_BOOL(IndentAccessModifiers); CHECK_PARSE_BOOL(IndentCaseLabels); CHECK_PARSE_BOOL(IndentCaseBlocks); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index b2d84f2ee389551..19cf521107c604b 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24153,6 +24153,53 @@ TEST_F(FormatTest, WhitespaceSensitiveMacros) { verifyNoChange("FOO(String-ized&Messy+But: :Still=Intentional);", Style); }
+TEST_F(FormatTest, IgnorePPDefinitions) {
- FormatStyle Style = getLLVMStyle();
- Style.IgnorePPDefinitions = true;
- verifyNoChange("#define A", Style);
- verifyNoChange("#define A b", Style);
- verifyNoChange("#define A ( args )", Style);
- verifyNoChange("#define A ( args ) = func ( args )", 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;
- verifyNoChange("#define A a a a a", 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 \\\na",Style);- Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
- verifyNoChange("#define A \\n"
"a a \\\n""a \\\na",Style);- Style.AlignEscapedNewlines = FormatStyle::ENAS_Right;
- verifyNoChange("#define A \\n"
"a a \\\n""a \\\na",Style);
+} + TEST_F(FormatTest, VeryLongNamespaceCommentSplit) { // These tests are not in NamespaceEndCommentsFixerTest because that doesn't // test its interaction with line wrapping