llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: Matthias Görgens (matthiasgoergens)

<details>
<summary>Changes</summary>

`26ffc71afa7c` disallowed breaking on either side of `##` to keep pasted 
identifiers together, but the blanket rule also caught the GNU comma-swallowing 
idiom `call(arg, ##__VA_ARGS__)`, so a macro line containing it could never be 
wrapped and stayed over the column limit.

Keep forbidding breaks after `##`, and before `##` except when the previous 
token is a comma: the comma-`##` sequence swallows the comma rather than 
pasting tokens, and a backslash-newline between them leaves the token stream 
unchanged. The two tests cover final and non-final `##__VA_ARGS__` and 
re-format their own output, pinning idempotence.

Fixes #<!-- -->212835.

## Tool use

Per the [LLVM AI Tool Use Policy](https://llvm.org/docs/AIToolPolicy.html): AI
tools were involved throughout the preparation of this change. I am the author
and accountable for the contribution.

Assisted-by: OpenAI Codex
Assisted-by: Claude Code
Assisted-by: Kimi
Assisted-by: DeepSeek


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


2 Files Affected:

- (modified) clang/lib/Format/TokenAnnotator.cpp (+5-1) 
- (modified) clang/unittests/Format/FormatTest.cpp (+24) 


``````````diff
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index b6c33279b0aca..06b28b37582d1 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6511,8 +6511,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine 
&Line,
             !(Right.Next &&
               Right.Next->isOneOf(TT_FunctionDeclarationName, tok::kw_const)));
   }
-  if (Left.is(tok::hashhash) || Right.is(tok::hashhash))
+  if (Left.is(tok::hashhash))
     return false;
+  // Keep pasted identifiers together, but allow a break before the GNU
+  // variadic-macro comma-swallowing extension: , ##__VA_ARGS__.
+  if (Right.is(tok::hashhash))
+    return Left.is(tok::comma);
   if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
                     TT_ClassHeadName, TT_QtProperty, tok::kw_operator)) {
     return true;
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index b72a683ac1fff..bce808a0857c9 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -5985,6 +5985,30 @@ TEST_F(FormatTest, HashInMacroDefinition) {
                Style);
   verifyFormat("#define A void # ## #", Style);
 
+  auto CommaPasteStyle = getLLVMStyleWithColumns(80);
+  CommaPasteStyle.IndentWidth = 4;
+  CommaPasteStyle.ContinuationIndentWidth = 8;
+  CommaPasteStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
+  verifyFormat(
+      "#define M(f, ...)                                                      "
+      "        \\\n"
+      "    auto f = call("
+      "firstArgumentThatIsQuiteLongEnoughToForceAWrapHere11111111,  \\\n"
+      "                  ##__VA_ARGS__);",
+      "#define M(f, ...) \\\n"
+      "    auto f = call("
+      "firstArgumentThatIsQuiteLongEnoughToForceAWrapHere11111111, "
+      "##__VA_ARGS__);",
+      CommaPasteStyle);
+  CommaPasteStyle.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign;
+  verifyFormat(
+      "#define M(...) \\\n"
+      "    call(firstArgumentThatIsQuiteLongEnoughToForceAWrapHere11111111, 
\\\n"
+      "         ##__VA_ARGS__, extra)",
+      "#define M(...) \\\n"
+      "    call(firstArgumentThatIsQuiteLongEnoughToForceAWrapHere11111111, "
+      "##__VA_ARGS__, extra)",
+      CommaPasteStyle);
   Style.ColumnLimit = 60;
   Style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign;
   verifyFormat(

``````````

</details>


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

Reply via email to