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

Reply via email to