Re-land [clang-scan-deps] Minimizer: Correctly handle multi-line content with CR+LF line endings

Previously, an #error directive with quoted, multi-line content, along with CR+LF line endings wasn't handled correctly.

Differential Revision: https://reviews.llvm.org/D66556

llvm-svn: 370129
This commit is contained in:
Alexandre Ganea 2019-08-28 00:04:06 +00:00
parent 93a26ec98d
commit 57b4e107e4
3 changed files with 55 additions and 14 deletions

4
clang/.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
# Windows line ending tests
test/Lexer/minimize_source_to_dependency_directives_invalid_error.c text eol=crlf
test/FixIt/fixit-newline-style.c text eol=crlf
test/Frontend/system-header-line-directive-ms-lineendings.c text eol=crlf

View File

@ -196,15 +196,29 @@ static void skipString(const char *&First, const char *const End) {
++First; // Finish off the string.
}
static void skipNewline(const char *&First, const char *End) {
assert(isVerticalWhitespace(*First));
++First;
// Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n)
static unsigned isEOL(const char *First, const char *const End) {
if (First == End)
return;
return 0;
if (End - First > 1 && isVerticalWhitespace(First[0]) &&
isVerticalWhitespace(First[1]) && First[0] != First[1])
return 2;
return !!isVerticalWhitespace(First[0]);
}
// Check for "\n\r" and "\r\n".
if (LLVM_UNLIKELY(isVerticalWhitespace(*First) && First[-1] != First[0]))
++First;
// Returns the length of the skipped newline
static unsigned skipNewline(const char *&First, const char *End) {
if (First == End)
return 0;
assert(isVerticalWhitespace(*First));
unsigned Len = isEOL(First, End);
assert(Len && "expected newline");
First += Len;
return Len;
}
static bool wasLineContinuation(const char *First, unsigned EOLLen) {
return *(First - (int)EOLLen - 1) == '\\';
}
static void skipToNewlineRaw(const char *&First, const char *const End) {
@ -212,17 +226,21 @@ static void skipToNewlineRaw(const char *&First, const char *const End) {
if (First == End)
return;
if (isVerticalWhitespace(*First))
unsigned Len = isEOL(First, End);
if (Len)
return;
while (!isVerticalWhitespace(*First))
do {
if (++First == End)
return;
Len = isEOL(First, End);
} while (!Len);
if (First[-1] != '\\')
return;
++First; // Keep going...
First += Len;
// Keep skipping lines...
}
}
@ -277,7 +295,7 @@ static bool isQuoteCppDigitSeparator(const char *const Start,
}
static void skipLine(const char *&First, const char *const End) {
do {
for (;;) {
assert(First <= End);
if (First == End)
return;
@ -322,9 +340,10 @@ static void skipLine(const char *&First, const char *const End) {
return;
// Skip over the newline.
assert(isVerticalWhitespace(*First));
skipNewline(First, End);
} while (First[-2] == '\\'); // Continue past line-continuations.
unsigned Len = skipNewline(First, End);
if (!wasLineContinuation(First, Len)) // Continue past line-continuations.
break;
}
}
static void skipDirective(StringRef Name, const char *&First,
@ -380,6 +399,8 @@ void Minimizer::printToNewline(const char *&First, const char *const End) {
// Print out the string.
if (Last == End || Last == First || Last[-1] != '\\') {
append(First, reverseOverSpaces(First, Last));
First = Last;
skipNewline(First, End);
return;
}

View File

@ -0,0 +1,16 @@
// Test CF+LF are properly handled along with quoted, multi-line #error
// RUN: %clang_cc1 -DOTHER -print-dependency-directives-minimized-source %s 2>&1 | FileCheck %s
#ifndef TEST
#error "message \
more message \
even more"
#endif
#ifdef OTHER
#include <string>
#endif
// CHECK: #ifdef OTHER
// CHECK-NEXT: #include <string>
// CHECK-NEXT: #endif