[clang] [clang-format] Fix first-line width calculation for CRLF multiline tokens (PR #228752)

via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 3 11:00:20 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: w1m (w1m024)

<details>
<summary>Changes</summary>

The first-line width of a multiline token is calculated from the text before the first `LF`. For `CRLF` input, this includes the preceding `CR`, which is counted as an extra column and can change wrapping at the column limit.

Exclude the trailing `CR` when measuring the first-line width while preserving the token text. Add a regression test covering `LF` and `CRLF` multiline raw strings whose first line, including the preceding code, exactly fits the column limit.

Fixes #<!-- -->224571
Assisted-by: Codex

---
Full diff: https://github.com/llvm/llvm-project/pull/228752.diff


2 Files Affected:

- (modified) clang/lib/Format/FormatTokenLexer.cpp (+5-1) 
- (modified) clang/unittests/Format/FormatTest.cpp (+17) 


``````````diff
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 2a8bef21ad4143..12a6fb8ea90540 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -1473,10 +1473,14 @@ FormatToken *FormatTokenLexer::getNextToken() {
     Column += FormatTok->ColumnWidth;
   } else {
     FormatTok->IsMultiline = true;
+    // Exclude the '\r' of a CRLF line ending from the first line's width.
+    StringRef FirstLine = Text.substr(0, FirstNewlinePos);
+    if (FirstLine.ends_with("\r"))
+      FirstLine = FirstLine.drop_back();
     // FIXME: ColumnWidth actually depends on the start column, we need to
     // take this into account when the token is moved.
     FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
-        Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding);
+        FirstLine, Column, Style.TabWidth, Encoding);
 
     // The last line of the token always starts in column 0.
     // Thus, the length can be precomputed even in the presence of tabs.
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 0a5950c25c60ef..19e9f9695812e2 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -16681,6 +16681,23 @@ TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) {
                " R\"(single line raw string)\" + bbbbbb);");
 }
 
+TEST_F(FormatTest, MultilineRawStringWidthWithCRLF) {
+  auto Style = getWebKitStyle();
+  Style.ColumnLimit = 23;
+  Style.AllowAllArgumentsOnNextLine = false;
+  Style.PackArguments.BinPack = FormatStyle::BPAS_OnePerLine;
+
+  // The raw string's first line reaches ColumnLimit; CR must not add a column.
+  verifyFormat("x = a ? f(R\"(aaaaaaaaaa\n)\",\n"
+               "            b)\n"
+               "      : g();",
+               "x = a ? f(R\"(aaaaaaaaaa\n)\", b) : g();", Style);
+  verifyFormat("x = a ? f(R\"(aaaaaaaaaa\r\n)\",\r\n"
+               "            b)\r\n"
+               "      : g();",
+               "x = a ? f(R\"(aaaaaaaaaa\r\n)\", b) : g();", Style);
+}
+
 TEST_F(FormatTest, SkipsUnknownStringLiterals) {
   verifyFormat("string a = \"unterminated;");
   verifyFormat("function(\"unterminated,\n"

``````````

</details>


https://github.com/llvm/llvm-project/pull/228752


More information about the cfe-commits mailing list