jansvoboda11 created this revision. jansvoboda11 added reviewers: Bigcheese, arphaman. jansvoboda11 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
The minimizer tries to squash multi-line macro definitions into single line. For that to work, contents of each line need to be separated by a space. Since we always strip leading whitespace on lines of a macro definition, the code currently tries to preserve exactly one space that appeared before the backslash. This means the following code: #define FOO(BAR) \ #BAR \ baz gets minimized into: #define FOO(BAR) #BAR baz However, if there are no spaces before the backslash on line 2: #define FOO(BAR) \ #BAR\ baz no space can be preserved, leading to (most likely) malformed macro definition: #define FOO(BAR) #BARbaz This patch makes sure we always put exactly one space at the end of line ending with a backslash. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D119231 Files: clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp Index: clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp =================================================================== --- clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp +++ clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp @@ -713,6 +713,17 @@ Out.data()); } +TEST(MinimizeSourceToDependencyDirectivesTest, + SupportWhitespaceBeforeLineContinuation) { + SmallVector<char, 128> Out; + + ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define FOO(BAR) \\\n" + " #BAR\\\n" + " baz\n", + Out)); + EXPECT_STREQ("#define FOO(BAR) #BAR baz\n", Out.data()); +} + TEST(MinimizeSourceToDependencyDirectivesTest, SupportWhitespaceBeforeLineContinuationInStringSkipping) { SmallVector<char, 128> Out; Index: clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp =================================================================== --- clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -270,6 +270,15 @@ return Last; } +static const char *findLastNonSpaceNonBackslash(const char *First, + const char *Last) { + assert(First <= Last); + while (First != Last && + (isHorizontalWhitespace(Last[-1]) || Last[-1] == '\\')) + --Last; + return Last; +} + static const char *findFirstTrailingSpace(const char *First, const char *Last) { const char *LastNonSpace = findLastNonSpace(First, Last); @@ -434,11 +443,11 @@ return; } - // 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)); + // Print up to the last character that's not a whitespace or backslash. + // Then print exactly one space, which matters when tokens are separated by + // a line continuation. + append(First, findLastNonSpaceNonBackslash(First, Last)); + put(' '); First = Last; skipNewline(First, End);
Index: clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp =================================================================== --- clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp +++ clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp @@ -713,6 +713,17 @@ Out.data()); } +TEST(MinimizeSourceToDependencyDirectivesTest, + SupportWhitespaceBeforeLineContinuation) { + SmallVector<char, 128> Out; + + ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define FOO(BAR) \\\n" + " #BAR\\\n" + " baz\n", + Out)); + EXPECT_STREQ("#define FOO(BAR) #BAR baz\n", Out.data()); +} + TEST(MinimizeSourceToDependencyDirectivesTest, SupportWhitespaceBeforeLineContinuationInStringSkipping) { SmallVector<char, 128> Out; Index: clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp =================================================================== --- clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -270,6 +270,15 @@ return Last; } +static const char *findLastNonSpaceNonBackslash(const char *First, + const char *Last) { + assert(First <= Last); + while (First != Last && + (isHorizontalWhitespace(Last[-1]) || Last[-1] == '\\')) + --Last; + return Last; +} + static const char *findFirstTrailingSpace(const char *First, const char *Last) { const char *LastNonSpace = findLastNonSpace(First, Last); @@ -434,11 +443,11 @@ return; } - // 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)); + // Print up to the last character that's not a whitespace or backslash. + // Then print exactly one space, which matters when tokens are separated by + // a line continuation. + append(First, findLastNonSpaceNonBackslash(First, Last)); + put(' '); First = Last; skipNewline(First, End);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits