llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Gedare Bloom (gedare) <details> <summary>Changes</summary> Allow an option to leave preprocessor directive indenting as-is. This simplifies handling mixed styles of CPP directive indentation. Fixes #<!-- -->38511 --- Full diff: https://github.com/llvm/llvm-project/pull/139750.diff 9 Files Affected: - (modified) clang/docs/ClangFormatStyleOptions.rst (+15) - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/include/clang/Format/Format.h (+13-1) - (modified) clang/lib/Format/ContinuationIndenter.cpp (+6) - (modified) clang/lib/Format/Format.cpp (+1) - (modified) clang/lib/Format/TokenAnnotator.cpp (+2-1) - (modified) clang/lib/Format/UnwrappedLineFormatter.cpp (+12-5) - (modified) clang/lib/Format/UnwrappedLineParser.cpp (+6-3) - (modified) clang/unittests/Format/FormatTest.cpp (+61-15) ``````````diff diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index a4c381bf583b6..99058bece63a0 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4423,6 +4423,21 @@ the configuration (without a prefix: ``Auto``). #endif #endif + * ``PPDIS_Leave`` (in configuration: ``Leave``) + Leaves indentation of directives as-is. + + .. note:: + + Ignores ``PPIndentWidth``. + + .. code-block:: c++ + + #if FOO + #if BAR + #include <foo> + #endif + #endif + .. _IndentRequiresClause: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bc13d02e2d20b..7baca95c8aea5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -844,6 +844,7 @@ clang-format ``enum`` enumerator lists. - Add ``OneLineFormatOffRegex`` option for turning formatting off for one line. - Add ``SpaceAfterOperatorKeyword`` option. +- Add ``Leave`` suboption to ``IndentPPDirectives``. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index b86c4bd00eb91..07859bb7de68d 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2976,7 +2976,19 @@ struct FormatStyle { /// #endif /// #endif /// \endcode - PPDIS_BeforeHash + PPDIS_BeforeHash, + /// Leaves indentation of directives as-is. + /// \note + /// Ignores ``PPIndentWidth``. + /// \endnote + /// \code + /// #if FOO + /// #if BAR + /// #include <foo> + /// #endif + /// #endif + /// \endcode + PPDIS_Leave }; /// The preprocessor directive indenting style to use. diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 55e1d1ceb55b7..06e3dda7a9c74 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -764,6 +764,12 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces; + if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave && + State.Line->InPPDirective && Previous.is(tok::hash) && + &Previous == State.Line->First) { + Spaces += Current.OriginalColumn - Previous.OriginalColumn - 1; + } + // Indent preprocessor directives after the hash if required. int PPColumnCorrection = 0; if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 20b5352b83a9e..c8ec30c33fdfd 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -514,6 +514,7 @@ struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { IO.enumCase(Value, "None", FormatStyle::PPDIS_None); IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); + IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave); } }; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 542c362ccacae..520cec52465c9 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3622,7 +3622,8 @@ void TokenAnnotator::setCommentLineLevels( // Align comments for preprocessor lines with the # in column 0 if // preprocessor lines are not indented. Otherwise, align with the next // line. - Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash && + Line->Level = (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash || + Style.IndentPPDirectives == FormatStyle::PPDIS_None) && PPDirectiveOrImportStmt ? 0 : NextNonCommentLine->Level; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 1298e3e7bab38..afd37cb71137b 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -62,10 +62,16 @@ class LevelIndentTracker { // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) IndentForLevel.resize(Line.Level + 1, -1); - if (Style.IndentPPDirectives != FormatStyle::PPDIS_None && - (Line.InPPDirective || - (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && - Line.Type == LT_CommentAbovePPDirective))) { + if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave && + Line.InPPDirective) { + Indent = Line.InMacroBody + ? (Line.Level - Line.PPLevel) * Style.IndentWidth + + AdditionalIndent + : Line.First->OriginalColumn; + } else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None && + (Line.InPPDirective || + (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && + Line.Type == LT_CommentAbovePPDirective))) { unsigned PPIndentWidth = (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth; Indent = Line.InMacroBody @@ -1651,7 +1657,8 @@ void UnwrappedLineFormatter::formatFirstToken( // Preprocessor directives get indented before the hash only if specified. In // Javascript import statements are indented like normal statements. if (!Style.isJavaScript() && - Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash && + (Style.IndentPPDirectives == FormatStyle::PPDIS_None || + Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash) && (Line.Type == LT_PreprocessorDirective || Line.Type == LT_ImportStatement)) { Indent = 0; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 2e138ff7ef59c..dd8e8bde126d3 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -164,7 +164,8 @@ UnwrappedLineParser::UnwrappedLineParser( LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr), Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), - IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None + IncludeGuard((Style.IndentPPDirectives == FormatStyle::PPDIS_None || + Style.IndentPPDirectives == FormatStyle::PPDIS_Leave) ? IG_Rejected : IG_Inited), IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn), @@ -172,7 +173,8 @@ UnwrappedLineParser::UnwrappedLineParser( void UnwrappedLineParser::reset() { PPBranchLevel = -1; - IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None + IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None || + Style.IndentPPDirectives == FormatStyle::PPDIS_Leave ? IG_Rejected : IG_Inited; IncludeGuardToken = nullptr; @@ -1142,7 +1144,8 @@ void UnwrappedLineParser::parsePPEndIf() { // If the #endif of a potential include guard is the last thing in the file, // then we found an include guard. if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() && - Style.IndentPPDirectives != FormatStyle::PPDIS_None) { + !(Style.IndentPPDirectives == FormatStyle::PPDIS_None || + Style.IndentPPDirectives == FormatStyle::PPDIS_Leave)) { IncludeGuard = IG_Found; } } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 436beaf68bd2a..3908dc7536813 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5522,7 +5522,6 @@ TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) { " x; \\\n" " }", style); - style.PPIndentWidth = 2; verifyFormat("#ifdef foo\n" "#define bar() \\\n" @@ -5542,22 +5541,55 @@ TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) { "#endif", style); + style.IndentPPDirectives = FormatStyle::PPDIS_Leave; + style.IndentWidth = 4; + verifyNoChange("#ifndef foo\n" + "#define foo\n" + "if (emacs) {\n" + "#ifdef is\n" + "#define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}\n" + "#endif", + style); + verifyNoChange("#ifndef foo\n" + " #define foo\n" + "if (emacs) {\n" + " #ifdef is\n" + "#define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + " #endif\n" + "}\n" + "#endif", + style); + verifyNoChange(" #ifndef foo\n" + "# define foo\n" + "if (emacs) {\n" + "#ifdef is\n" + " # define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}\n" + " #endif", + style); + style.IndentWidth = 1; style.PPIndentWidth = 4; - verifyFormat("#if 1\n" - "#define X \\\n" - " { \\\n" - " x; \\\n" - " x; \\\n" - " }\n" - "#endif", - style); - verifyFormat("#define X \\\n" - " { \\\n" - " x; \\\n" - " x; \\\n" - " }", - style); + verifyNoChange("# if 1\n" + " #define X \\\n" + " { \\\n" + " x; \\\n" + " x; \\\n" + " }\n" + "# endif", + style); style.IndentWidth = 4; style.PPIndentWidth = 1; @@ -25843,6 +25875,20 @@ TEST_F(FormatTest, SkipMacroDefinitionBody) { "a", Style); + Style.IndentPPDirectives = FormatStyle::PPDIS_Leave; + verifyNoChange("#if A\n" + "#define A a\n" + "#endif", + Style); + verifyNoChange("#if A\n" + " #define A a\n" + "#endif", + Style); + verifyNoChange("#if A\n" + "# define A a\n" + "#endif", + Style); + // Adjust indendations but don't change the definition. Style.IndentPPDirectives = FormatStyle::PPDIS_None; verifyNoChange("#if A\n" `````````` </details> https://github.com/llvm/llvm-project/pull/139750 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits