KyleFromKitware created this revision. KyleFromKitware added a reviewer: clang. KyleFromKitware added a project: clang. Herald added a project: All. KyleFromKitware requested review of this revision. Herald added a subscriber: cfe-commits.
And fix a few corner cases in which it returns the wrong answer. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D143099 Files: clang/include/clang/Lex/Lexer.h clang/lib/Lex/Lexer.cpp clang/unittests/Lex/LexerTest.cpp Index: clang/unittests/Lex/LexerTest.cpp =================================================================== --- clang/unittests/Lex/LexerTest.cpp +++ clang/unittests/Lex/LexerTest.cpp @@ -660,4 +660,20 @@ } EXPECT_TRUE(ToksView.empty()); } + +TEST_F(LexerTest, FindBeginningOfLine) { + auto FindBeginningOfLineOffset = [](StringRef Buffer, unsigned int Offset) -> int { + return Lexer::findBeginningOfLine(Buffer, Offset) - Buffer.data(); + }; + + EXPECT_EQ(FindBeginningOfLineOffset("int func();", 3), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func();", 0), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 13), 13); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 12), 13); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 11), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\\\nint func2();", 14), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\r\nint func2();", 13), 14); + EXPECT_EQ(FindBeginningOfLineOffset("\nint func();", 4), 1); + EXPECT_EQ(FindBeginningOfLineOffset("\\\nint func();", 5), 0); +} } // anonymous namespace Index: clang/lib/Lex/Lexer.cpp =================================================================== --- clang/lib/Lex/Lexer.cpp +++ clang/lib/Lex/Lexer.cpp @@ -492,19 +492,22 @@ /// Returns the pointer that points to the beginning of line that contains /// the given offset, or null if the offset if invalid. -static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) { +const char *Lexer::findBeginningOfLine(StringRef Buffer, unsigned Offset) { const char *BufStart = Buffer.data(); if (Offset >= Buffer.size()) return nullptr; const char *LexStart = BufStart + Offset; - for (; LexStart != BufStart; --LexStart) { + while (true) { if (isVerticalWhitespace(LexStart[0]) && !Lexer::isNewLineEscaped(BufStart, LexStart)) { // LexStart should point at first character of logical line. ++LexStart; break; } + if (LexStart == BufStart) + break; + --LexStart; } return LexStart; } @@ -525,7 +528,7 @@ // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. const char *StrData = Buffer.data() + LocInfo.second; - const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second); + const char *LexStart = Lexer::findBeginningOfLine(Buffer, LocInfo.second); if (!LexStart || LexStart == StrData) return Loc; Index: clang/include/clang/Lex/Lexer.h =================================================================== --- clang/include/clang/Lex/Lexer.h +++ clang/include/clang/Lex/Lexer.h @@ -595,6 +595,10 @@ static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM); + /// Returns the pointer that points to the beginning of line that contains + /// the given offset, or null if the offset if invalid. + static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset); + /// Check if this is the first time we're lexing the input file. bool isFirstTimeLexingFile() const { return IsFirstTimeLexingFile; }
Index: clang/unittests/Lex/LexerTest.cpp =================================================================== --- clang/unittests/Lex/LexerTest.cpp +++ clang/unittests/Lex/LexerTest.cpp @@ -660,4 +660,20 @@ } EXPECT_TRUE(ToksView.empty()); } + +TEST_F(LexerTest, FindBeginningOfLine) { + auto FindBeginningOfLineOffset = [](StringRef Buffer, unsigned int Offset) -> int { + return Lexer::findBeginningOfLine(Buffer, Offset) - Buffer.data(); + }; + + EXPECT_EQ(FindBeginningOfLineOffset("int func();", 3), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func();", 0), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 13), 13); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 12), 13); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\nint func2();", 11), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\\\nint func2();", 14), 0); + EXPECT_EQ(FindBeginningOfLineOffset("int func1();\r\nint func2();", 13), 14); + EXPECT_EQ(FindBeginningOfLineOffset("\nint func();", 4), 1); + EXPECT_EQ(FindBeginningOfLineOffset("\\\nint func();", 5), 0); +} } // anonymous namespace Index: clang/lib/Lex/Lexer.cpp =================================================================== --- clang/lib/Lex/Lexer.cpp +++ clang/lib/Lex/Lexer.cpp @@ -492,19 +492,22 @@ /// Returns the pointer that points to the beginning of line that contains /// the given offset, or null if the offset if invalid. -static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) { +const char *Lexer::findBeginningOfLine(StringRef Buffer, unsigned Offset) { const char *BufStart = Buffer.data(); if (Offset >= Buffer.size()) return nullptr; const char *LexStart = BufStart + Offset; - for (; LexStart != BufStart; --LexStart) { + while (true) { if (isVerticalWhitespace(LexStart[0]) && !Lexer::isNewLineEscaped(BufStart, LexStart)) { // LexStart should point at first character of logical line. ++LexStart; break; } + if (LexStart == BufStart) + break; + --LexStart; } return LexStart; } @@ -525,7 +528,7 @@ // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. const char *StrData = Buffer.data() + LocInfo.second; - const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second); + const char *LexStart = Lexer::findBeginningOfLine(Buffer, LocInfo.second); if (!LexStart || LexStart == StrData) return Loc; Index: clang/include/clang/Lex/Lexer.h =================================================================== --- clang/include/clang/Lex/Lexer.h +++ clang/include/clang/Lex/Lexer.h @@ -595,6 +595,10 @@ static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM); + /// Returns the pointer that points to the beginning of line that contains + /// the given offset, or null if the offset if invalid. + static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset); + /// Check if this is the first time we're lexing the input file. bool isFirstTimeLexingFile() const { return IsFirstTimeLexingFile; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits