Skip to content

Commit 2abca4f

Browse files
committed
[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: 369986
1 parent b26bc34 commit 2abca4f

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp

+35-14
Original file line numberDiff line numberDiff line change
@@ -196,33 +196,51 @@ static void skipString(const char *&First, const char *const End) {
196196
++First; // Finish off the string.
197197
}
198198

199-
static void skipNewline(const char *&First, const char *End) {
200-
assert(isVerticalWhitespace(*First));
201-
++First;
199+
// Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n)
200+
static unsigned isEOL(const char *First, const char *const End) {
202201
if (First == End)
203-
return;
202+
return 0;
203+
if (End - First > 1 && isVerticalWhitespace(First[0]) &&
204+
isVerticalWhitespace(First[1]) && First[0] != First[1])
205+
return 2;
206+
return !!isVerticalWhitespace(First[0]);
207+
}
204208

205-
// Check for "\n\r" and "\r\n".
206-
if (LLVM_UNLIKELY(isVerticalWhitespace(*First) && First[-1] != First[0]))
207-
++First;
209+
// Returns the length of the skipped newline
210+
static unsigned skipNewline(const char *&First, const char *End) {
211+
if (First == End)
212+
return 0;
213+
assert(isVerticalWhitespace(*First));
214+
unsigned Len = isEOL(First, End);
215+
assert(Len && "expected newline");
216+
First += Len;
217+
return Len;
218+
}
219+
220+
static bool wasLineContinuation(const char *First, unsigned EOLLen) {
221+
return *(First - (int)EOLLen - 1) == '\\';
208222
}
209223

210224
static void skipToNewlineRaw(const char *&First, const char *const End) {
211225
for (;;) {
212226
if (First == End)
213227
return;
214228

215-
if (isVerticalWhitespace(*First))
229+
unsigned Len = isEOL(First, End);
230+
if (Len)
216231
return;
217232

218-
while (!isVerticalWhitespace(*First))
233+
do {
219234
if (++First == End)
220235
return;
236+
Len = isEOL(First, End);
237+
} while (!Len);
221238

222239
if (First[-1] != '\\')
223240
return;
224241

225-
++First; // Keep going...
242+
First += Len;
243+
// Keep skipping lines...
226244
}
227245
}
228246

@@ -277,7 +295,7 @@ static bool isQuoteCppDigitSeparator(const char *const Start,
277295
}
278296

279297
static void skipLine(const char *&First, const char *const End) {
280-
do {
298+
for (;;) {
281299
assert(First <= End);
282300
if (First == End)
283301
return;
@@ -322,9 +340,10 @@ static void skipLine(const char *&First, const char *const End) {
322340
return;
323341

324342
// Skip over the newline.
325-
assert(isVerticalWhitespace(*First));
326-
skipNewline(First, End);
327-
} while (First[-2] == '\\'); // Continue past line-continuations.
343+
unsigned Len = skipNewline(First, End);
344+
if (!wasLineContinuation(First, Len)) // Continue past line-continuations.
345+
break;
346+
}
328347
}
329348

330349
static void skipDirective(StringRef Name, const char *&First,
@@ -379,6 +398,8 @@ void Minimizer::printToNewline(const char *&First, const char *const End) {
379398
// Print out the string.
380399
if (Last == End || Last == First || Last[-1] != '\\') {
381400
append(First, reverseOverSpaces(First, Last));
401+
First = Last;
402+
skipNewline(First, End);
382403
return;
383404
}
384405

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test CF+LF are properly handled along with quoted, multi-line #error
2+
// RUN: cat %s | unix2dos | %clang_cc1 -DOTHER -print-dependency-directives-minimized-source 2>&1 | FileCheck %s
3+
4+
#ifndef TEST
5+
#error "message \
6+
more message \
7+
even more"
8+
#endif
9+
10+
#ifdef OTHER
11+
#include <string>
12+
#endif
13+
14+
// CHECK: #ifdef OTHER
15+
// CHECK-NEXT: #include <string>
16+
// CHECK-NEXT: #endif

0 commit comments

Comments
 (0)