llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: Aditya Goyal (goyaladitya05)

<details>
<summary>Changes</summary>

### Cause
When a macro configured as object-like (e.g. `Macros: [CASE=case]`) is called 
with arguments (`CASE(1, "1")`), the parser rewinds the token stream to reparse 
the arguments as regular tokens. It then called `nextToken()`, which first 
pushes the current `FormatTok` onto the line being built, but at that point 
`FormatTok` is the token *past* the macro call's closing paren, left over from 
`parseMacroCall()`. The rewound stream serves that token again later, so it 
ends up in the unwrapped lines twice.

A duplicated token makes `AnnotatedLine`'s Next/Previous re-linking cyclic, and 
the first backward walk over the line 
(`TokenAnnotator::calculateUnbreakableTailLengths`) loops forever. With a 
single macro call the two copies land in different lines, which terminates but 
silently corrupts the layout; with two calls (or one top-level call) they land 
in the same line and clang-format hangs.

### Changes
This PR restores `FormatTok` with `Tokens-&gt;getNextToken()` instead, which 
yields the identical stream state without the bogus push, matching the direct 
restores in the neighboring fallback paths.

The expected output of `KeepParensWhenExpandingObjectLikeMacros` changed 
because it exercised the silent variant of the bug: the phantom `;` pushed onto 
the `void f() {` line is what kept the macro call from being merged with the 
function header.

Fixes #<!-- -->163338.


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


2 Files Affected:

- (modified) clang/lib/Format/UnwrappedLineParser.cpp (+2-1) 
- (modified) clang/unittests/Format/FormatTestMacroExpansion.cpp (+16-2) 


``````````diff
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 8e6f7e2f2ce07..4520e4cb52407 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -5110,7 +5110,8 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
         Args.reset();
         UnexpandedLine->Tokens.resize(1);
         Tokens->setPosition(Position);
-        nextToken();
+        // Not nextToken(), which would push the stale FormatTok onto the line.
+        FormatTok = Tokens->getNextToken();
         assert(!Args && Macros.objectLike(ID->TokenText));
       }
       if ((!Args && Macros.objectLike(ID->TokenText)) ||
diff --git a/clang/unittests/Format/FormatTestMacroExpansion.cpp 
b/clang/unittests/Format/FormatTestMacroExpansion.cpp
index d391fe3d715c3..8ff3282d31aee 100644
--- a/clang/unittests/Format/FormatTestMacroExpansion.cpp
+++ b/clang/unittests/Format/FormatTestMacroExpansion.cpp
@@ -231,8 +231,7 @@ a))",
 TEST_F(FormatTestMacroExpansion, KeepParensWhenExpandingObjectLikeMacros) {
   FormatStyle Style = getLLVMStyle();
   Style.Macros.push_back("FN=class C { int f");
-  verifyFormat("void f() {\n"
-               "  FN(a *b);\n"
+  verifyFormat("void f() { FN(a *b);\n"
                "  };\n"
                "}",
                Style);
@@ -301,6 +300,21 @@ TEST_F(FormatTestMacroExpansion, 
IndentChildrenWithinMacroCall) {
                Style);
 }
 
+TEST_F(FormatTestMacroExpansion, ObjectLikeMacroCalledWithArgsDoesNotHang) {
+  FormatStyle Style = getLLVMStyle();
+  Style.Macros.push_back("CASE=case");
+  verifyNoCrash("const char *fct(int wki) {\n"
+                "  switch (wki) {\n"
+                "    CASE(1, \"1\");\n"
+                "    CASE(2, \"2\");\n"
+                "    default:\n"
+                "      return \"123\";\n"
+                "  }\n"
+                "}",
+                Style);
+  verifyNoCrash("CASE(1, \"1\");", Style);
+}
+
 } // namespace
 } // namespace test
 } // namespace format

``````````

</details>


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

Reply via email to