diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3033,6 +3033,21 @@ Add a space in front of an Objective-C protocol list, i.e. use ``Foo `` instead of ``Foo``. +**PPIndentWidth** (``int``) + The number of columns to use for indentation of preprocessor statements. + When set to -1 (default) ``IndentWidth`` is used also for preprocessor + statements. + + .. code-block:: c++ + + PPIndentWidth: 1 + + #ifdef __linux__ + # define FOO + #else + # define BAR + #endif + **PenaltyBreakAssignment** (``unsigned``) The penalty for breaking around an assignment operator. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -233,6 +233,9 @@ - Option ``IndentAccessModifiers`` has been added to be able to give access modifiers their own indentation level inside records. +- Option ``PPIndentWidth`` has been added to be able to configure pre-processor + indentation independent from regular code. + - Option ``ShortNamespaceLines`` has been added to give better control over ``FixNamespaceComments`` when determining a namespace length. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2666,6 +2666,20 @@ /// Pointer and reference alignment style. PointerAlignmentStyle PointerAlignment; + /// The number of columns to use for indentation of preprocessor statements. + /// When set to -1 (default) ``IndentWidth`` is used also for preprocessor + /// statements. + /// \code + /// PPIndentWidth: 1 + /// + /// #ifdef __linux__ + /// # define FOO + /// #else + /// # define BAR + /// #endif + /// \endcode + int PPIndentWidth; + /// See documentation of ``RawStringFormats``. struct RawStringFormat { /// The language of this raw string. diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -665,6 +665,7 @@ IO.mapOptional("PenaltyIndentedWhitespace", Style.PenaltyIndentedWhitespace); IO.mapOptional("PointerAlignment", Style.PointerAlignment); + IO.mapOptional("PPIndentWidth", Style.PPIndentWidth); IO.mapOptional("RawStringFormats", Style.RawStringFormats); IO.mapOptional("ReflowComments", Style.ReflowComments); IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); @@ -1022,6 +1023,7 @@ LLVMStyle.IndentRequires = false; LLVMStyle.IndentWrappedFunctionNames = false; LLVMStyle.IndentWidth = 2; + LLVMStyle.PPIndentWidth = -1; LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.JavaScriptWrapImports = true; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,9 @@ while (IndentForLevel.size() <= Line.Level) IndentForLevel.push_back(-1); if (Line.InPPDirective) { - Indent = Line.Level * Style.IndentWidth + AdditionalIndent; + unsigned IndentWidth = + (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth; + Indent = Line.Level * IndentWidth + AdditionalIndent; } else { IndentForLevel.resize(Line.Level + 1); Indent = getIndent(IndentForLevel, Line.Level); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3453,6 +3453,48 @@ verifyFormat("a\f\\"); } +TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) { + FormatStyle style = getChromiumStyle(FormatStyle::LK_Cpp); + style.IndentWidth = 4; + style.PPIndentWidth = 1; + + style.IndentPPDirectives = FormatStyle::PPDIS_None; + verifyFormat("#ifdef __linux__\n" + "void foo() {\n" + " int x = 0;\n" + "}\n" + "#define FOO\n" + "#endif\n" + "void bar() {\n" + " int y = 0;\n" + "}\n", + style); + + style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash; + verifyFormat("#ifdef __linux__\n" + "void foo() {\n" + " int x = 0;\n" + "}\n" + "# define FOO foo\n" + "#endif\n" + "void bar() {\n" + " int y = 0;\n" + "}\n", + style); + + style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash; + verifyFormat("#ifdef __linux__\n" + "void foo() {\n" + " int x = 0;\n" + "}\n" + " #define FOO foo\n" + "#endif\n" + "void bar() {\n" + " int y = 0;\n" + "}\n", + style); +} + TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) { verifyFormat("#define A(BB)", getLLVMStyleWithColumns(13)); verifyFormat("#define A( \\\n BB)", getLLVMStyleWithColumns(12));