diff --git a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp --- a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -244,14 +244,20 @@ } } -static const char *reverseOverSpaces(const char *First, const char *Last) { +static const char *findLastNonSpace(const char *First, const char *Last) { assert(First <= Last); - const char *PrevLast = Last; - while (First != Last && isHorizontalWhitespace(Last[-1])) { - PrevLast = Last; + while (First != Last && isHorizontalWhitespace(Last[-1])) --Last; - } - return PrevLast; + return Last; +} + +static const char *findFirstTrailingSpace(const char *First, + const char *Last) { + const char *LastNonSpace = findLastNonSpace(First, Last); + if (Last == LastNonSpace) + return Last; + assert(isHorizontalWhitespace(LastNonSpace[0])); + return LastNonSpace + 1; } static void skipLineComment(const char *&First, const char *const End) { @@ -385,7 +391,7 @@ } // Deal with "//..." and "/*...*/". - append(First, reverseOverSpaces(First, Last)); + append(First, findFirstTrailingSpace(First, Last)); First = Last; if (Last[1] == '/') { @@ -400,15 +406,20 @@ } while (Last != End && !isVerticalWhitespace(*Last)); // Print out the string. - if (Last == End || Last == First || Last[-1] != '\\') { - append(First, reverseOverSpaces(First, Last)); + const char *LastBeforeTrailingSpace = findLastNonSpace(First, Last); + if (Last == End || LastBeforeTrailingSpace == First || + LastBeforeTrailingSpace[-1] != '\\') { + append(First, LastBeforeTrailingSpace); First = Last; skipNewline(First, End); return; } - // Print up to the backslash, backing up over spaces. - append(First, reverseOverSpaces(First, Last - 1)); + // Print up to the backslash, backing up over spaces. Preserve at least one + // space, as the space matters when tokens are separated by a line + // continuation. + append(First, findFirstTrailingSpace( + First, LastBeforeTrailingSpace - 1)); First = Last; skipNewline(First, End); diff --git a/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp b/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp --- a/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp +++ b/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp @@ -157,19 +157,19 @@ ASSERT_FALSE(minimizeSourceToDependencyDirectives( "#define MACRO(\t)\tcon \t tent\t", Out)); - EXPECT_STREQ("#define MACRO() con \t tent\t\n", Out.data()); + EXPECT_STREQ("#define MACRO() con \t tent\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives( "#define MACRO(\f)\fcon \f tent\f", Out)); - EXPECT_STREQ("#define MACRO() con \f tent\f\n", Out.data()); + EXPECT_STREQ("#define MACRO() con \f tent\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives( "#define MACRO(\v)\vcon \v tent\v", Out)); - EXPECT_STREQ("#define MACRO() con \v tent\v\n", Out.data()); + EXPECT_STREQ("#define MACRO() con \v tent\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives( "#define MACRO \t\v\f\v\t con\f\t\vtent\v\f \v", Out)); - EXPECT_STREQ("#define MACRO con\f\t\vtent\v\n", Out.data()); + EXPECT_STREQ("#define MACRO con\f\t\vtent\n", Out.data()); } TEST(MinimizeSourceToDependencyDirectivesTest, DefineMultilineArgs) { @@ -476,6 +476,17 @@ EXPECT_STREQ("#define GUA RD\n", Out.data()); } +TEST(MinimizeSourceToDependencyDirectivesTest, + WhitespaceAfterLineContinuationSlash) { + SmallVector Out; + + ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define A 1 + \\ \n" + "2 + \\\t\n" + "3\n", + Out)); + EXPECT_STREQ("#define A 1 + 2 + 3\n", Out.data()); +} + TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) { SmallVector Out;