aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format/Format.cpp
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2015-05-06 11:16:43 +0000
committerDaniel Jasper <djasper@google.com>2015-05-06 11:16:43 +0000
commite2408e37db7e40aa6d79a741a51373f283706c40 (patch)
tree9e2eed594a78818b193c52582ff30ebcbf5bf857 /clang/lib/Format/Format.cpp
parent8389e235e9e00d3dbcb663816f2b6ba7e768c1e5 (diff)
downloadllvm-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.cpp27
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);
}