[clang] Fix preprocessed block comment newline on windows containing extra carriage return (PR #205084)

Joe Kirchoff via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 22 04:48:48 PDT 2026


https://github.com/Rinn updated https://github.com/llvm/llvm-project/pull/205084

>From 25db0f0051754ebc88a1b42438d4d593b486f934 Mon Sep 17 00:00:00 2001
From: Joe Kirchoff <joe.kirchoff at epicgames.com>
Date: Mon, 22 Jun 2026 12:29:50 +0100
Subject: [PATCH 1/2] Fix preprocessed block comment newline on windows

When preprocessing a source file on windows with \r\n newlines while preserving comments, any newlines in a block comment are written directly which is then later normalized to \r\r\n. Fix this by only writing out \n in PrintPreprocessedTokens for those comments by copying the logic from PrintPPOutputPPCallbacks::HandleNewlinesInToken
---
 .../lib/Frontend/PrintPreprocessedOutput.cpp  | 30 +++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 02266882c4c4a..16c09d1263e30 100644
--- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -889,6 +889,26 @@ struct UnknownPragmaHandler : public PragmaHandler {
 };
 } // end anonymous namespace
 
+static void PrintPreprocessedComment(raw_ostream *OS, const char *TokStr,
+                                     unsigned Len) {
+  for (; Len; --Len, ++TokStr) {
+    if (*TokStr != '\n' &&
+        *TokStr != '\r') {
+      *OS << *TokStr;
+      continue;
+    }
+
+    *OS << '\n';
+
+    // If we have \n\r or \r\n, skip both and emit one newline.
+    if (Len != 1 &&
+        (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+        TokStr[0] != TokStr[1]) {
+      ++TokStr;
+      --Len;
+    }
+  }
+}
 
 static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
                                     PrintPPOutputPPCallbacks *Callbacks) {
@@ -1022,7 +1042,10 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
     } else if (Tok.getLength() < std::size(Buffer)) {
       const char *TokPtr = Buffer;
       unsigned Len = PP.getSpelling(Tok, TokPtr);
-      Callbacks->OS->write(TokPtr, Len);
+      if (Tok.is(tok::comment))
+        PrintPreprocessedComment(Callbacks->OS, TokPtr, Len);
+      else
+        Callbacks->OS->write(TokPtr, Len);
 
       // Tokens that can contain embedded newlines need to adjust our current
       // line number.
@@ -1039,7 +1062,10 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
       }
     } else {
       std::string S = PP.getSpelling(Tok);
-      Callbacks->OS->write(S.data(), S.size());
+      if (Tok.is(tok::comment))
+        PrintPreprocessedComment(Callbacks->OS, S.data(), S.size());
+      else
+        Callbacks->OS->write(S.data(), S.size());
 
       // Tokens that can contain embedded newlines need to adjust our current
       // line number.

>From 515cd83647efe645fe4ece3c3e2e306cd57c09ec Mon Sep 17 00:00:00 2001
From: Joe Kirchoff <joe.kirchoff at epicgames.com>
Date: Mon, 22 Jun 2026 12:48:29 +0100
Subject: [PATCH 2/2] clang-format

---
 clang/lib/Frontend/PrintPreprocessedOutput.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 16c09d1263e30..40c1b89366a7c 100644
--- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -892,8 +892,7 @@ struct UnknownPragmaHandler : public PragmaHandler {
 static void PrintPreprocessedComment(raw_ostream *OS, const char *TokStr,
                                      unsigned Len) {
   for (; Len; --Len, ++TokStr) {
-    if (*TokStr != '\n' &&
-        *TokStr != '\r') {
+    if (*TokStr != '\n' && *TokStr != '\r') {
       *OS << *TokStr;
       continue;
     }
@@ -901,8 +900,7 @@ static void PrintPreprocessedComment(raw_ostream *OS, const char *TokStr,
     *OS << '\n';
 
     // If we have \n\r or \r\n, skip both and emit one newline.
-    if (Len != 1 &&
-        (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+    if (Len != 1 && (TokStr[1] == '\n' || TokStr[1] == '\r') &&
         TokStr[0] != TokStr[1]) {
       ++TokStr;
       --Len;



More information about the cfe-commits mailing list