https://github.com/mygitljf updated 
https://github.com/llvm/llvm-project/pull/199103

>From 70d1648e9d5a973acd5e710f485764be63d80038 Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Thu, 21 May 2026 19:53:27 +0000
Subject: [PATCH 1/3] [clang-format] Fix a crash on triple-bracket input like
 `[[[a]]`

`isCppAttribute` only checks the tokens following `[[`, so for malformed
input `[[[a]]` it returns true on the *middle* `[`: that token's
`Next`/`Next->Next` look like a valid `[[ident...]]` sequence. The middle
`[` is then annotated as `TT_AttributeLSquare` while the outer `[` stays
as a raw `tok::l_square`, which violates the invariant guarded by
`assert(Left.isNot(tok::l_square))` in `canBreakBefore` and aborts the
process.

Reject the C++ attribute classification when the candidate `[[` is
itself preceded by another `[`. Legal C++ never has `[[[` in any
context, so this is a strict refinement that mirrors the existing
defensive check that excludes ObjC `@[...]` array literals.

Fixes #199010
---
 clang/lib/Format/TokenAnnotator.cpp   | 6 ++++++
 clang/unittests/Format/FormatTest.cpp | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 43e4f6796b6dd..63b4f65418a93 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -90,6 +90,12 @@ static bool isCppAttribute(bool IsCpp, const FormatToken 
&Tok) {
   // The first square bracket is part of an ObjC array literal
   if (Tok.Previous && Tok.Previous->is(tok::at))
     return false;
+  // A C++ attribute specifier '[[...]]' never appears directly inside another
+  // '['. Treating malformed input like '[[[a]]' as one would mis-annotate the
+  // inner '[' as TT_AttributeLSquare while leaving the outer '[' as a raw
+  // tok::l_square, tripping an assertion in canBreakBefore.
+  if (Tok.Previous && Tok.Previous->is(tok::l_square))
+    return false;
   const FormatToken *AttrTok = Tok.Next->Next;
   if (!AttrTok)
     return false;
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 83e2c5b38ceaf..6f01492ddce82 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -22508,6 +22508,9 @@ TEST_F(FormatTest, DoNotCrashOnInvalidInput) {
   verifyNoCrash("        tst     %o5     ! are we doing the gray case?\n"
                 "LY52:                   ! [internal]");
   verifyNoCrash("operator foo *;");
+  verifyNoCrash("[[[a]]");
+  verifyNoCrash("[[[a]]]");
+  verifyNoCrash("[[ [a] ]]");
 }
 
 TEST_F(FormatTest, FormatsTableGenCode) {

>From 56ccc88183af0f3dfac5dc1ed92df5ea9022d7da Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Sat, 23 May 2026 10:05:12 +0000
Subject: [PATCH 2/3] [clang-format] simplify annotations

---
 clang/lib/Format/TokenAnnotator.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 63b4f65418a93..b628c309028ab 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -90,10 +90,7 @@ static bool isCppAttribute(bool IsCpp, const FormatToken 
&Tok) {
   // The first square bracket is part of an ObjC array literal
   if (Tok.Previous && Tok.Previous->is(tok::at))
     return false;
-  // A C++ attribute specifier '[[...]]' never appears directly inside another
-  // '['. Treating malformed input like '[[[a]]' as one would mis-annotate the
-  // inner '[' as TT_AttributeLSquare while leaving the outer '[' as a raw
-  // tok::l_square, tripping an assertion in canBreakBefore.
+  // Avoid mis-annotating the inner '[[' of malformed input.
   if (Tok.Previous && Tok.Previous->is(tok::l_square))
     return false;
   const FormatToken *AttrTok = Tok.Next->Next;

>From 60f2a5506c3253e7423240214343d1aff5d88a60 Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Fri, 5 Jun 2026 20:37:52 +0800
Subject: [PATCH 3/3] Apply suggestion from @HazardyKnusperkeks
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/TokenAnnotator.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index b628c309028ab..6f1ef8e03c480 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -88,10 +88,8 @@ static bool isCppAttribute(bool IsCpp, const FormatToken 
&Tok) {
   if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square))
     return false;
   // The first square bracket is part of an ObjC array literal
-  if (Tok.Previous && Tok.Previous->is(tok::at))
-    return false;
-  // Avoid mis-annotating the inner '[[' of malformed input.
-  if (Tok.Previous && Tok.Previous->is(tok::l_square))
+if (Tok.Previous && Tok.Previous->isOneOf(tok::at, tok::l_square))
+return false;
     return false;
   const FormatToken *AttrTok = Tok.Next->Next;
   if (!AttrTok)

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

Reply via email to