https://github.com/turgu1 updated 
https://github.com/llvm/llvm-project/pull/186686

>From c25fdac05571a44bb9c7e7ec297f7d50afe549c6 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sat, 14 Mar 2026 21:07:36 -0400
Subject: [PATCH 01/11] A new IndentPPDirectives style: BeforeHashWithCode

---
 clang/include/clang/Format/Format.h         | 13 ++++
 clang/lib/Format/Format.cpp                 |  1 +
 clang/lib/Format/FormatTokenSource.h        |  5 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp | 13 +++-
 clang/lib/Format/UnwrappedLineFormatter.h   |  3 +-
 clang/lib/Format/UnwrappedLineParser.cpp    | 68 +++++++++++++++++----
 6 files changed, 86 insertions(+), 17 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index aea18a836328f..cb25b3a82cd5c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3247,6 +3247,19 @@ struct FormatStyle {
     ///    #endif
     /// \endcode
     PPDIS_BeforeHash,
+    /// Indents directives before the hash with the current code indentation
+    /// level.
+    /// \code
+    ///    if (foo)
+    ///    {
+    ///      #if FOO
+    ///        #if BAR
+    ///          #include <foo>
+    ///        #endif
+    ///      #endif
+    ///    }
+    /// \endcode
+    PPDIS_BeforeHashWithCode,
     /// Leaves indentation of directives as-is.
     /// \note
     ///  Ignores ``PPIndentWidth``.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b98a9086811cd..563c9ba03adf2 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -622,6 +622,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, "BeforeHashWithCode", 
FormatStyle::PPDIS_BeforeHashWithCode);
     IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);
   }
 };
diff --git a/clang/lib/Format/FormatTokenSource.h 
b/clang/lib/Format/FormatTokenSource.h
index 8f00e5f4582c6..7ab49542ef099 100644
--- a/clang/lib/Format/FormatTokenSource.h
+++ b/clang/lib/Format/FormatTokenSource.h
@@ -191,14 +191,15 @@ class IndexedTokenSource : public FormatTokenSource {
 class ScopedMacroState : public FormatTokenSource {
 public:
   ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
-                   FormatToken *&ResetToken)
+                   FormatToken *&ResetToken, bool PreserveLevel = false)
       : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
         PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
         Token(nullptr), PreviousToken(nullptr) {
     FakeEOF.Tok.startToken();
     FakeEOF.Tok.setKind(tok::eof);
     TokenSource = this;
-    Line.Level = 0;
+    if (!PreserveLevel)
+      Line.Level = 0;
     Line.InPPDirective = true;
     // InMacroBody gets set after the `#define x` part.
   }
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 74c0f4bf75721..f3b1510e3f687 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -68,6 +68,12 @@ class LevelIndentTracker {
                    ? (Line.Level - Line.PPLevel) * Style.IndentWidth +
                          AdditionalIndent
                    : Line.First->OriginalColumn;
+    } else if (Style.IndentPPDirectives == 
FormatStyle::PPDIS_BeforeHashWithCode &&
+               Line.InPPDirective && !Line.InMacroBody) {
+      // For BeforeHashWithCode, PP directives are indented at the surrounding
+      // code level, using the same indentation as regular code (not 
PPIndentWidth).
+      Indent = getIndent(Line.Level);
+      Indent += AdditionalIndent;
     } else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
                (Line.InPPDirective ||
                 (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
@@ -1467,7 +1473,8 @@ unsigned UnwrappedLineFormatter::format(
       if (!DryRun) {
         bool LastLine = TheLine.First->is(tok::eof);
         formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent,
-                         LastLine ? LastStartColumn : NextStartColumn + 
Indent);
+                         LastLine ? LastStartColumn : NextStartColumn + Indent,
+                         0);
       }
 
       NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
@@ -1516,7 +1523,7 @@ unsigned UnwrappedLineFormatter::format(
         if (ReformatLeadingWhitespace) {
           formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
                            TheLine.First->OriginalColumn,
-                           TheLine.First->OriginalColumn);
+                           TheLine.First->OriginalColumn, 0);
         } else {
           Whitespaces->addUntouchableToken(*TheLine.First,
                                            TheLine.InPPDirective);
@@ -1649,7 +1656,7 @@ void UnwrappedLineFormatter::formatFirstToken(
     const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
     const AnnotatedLine *PrevPrevLine,
     const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
-    unsigned NewlineIndent) {
+    unsigned NewlineIndent, unsigned PPNestingLevel) {
   FormatToken &RootToken = *Line.First;
   if (RootToken.is(tok::eof)) {
     unsigned Newlines = std::min(
diff --git a/clang/lib/Format/UnwrappedLineFormatter.h 
b/clang/lib/Format/UnwrappedLineFormatter.h
index 9b8acf427a2a0..17889d03644b6 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/clang/lib/Format/UnwrappedLineFormatter.h
@@ -47,7 +47,8 @@ class UnwrappedLineFormatter {
                         const AnnotatedLine *PreviousLine,
                         const AnnotatedLine *PrevPrevLine,
                         const SmallVectorImpl<AnnotatedLine *> &Lines,
-                        unsigned Indent, unsigned NewlineIndent);
+                        unsigned Indent, unsigned NewlineIndent,
+                        unsigned PPNestingLevel = 0);
 
   /// Returns the column limit for a line, taking into account whether we
   /// need an escaped newline due to a continued preprocessor directive.
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index ddf584c6ed818..c3ad21cf5291e 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -998,7 +998,12 @@ void UnwrappedLineParser::parseChildBlock() {
 
 void UnwrappedLineParser::parsePPDirective() {
   assert(FormatTok->is(tok::hash) && "'#' expected");
-  ScopedMacroState MacroState(*Line, Tokens, FormatTok);
+  // For BeforeHashWithCode, PP directives are indented at the surrounding code
+  // level. Preserving Line->Level allows ScopedMacroState to keep the code
+  // context level instead of resetting it to 0.
+  const bool PreserveLevel =
+      Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode;
+  ScopedMacroState MacroState(*Line, Tokens, FormatTok, PreserveLevel);
 
   nextToken();
 
@@ -4639,7 +4644,27 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel 
AdjustLevel) {
     // At the top level we only get here when no unexpansion is going on, or
     // when conditional formatting led to unfinished macro reconstructions.
     assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty());
+    // For BeforeHashWithCode, code lines inside PP conditional blocks must be
+    // indented by the PP nesting depth so that code appears more indented than
+    // its enclosing PP directive (mirroring how C++ block content is indented
+    // relative to the opening brace). PP directive lines already have
+    // PPBranchLevel+1 added in parsePPUnknown; code lines need the same
+    // treatment. We temporarily adjust Level here and restore it afterwards so
+    // that the next line still starts from the correct C++ brace level.
+    // For BeforeHashWithCode, code lines inside PP blocks need their level
+    // raised to match the enclosing PP directive's nesting depth. Using
+    // Line->PPLevel (set at first-token push time) instead of the current
+    // PPBranchLevel, which may have been altered by later PP directives that
+    // readToken processed after the code tokens but before addUnwrappedLine.
+    const bool BWHCCodeLine =
+        Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
+        !Line->InPPDirective && Line->PPLevel > 0;
+    const unsigned PPAdj = BWHCCodeLine ? Line->PPLevel : 0;
+    if (BWHCCodeLine)
+      Line->Level += PPAdj;
     CurrentLines->push_back(std::move(*Line));
+    if (BWHCCodeLine)
+      Line->Level -= PPAdj;
   }
   Line->Tokens.clear();
   Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
@@ -4926,16 +4951,28 @@ void UnwrappedLineParser::readToken(int 
LevelDifference) {
       // directives only after that unwrapped line was finished later.
       bool SwitchToPreprocessorLines = !Line->Tokens.empty();
       ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
-      assert((LevelDifference >= 0 ||
-              static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
-             "LevelDifference makes Line->Level negative");
-      Line->Level += LevelDifference;
-      // Comments stored before the preprocessor directive need to be output
-      // before the preprocessor directive, at the same level as the
-      // preprocessor directive, as we consider them to apply to the directive.
-      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
-          PPBranchLevel > 0) {
-        Line->Level += PPBranchLevel;
+      // For BeforeHashWithCode, the PP directive is indented at the 
surrounding
+      // code level. Apply LevelDifference to get the correct code context 
level
+      // (e.g. leaving a block), but do NOT apply PPBranchLevel since PP
+      // directives should align with the code rather than nesting PP levels.
+      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode) {
+        assert((LevelDifference >= 0 ||
+                static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
+               "LevelDifference makes Line->Level negative");
+        Line->Level += LevelDifference;
+      } else {
+        assert((LevelDifference >= 0 ||
+                static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
+              "LevelDifference makes Line->Level negative");
+        Line->Level += LevelDifference;
+        // Comments stored before the preprocessor directive need to be output
+        // before the preprocessor directive, at the same level as the
+        // preprocessor directive, as we consider them to apply to the
+        // directive.
+       if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
+            PPBranchLevel > 0) {
+          Line->Level += PPBranchLevel;
+        }
       }
       assert(Line->Level >= Line->UnbracedBodyLevel);
       Line->Level -= Line->UnbracedBodyLevel;
@@ -5111,6 +5148,15 @@ UnwrappedLineParser::parseMacroCall() {
 }
 
 void UnwrappedLineParser::pushToken(FormatToken *Tok) {
+  // For BeforeHashWithCode style, record the actual PP nesting depth when the
+  // first token of a code (non-PP) line is pushed. This captures the true PP
+  // context at line-start time, before readToken may subsequently process
+  // more PP directives and change PPBranchLevel before addUnwrappedLine.
+  if (Line->Tokens.empty() && !Line->InPPDirective &&
+      Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode) {
+    Line->PPLevel =
+        PPBranchLevel >= 0 ? static_cast<unsigned>(PPBranchLevel + 1) : 0;
+  }
   Line->Tokens.push_back(UnwrappedLineNode(Tok));
   if (AtEndOfPPLine) {
     auto &Tok = *Line->Tokens.back().Tok;

>From 43a5fe4b85a2c30096722ea92d683fa75df54b2f Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 13:23:36 -0400
Subject: [PATCH 02/11] Some correction

---
 clang/lib/Format/UnwrappedLineFormatter.cpp |  6 +-
 clang/lib/Format/UnwrappedLineParser.cpp    | 67 ++++++++++++++++++++-
 2 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index f3b1510e3f687..ad55a9ee678ea 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -68,10 +68,12 @@ class LevelIndentTracker {
                    ? (Line.Level - Line.PPLevel) * Style.IndentWidth +
                          AdditionalIndent
                    : Line.First->OriginalColumn;
-    } else if (Style.IndentPPDirectives == 
FormatStyle::PPDIS_BeforeHashWithCode &&
+    } else if (Style.IndentPPDirectives ==
+                   FormatStyle::PPDIS_BeforeHashWithCode &&
                Line.InPPDirective && !Line.InMacroBody) {
       // For BeforeHashWithCode, PP directives are indented at the surrounding
-      // code level, using the same indentation as regular code (not 
PPIndentWidth).
+      // code level, using the same indentation as regular code (not
+      // PPIndentWidth).
       Indent = getIndent(Line.Level);
       Indent += AdditionalIndent;
     } else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index c3ad21cf5291e..34aa92b31f79b 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1237,6 +1237,18 @@ void UnwrappedLineParser::parsePPUnknown() {
     nextToken();
   if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
     Line->Level += PPBranchLevel + 1;
+  // For BeforeHashWithCode, PP directives inside unreachable branches must
+  // not be emitted: in multi-pass formatting the surrounding C++ braces may
+  // have been skipped (PP_Unreachable code is not parsed), leaving
+  // Line->Level too low.  The resulting incorrect replacement would conflict
+  // with the correct one produced by the reachable pass, causing an
+  // "overlapping replacement" error and an empty output.  Simply discard the
+  // accumulated tokens so the reachable pass wins.
+  if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
+      !PPStack.empty() && PPStack.back().Kind == PP_Unreachable) {
+    Line->Tokens.clear();
+    return;
+  }
   addUnwrappedLine();
 }
 
@@ -2524,11 +2536,30 @@ bool UnwrappedLineParser::parseBracedList(bool 
IsAngleBracket, bool IsEnum) {
         parseChildBlock();
       }
     }
+    // For BeforeHashWithCode enum bodies: whenever readToken just processed a
+    // PP directive and returned the first post-PP token (AtEndOfPPLine=true),
+    // flush the accumulated pre-PP body tokens as their own UnwrappedLine.
+    // This gives each PP-separated segment its own line so the BWHCCodeLine
+    // level-boost in addUnwrappedLine can apply the correct indentation.
+    if (IsEnum && !IsAngleBracket &&
+        Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
+        Style.AllowShortEnumsOnASingleLine && AtEndOfPPLine &&
+        !Line->Tokens.empty()) {
+      addUnwrappedLine();
+    }
     if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
       if (IsEnum) {
         FormatTok->setBlockKind(BK_Block);
-        if (!Style.AllowShortEnumsOnASingleLine)
+        if (!Style.AllowShortEnumsOnASingleLine) {
+          addUnwrappedLine();
+        } else if (Style.IndentPPDirectives ==
+                       FormatStyle::PPDIS_BeforeHashWithCode &&
+                   !Line->Tokens.empty()) {
+          // For BeforeHashWithCode, flush any remaining enum body tokens
+          // before the closing brace so they get their own UnwrappedLine
+          // with the correct indentation level.
           addUnwrappedLine();
+        }
       }
       nextToken();
       return !HasError;
@@ -3885,10 +3916,20 @@ bool UnwrappedLineParser::parseEnum() {
   if (!Style.AllowShortEnumsOnASingleLine) {
     addUnwrappedLine();
     Line->Level += 1;
+  } else if (Style.IndentPPDirectives ==
+             FormatStyle::PPDIS_BeforeHashWithCode) {
+    // For BeforeHashWithCode, flush the enum declaration as its own
+    // UnwrappedLine (like AllowShortEnumsOnASingleLine=false does) so that
+    // body tokens start in a fresh line.  Each PP-separated segment of the
+    // body can then be emitted at its correct indentation via BWHCCodeLine.
+    addUnwrappedLine();
+    ++Line->Level;
   }
   bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true);
   if (!Style.AllowShortEnumsOnASingleLine)
     Line->Level -= 1;
+  else if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode)
+    --Line->Level;
   if (HasError) {
     if (FormatTok->is(tok::semi))
       nextToken();
@@ -4950,6 +4991,9 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
       // If there is an unfinished unwrapped line, we flush the preprocessor
       // directives only after that unwrapped line was finished later.
       bool SwitchToPreprocessorLines = !Line->Tokens.empty();
+      // Save CurrentLines before ScopedLineState may switch it to
+      // PreprocessorDirectives, so we can detect child-block contexts later.
+      const auto *OrigCurrentLines = CurrentLines;
       ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
       // For BeforeHashWithCode, the PP directive is indented at the 
surrounding
       // code level. Apply LevelDifference to get the correct code context 
level
@@ -4960,16 +5004,33 @@ void UnwrappedLineParser::readToken(int 
LevelDifference) {
                 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
                "LevelDifference makes Line->Level negative");
         Line->Level += LevelDifference;
+        // When this PP directive is being deferred to PreprocessorDirectives
+        // (SwitchToPreprocessorLines=true), it may be encountered at a deeper
+        // C++ brace nesting than the opening PP directive of the same
+        // conditional block. This happens inside child-block contexts (e.g.
+        // lambda bodies): the opening #if is processed by readToken() before
+        // parseChildBlock()'s ScopedLineState adds +1 to Line->Level, while
+        // the closing #endif is processed after, giving it a Level one higher
+        // than the #if. Detect child-block context by checking 
OrigCurrentLines
+        // (saved before ScopedLineState may switch CurrentLines): inside a
+        // child block it points to the parent's token children list rather 
than
+        // the top-level Lines vector. Use the level recorded for the first
+        // deferred directive (the opening #if) so that all directives of the
+        // same conditional block share the same C++ level.
+        if (SwitchToPreprocessorLines && !PreprocessorDirectives.empty() &&
+            OrigCurrentLines != &Lines) {
+          Line->Level = PreprocessorDirectives.front().Level;
+        }
       } else {
         assert((LevelDifference >= 0 ||
                 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
-              "LevelDifference makes Line->Level negative");
+               "LevelDifference makes Line->Level negative");
         Line->Level += LevelDifference;
         // Comments stored before the preprocessor directive need to be output
         // before the preprocessor directive, at the same level as the
         // preprocessor directive, as we consider them to apply to the
         // directive.
-       if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
+        if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
             PPBranchLevel > 0) {
           Line->Level += PPBranchLevel;
         }

>From 637767a97641209727b19cca8d6affc1585e96f5 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 15:38:42 -0400
Subject: [PATCH 03/11] Corrected line formatting.

---
 clang/lib/Format/Format.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 8dedab081a55c..787b469f9ccd5 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -622,7 +622,8 @@ 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, "BeforeHashWithCode", 
FormatStyle::PPDIS_BeforeHashWithCode);
+    IO.enumCase(Value, "BeforeHashWithCode",
+                FormatStyle::PPDIS_BeforeHashWithCode);
     IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);
   }
 };

>From 0615fd3b7e1ab7cf098b411b64618da5698aa05c Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 15:46:10 -0400
Subject: [PATCH 04/11] Update clang/lib/Format/UnwrappedLineFormatter.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Björn Schäpers <[email protected]>
---
 clang/lib/Format/UnwrappedLineFormatter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index e282b0e27da07..15255e0b06d96 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1565,7 +1565,7 @@ unsigned UnwrappedLineFormatter::format(
         bool LastLine = TheLine.First->is(tok::eof);
         formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent,
                          LastLine ? LastStartColumn : NextStartColumn + Indent,
-                         0);
+                         /*PPNestingLevel=*/0);
       }
 
       NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);

>From 9c2e33016a4ac8cef9e6c840dd66294a68eef04a Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 15:46:31 -0400
Subject: [PATCH 05/11] Update clang/lib/Format/UnwrappedLineParser.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Björn Schäpers <[email protected]>
---
 clang/lib/Format/UnwrappedLineParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index d4af259a54832..db886a5cbc8d0 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2543,7 +2543,7 @@ bool UnwrappedLineParser::parseBracedList(bool 
IsAngleBracket, bool IsEnum) {
       }
     }
     // For BeforeHashWithCode enum bodies: whenever readToken just processed a
-    // PP directive and returned the first post-PP token (AtEndOfPPLine=true),
+    // PP directive and returned the first post-PP token (AtEndOfPPLine == 
true),
     // flush the accumulated pre-PP body tokens as their own UnwrappedLine.
     // This gives each PP-separated segment its own line so the BWHCCodeLine
     // level-boost in addUnwrappedLine can apply the correct indentation.

>From 9e1a991c167fbe7b2cf8530b9d1849f2370a3d82 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 16:29:09 -0400
Subject: [PATCH 06/11] Corrective actions as requested

---
 clang/docs/ClangFormatStyleOptions.rst      | 18 +++++++++
 clang/lib/Format/UnwrappedLineFormatter.cpp |  3 +-
 clang/lib/Format/UnwrappedLineParser.cpp    | 44 ++++++++-------------
 3 files changed, 36 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 342eb0bdb1279..59b0105296211 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4810,6 +4810,24 @@ the configuration (without a prefix: ``Auto``).
          #endif
        #endif
 
+  * ``PPDIS_BeforeHashWithCode`` (in configuration: ``BeforeHashWithCode``)
+    Indents directives before the hash and align with the surrounding 
+    C++ indentation level. Code inside a PP conditional block is indented 
+    one further level relative to the directive that guards it.
+
+    .. code-block:: c++
+
+      enum class Feature {
+        none,
+        #if PLATFORM_FULL
+          wifi,
+          #ifdef HAS_BLE
+            ble,
+          #endif
+        #endif
+        basic
+      };
+
   * ``PPDIS_Leave`` (in configuration: ``Leave``)
     Leaves indentation of directives as-is.
 
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 15255e0b06d96..1a6ecdb680674 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1614,7 +1614,8 @@ unsigned UnwrappedLineFormatter::format(
         if (ReformatLeadingWhitespace) {
           formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
                            TheLine.First->OriginalColumn,
-                           TheLine.First->OriginalColumn, 0);
+                           TheLine.First->OriginalColumn, 
+                           /*PPNestingLevel=*/0);
         } else {
           Whitespaces->addUntouchableToken(*TheLine.First,
                                            TheLine.InPPDirective);
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index db886a5cbc8d0..540eac61e035e 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1243,15 +1243,15 @@ void UnwrappedLineParser::parsePPUnknown() {
     nextToken();
   if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
     Line->Level += PPBranchLevel + 1;
-  // For BeforeHashWithCode, PP directives inside unreachable branches must
-  // not be emitted: in multi-pass formatting the surrounding C++ braces may
-  // have been skipped (PP_Unreachable code is not parsed), leaving
-  // Line->Level too low.  The resulting incorrect replacement would conflict
-  // with the correct one produced by the reachable pass, causing an
-  // "overlapping replacement" error and an empty output.  Simply discard the
-  // accumulated tokens so the reachable pass wins.
   if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
       !PPStack.empty() && PPStack.back().Kind == PP_Unreachable) {
+    // PP directives inside unreachable branches must
+    // not be emitted: in multi-pass formatting the surrounding C++ braces may
+    // have been skipped (PP_Unreachable code is not parsed), leaving
+    // Line->Level too low. The resulting incorrect replacement would conflict
+    // with the correct one produced by the reachable pass, causing an
+    // "overlapping replacement" error and an empty output. Simply discard the
+    // accumulated tokens so the reachable pass wins.
     Line->Tokens.clear();
     return;
   }
@@ -3922,23 +3922,15 @@ bool UnwrappedLineParser::parseEnum() {
   }
   // Parse enum body.
   nextToken();
-  if (!Style.AllowShortEnumsOnASingleLine) {
+  bool updateLevel = !Style.AllowShortEnumsOnASingleLine ||
+                     Style.IndentPPDirectives == 
FormatStyle::PPDIS_BeforeHashWithCode;
+  if (updateLevel) {
     addUnwrappedLine();
     Line->Level += 1;
-  } else if (Style.IndentPPDirectives ==
-             FormatStyle::PPDIS_BeforeHashWithCode) {
-    // For BeforeHashWithCode, flush the enum declaration as its own
-    // UnwrappedLine (like AllowShortEnumsOnASingleLine=false does) so that
-    // body tokens start in a fresh line.  Each PP-separated segment of the
-    // body can then be emitted at its correct indentation via BWHCCodeLine.
-    addUnwrappedLine();
-    ++Line->Level;
   }
   bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true);
-  if (!Style.AllowShortEnumsOnASingleLine)
+  if (updateLevel)
     Line->Level -= 1;
-  else if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode)
-    --Line->Level;
   if (HasError) {
     if (FormatTok->is(tok::semi))
       nextToken();
@@ -4887,9 +4879,9 @@ void UnwrappedLineParser::nextToken(int LevelDifference) {
   if (Style.isVerilog()) {
     // Blocks in Verilog can have `begin` and `end` instead of braces.  For
     // keywords like `begin`, we can't treat them the same as left braces
-    // because some contexts require one of them.  For example structs use
+    // because some contexts require one of them. For example structs use
     // braces and if blocks use keywords, and a left brace can occur in an if
-    // statement, but it is not a block.  For keywords like `end`, we simply
+    // statement, but it is not a block. For keywords like `end`, we simply
     // treat them the same as right braces.
     if (Keywords.isVerilogEnd(*FormatTok))
       FormatTok->Tok.setKind(tok::r_brace);
@@ -5011,11 +5003,11 @@ void UnwrappedLineParser::readToken(int 
LevelDifference) {
       // code level. Apply LevelDifference to get the correct code context 
level
       // (e.g. leaving a block), but do NOT apply PPBranchLevel since PP
       // directives should align with the code rather than nesting PP levels.
-      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode) {
-        assert((LevelDifference >= 0 ||
+      assert((LevelDifference >= 0 ||
                 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
                "LevelDifference makes Line->Level negative");
-        Line->Level += LevelDifference;
+      Line->Level += LevelDifference;
+      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode) {
         // When this PP directive is being deferred to PreprocessorDirectives
         // (SwitchToPreprocessorLines=true), it may be encountered at a deeper
         // C++ brace nesting than the opening PP directive of the same
@@ -5034,10 +5026,6 @@ void UnwrappedLineParser::readToken(int LevelDifference) 
{
           Line->Level = PreprocessorDirectives.front().Level;
         }
       } else {
-        assert((LevelDifference >= 0 ||
-                static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
-               "LevelDifference makes Line->Level negative");
-        Line->Level += LevelDifference;
         // Comments stored before the preprocessor directive need to be output
         // before the preprocessor directive, at the same level as the
         // preprocessor directive, as we consider them to apply to the

>From 17b91b627655057c178edfe36d674b78be095d36 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 17:37:46 -0400
Subject: [PATCH 07/11] Code formatting update

---
 clang/lib/Format/UnwrappedLineFormatter.cpp |  2 +-
 clang/lib/Format/UnwrappedLineParser.cpp    | 18 ++++++++++--------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 1a6ecdb680674..df049a525f4d8 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1614,7 +1614,7 @@ unsigned UnwrappedLineFormatter::format(
         if (ReformatLeadingWhitespace) {
           formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
                            TheLine.First->OriginalColumn,
-                           TheLine.First->OriginalColumn, 
+                           TheLine.First->OriginalColumn,
                            /*PPNestingLevel=*/0);
         } else {
           Whitespaces->addUntouchableToken(*TheLine.First,
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 540eac61e035e..b68af35b59c14 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2543,10 +2543,11 @@ bool UnwrappedLineParser::parseBracedList(bool 
IsAngleBracket, bool IsEnum) {
       }
     }
     // For BeforeHashWithCode enum bodies: whenever readToken just processed a
-    // PP directive and returned the first post-PP token (AtEndOfPPLine == 
true),
-    // flush the accumulated pre-PP body tokens as their own UnwrappedLine.
-    // This gives each PP-separated segment its own line so the BWHCCodeLine
-    // level-boost in addUnwrappedLine can apply the correct indentation.
+    // PP directive and returned the first post-PP token (AtEndOfPPLine ==
+    // true), flush the accumulated pre-PP body tokens as their own
+    // UnwrappedLine. This gives each PP-separated segment its own line so the
+    // BWHCCodeLine level-boost in addUnwrappedLine can apply the correct
+    // indentation.
     if (IsEnum && !IsAngleBracket &&
         Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
         Style.AllowShortEnumsOnASingleLine && AtEndOfPPLine &&
@@ -3922,8 +3923,9 @@ bool UnwrappedLineParser::parseEnum() {
   }
   // Parse enum body.
   nextToken();
-  bool updateLevel = !Style.AllowShortEnumsOnASingleLine ||
-                     Style.IndentPPDirectives == 
FormatStyle::PPDIS_BeforeHashWithCode;
+  bool updateLevel =
+      !Style.AllowShortEnumsOnASingleLine ||
+      Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode;
   if (updateLevel) {
     addUnwrappedLine();
     Line->Level += 1;
@@ -5004,8 +5006,8 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
       // (e.g. leaving a block), but do NOT apply PPBranchLevel since PP
       // directives should align with the code rather than nesting PP levels.
       assert((LevelDifference >= 0 ||
-                static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
-               "LevelDifference makes Line->Level negative");
+              static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
+             "LevelDifference makes Line->Level negative");
       Line->Level += LevelDifference;
       if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode) {
         // When this PP directive is being deferred to PreprocessorDirectives

>From 360c304e8e8aba0ec2aef17493318213e3abaeee Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 18:14:20 -0400
Subject: [PATCH 08/11] Update format documentation

---
 clang/include/clang/Format/Format.h | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index b9e432d560bc5..4b453112caa43 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3356,14 +3356,16 @@ struct FormatStyle {
     /// Indents directives before the hash with the current code indentation
     /// level.
     /// \code
-    ///    if (foo)
-    ///    {
-    ///      #if FOO
-    ///        #if BAR
-    ///          #include <foo>
-    ///        #endif
-    ///      #endif
-    ///    }
+    ///   enum class Feature {
+    ///     none,
+    ///     #if PLATFORM_FULL
+    ///       wifi,
+    ///       #ifdef HAS_BLE
+    ///         ble,
+    ///       #endif
+    ///     #endif
+    ///     basic
+    ///   };
     /// \endcode
     PPDIS_BeforeHashWithCode,
     /// Leaves indentation of directives as-is.

>From 4e37dd08020641be9a20bb7ba9ca22a5d1e68ff7 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 19:48:22 -0400
Subject: [PATCH 09/11] Documentation adjustment

---
 clang/include/clang/Format/Format.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 4b453112caa43..cd3798eea7596 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3353,8 +3353,9 @@ struct FormatStyle {
     ///    #endif
     /// \endcode
     PPDIS_BeforeHash,
-    /// Indents directives before the hash with the current code indentation
-    /// level.
+    /// Indents directives before the hash and align with the surrounding 
+    /// C++ indentation level. Code inside a PP conditional block is indented 
+    /// one further level relative to the directive that guards it.
     /// \code
     ///   enum class Feature {
     ///     none,

>From 81111d6107bf840816799fecc759a5151b286015 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 19:56:02 -0400
Subject: [PATCH 10/11] Renamed BWHCCodeLine to IsACodeLineInsidePPBlock

---
 clang/lib/Format/UnwrappedLineParser.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index b68af35b59c14..3f9fe40b2e56c 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2546,8 +2546,8 @@ bool UnwrappedLineParser::parseBracedList(bool 
IsAngleBracket, bool IsEnum) {
     // PP directive and returned the first post-PP token (AtEndOfPPLine ==
     // true), flush the accumulated pre-PP body tokens as their own
     // UnwrappedLine. This gives each PP-separated segment its own line so the
-    // BWHCCodeLine level-boost in addUnwrappedLine can apply the correct
-    // indentation.
+    // IsACodeLineInsidePPBlock level-boost in addUnwrappedLine can apply the 
+    // correct indentation.
     if (IsEnum && !IsAngleBracket &&
         Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
         Style.AllowShortEnumsOnASingleLine && AtEndOfPPLine &&
@@ -4703,14 +4703,14 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel 
AdjustLevel) {
     // Line->PPLevel (set at first-token push time) instead of the current
     // PPBranchLevel, which may have been altered by later PP directives that
     // readToken processed after the code tokens but before addUnwrappedLine.
-    const bool BWHCCodeLine =
+    const bool IsACodeLineInsidePPBlock =
         Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&
         !Line->InPPDirective && Line->PPLevel > 0;
-    const unsigned PPAdj = BWHCCodeLine ? Line->PPLevel : 0;
-    if (BWHCCodeLine)
+    const unsigned PPAdj = IsACodeLineInsidePPBlock ? Line->PPLevel : 0;
+    if (IsACodeLineInsidePPBlock)
       Line->Level += PPAdj;
     CurrentLines->push_back(std::move(*Line));
-    if (BWHCCodeLine)
+    if (IsACodeLineInsidePPBlock)
       Line->Level -= PPAdj;
   }
   Line->Tokens.clear();

>From a41919e570751a1da343b226f63a2a9614a00b23 Mon Sep 17 00:00:00 2001
From: Guy Turcotte <[email protected]>
Date: Sun, 15 Mar 2026 20:41:57 -0400
Subject: [PATCH 11/11] Blank spaces removal

---
 clang/include/clang/Format/Format.h      | 4 ++--
 clang/lib/Format/UnwrappedLineParser.cpp | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index cd3798eea7596..e6c8e2170cc74 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3353,8 +3353,8 @@ struct FormatStyle {
     ///    #endif
     /// \endcode
     PPDIS_BeforeHash,
-    /// Indents directives before the hash and align with the surrounding 
-    /// C++ indentation level. Code inside a PP conditional block is indented 
+    /// Indents directives before the hash and align with the surrounding
+    /// C++ indentation level. Code inside a PP conditional block is indented
     /// one further level relative to the directive that guards it.
     /// \code
     ///   enum class Feature {
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 3f9fe40b2e56c..d69747a09c542 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2546,7 +2546,7 @@ bool UnwrappedLineParser::parseBracedList(bool 
IsAngleBracket, bool IsEnum) {
     // PP directive and returned the first post-PP token (AtEndOfPPLine ==
     // true), flush the accumulated pre-PP body tokens as their own
     // UnwrappedLine. This gives each PP-separated segment its own line so the
-    // IsACodeLineInsidePPBlock level-boost in addUnwrappedLine can apply the 
+    // IsACodeLineInsidePPBlock level-boost in addUnwrappedLine can apply the
     // correct indentation.
     if (IsEnum && !IsAngleBracket &&
         Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHashWithCode &&

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to