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,7 +244,8 @@ } } -static const char *reverseOverSpaces(const char *First, const char *Last) { +static const char *reverseOverSpacesUntilFirstSpace(const char *First, + const char *Last) { assert(First <= Last); const char *PrevLast = Last; while (First != Last && isHorizontalWhitespace(Last[-1])) { @@ -254,6 +255,13 @@ return PrevLast; } +static const char *reverseOverSpaces(const char *First, const char *Last) { + assert(First <= Last); + while (First != Last && isHorizontalWhitespace(Last[-1])) + --Last; + return Last; +} + static void skipLineComment(const char *&First, const char *const End) { assert(First[0] == '/' && First[1] == '/'); First += 2; @@ -385,7 +393,7 @@ } // Deal with "//..." and "/*...*/". - append(First, reverseOverSpaces(First, Last)); + append(First, reverseOverSpacesUntilFirstSpace(First, Last)); First = Last; if (Last[1] == '/') { @@ -400,15 +408,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 = reverseOverSpaces(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, reverseOverSpacesUntilFirstSpace( + 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;