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

Reply via email to