From 1f0a479997daccf6c2d42d81533e2c935d7ad841 Mon Sep 17 00:00:00 2001 From: Alexandre Ganea Date: Wed, 28 Aug 2019 00:04:06 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370129 91177308-0d34-0410-b5e6-96231b3b80d8 --- .gitattributes | 4 ++ .../DependencyDirectivesSourceMinimizer.cpp | 49 +++++++++++++------ ...e_to_dependency_directives_invalid_error.c | 16 ++++++ 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 .gitattributes create mode 100644 test/Lexer/minimize_source_to_dependency_directives_invalid_error.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..1f6a5a1132 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/lib/Lex/DependencyDirectivesSourceMinimizer.cpp index 11dca07361..a350481df9 100644 --- a/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ b/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -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; } diff --git a/test/Lexer/minimize_source_to_dependency_directives_invalid_error.c b/test/Lexer/minimize_source_to_dependency_directives_invalid_error.c new file mode 100644 index 0000000000..c4a4cf3d97 --- /dev/null +++ b/test/Lexer/minimize_source_to_dependency_directives_invalid_error.c @@ -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 +#endif + +// CHECK: #ifdef OTHER +// CHECK-NEXT: #include +// CHECK-NEXT: #endif -- 2.40.0