From 093e6bdd4bec8ce9b3baf1e8e0a07aa6549dd5d4 Mon Sep 17 00:00:00 2001 From: XDeme <66138117+XDeme@users.noreply.github.com> Date: Thu, 11 Jan 2024 00:46:11 -0300 Subject: [PATCH] [clang-format] Fix crash involving array designators (#77045) Fixes llvm/llvm-project#76716 Fixes parsing of `[0]{}`. Before this patch it was begin parsed as a lambda, now it is correctly parsed as a designator initializer. --- clang/lib/Format/UnwrappedLineParser.cpp | 2 +- clang/lib/Format/WhitespaceManager.h | 1 + clang/unittests/Format/FormatTest.cpp | 12 ++++++++++++ clang/unittests/Format/TokenAnnotatorTest.cpp | 5 +++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 684609747a5513..d4aa3735c2a546 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2308,7 +2308,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { LeftSquare->isCppStructuredBinding(Style)) { return false; } - if (FormatTok->is(tok::l_square)) + if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind())) return false; if (FormatTok->is(tok::r_square)) { const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true); diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index 24fe492dcb0269..dc6f60e5deeedf 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -282,6 +282,7 @@ class WhitespaceManager { for (auto PrevIter = Start; PrevIter != End; ++PrevIter) { // If we broke the line the initial spaces are already // accounted for. + assert(PrevIter->Index < Changes.size()); if (Changes[PrevIter->Index].NewlinesBefore > 0) NetWidth = 0; NetWidth += diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 9fd55db44df685..8f115fb8cbf0fb 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -20931,6 +20931,12 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) { "};", Style); + verifyNoCrash("Foo foo[] = {\n" + " [0] = {1, 1},\n" + " [1] { 1, 1, },\n" + " [2] { 1, 1, },\n" + "};"); + verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", " " {\"x\", \"dy\"}},\n" @@ -21173,6 +21179,12 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) { "};", Style); + verifyNoCrash("Foo foo[] = {\n" + " [0] = {1, 1},\n" + " [1] { 1, 1, },\n" + " [2] { 1, 1, },\n" + "};"); + verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", {\"x\", " "\"dy\"} },\n" diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index decc0785c5cde7..494205a1f2d8ed 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2324,6 +2324,11 @@ TEST_F(TokenAnnotatorTest, UnderstandDesignatedInitializers) { EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit); EXPECT_TOKEN(Tokens[6], tok::period, TT_DesignatedInitializerPeriod); EXPECT_TOKEN(Tokens[13], tok::period, TT_DesignatedInitializerPeriod); + + Tokens = annotate("Foo foo[] = {[0]{}};"); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::l_square, TT_DesignatedInitializerLSquare); + EXPECT_BRACE_KIND(Tokens[9], BK_BracedInit); } TEST_F(TokenAnnotatorTest, UnderstandsJavaScript) {