From: Daniel Jasper Date: Wed, 6 May 2015 11:16:43 +0000 (+0000) Subject: clang-format: Fix another assertion discovered by the fuzzer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f57cfa4de26e5e64cdf27cb375b12895fd17a698;p=clang clang-format: Fix another assertion discovered by the fuzzer. In the process, fix an old todo that I don't really know how to write tests for. The problem is that Clang's lexer creates very strange token sequences for these. However, the new approach seems generally better and easier to read so I am submitting it nonetheless. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236589 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 9aad4f7d0e..8348a535a4 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -1000,18 +1000,25 @@ private: // Consume and record whitespace until we find a significant token. unsigned WhitespaceLength = TrailingWhitespace; while (FormatTok->Tok.is(tok::unknown)) { + StringRef Text = FormatTok->TokenText; + auto EscapesNewline = [&](int pos) { + // A '\r' here is just part of '\r\n'. Skip it. + if (pos >= 0 && Text[pos] == '\r') + --pos; + // See whether there is an odd number of '\' before this. + unsigned count = 0; + for (; pos >= 0; --pos, ++count) + if (Text[count] != '\\') + break; + return count & 1; + }; // FIXME: This miscounts tok:unknown tokens that are not just // whitespace, e.g. a '`' character. - for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) { - switch (FormatTok->TokenText[i]) { + for (int i = 0, e = Text.size(); i != e; ++i) { + switch (Text[i]) { case '\n': ++FormatTok->NewlinesBefore; - // FIXME: This is technically incorrect, as it could also - // be a literal backslash at the end of the line. - if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' && - (FormatTok->TokenText[i - 1] != '\r' || i == 1 || - FormatTok->TokenText[i - 2] != '\\'))) - FormatTok->HasUnescapedNewline = true; + FormatTok->HasUnescapedNewline = !EscapesNewline(i - 1); FormatTok->LastNewlineOffset = WhitespaceLength + i + 1; Column = 0; break; @@ -1030,8 +1037,7 @@ private: Column += Style.TabWidth - Column % Style.TabWidth; break; case '\\': - if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' && - FormatTok->TokenText[i + 1] != '\n')) + if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n')) FormatTok->Type = TT_ImplicitStringLiteral; break; default: @@ -1056,6 +1062,7 @@ private: FormatTok->TokenText[1] == '\n') { ++FormatTok->NewlinesBefore; WhitespaceLength += 2; + FormatTok->LastNewlineOffset = 2; Column = 0; FormatTok->TokenText = FormatTok->TokenText.substr(2); } diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 31befad678..ea15312eb5 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -2951,15 +2951,13 @@ TEST_F(FormatTest, FormatUnbalancedStructuralElements) { format("#define A } }\nint i;", getLLVMStyleWithColumns(11))); } -TEST_F(FormatTest, EscapedNewlineAtStartOfToken) { +TEST_F(FormatTest, EscapedNewlines) { EXPECT_EQ( "#define A \\\n int i; \\\n int j;", format("#define A \\\nint i;\\\n int j;", getLLVMStyleWithColumns(11))); EXPECT_EQ("template f();", format("\\\ntemplate f();")); -} - -TEST_F(FormatTest, NoEscapedNewlineHandlingInBlockComments) { EXPECT_EQ("/* \\ \\ \\\n*/", format("\\\n/* \\ \\ \\\n*/")); + EXPECT_EQ("", format("")); } TEST_F(FormatTest, DontCrashOnBlockComments) {