diff options
author | Daniel Jasper <djasper@google.com> | 2015-05-06 11:16:43 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2015-05-06 11:16:43 +0000 |
commit | e2408e37db7e40aa6d79a741a51373f283706c40 (patch) | |
tree | 9e2eed594a78818b193c52582ff30ebcbf5bf857 /clang/lib/Format/Format.cpp | |
parent | 8389e235e9e00d3dbcb663816f2b6ba7e768c1e5 (diff) | |
download | llvm-e2408e37db7e40aa6d79a741a51373f283706c40.zip llvm-e2408e37db7e40aa6d79a741a51373f283706c40.tar.gz llvm-e2408e37db7e40aa6d79a741a51373f283706c40.tar.bz2 |
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.
llvm-svn: 236589
Diffstat (limited to 'clang/lib/Format/Format.cpp')
-rw-r--r-- | clang/lib/Format/Format.cpp | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9aad4f7..8348a535 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/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); } |