arphaman updated this revision to Diff 161132.
arphaman marked an inline comment as done.
arphaman added a comment.

- Use lambda
- Work with spelling locs


Repository:
  rC Clang

https://reviews.llvm.org/D50740

Files:
  include/clang/Basic/SourceManager.h
  lib/Basic/SourceManager.cpp
  unittests/Basic/SourceManagerTest.cpp

Index: unittests/Basic/SourceManagerTest.cpp
===================================================================
--- unittests/Basic/SourceManagerTest.cpp
+++ unittests/Basic/SourceManagerTest.cpp
@@ -377,6 +377,123 @@
   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
 }
 
+TEST_F(SourceManagerTest, isPointWithin) {
+  const char *header = "int x;";
+
+  const char *main = "#include </test-header.h>\n"
+                     "#include </test-header.h>\n";
+
+  std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
+      llvm::MemoryBuffer::getMemBuffer(header);
+  std::unique_ptr<llvm::MemoryBuffer> MainBuf =
+      llvm::MemoryBuffer::getMemBuffer(main);
+  SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
+
+  const FileEntry *headerFile =
+      FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
+
+  TrivialModuleLoader ModLoader;
+  MemoryBufferCache PCMCache;
+  HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+                          Diags, LangOpts, &*Target);
+  Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+                  SourceMgr, PCMCache, HeaderInfo, ModLoader,
+                  /*IILookup =*/nullptr,
+                  /*OwnsHeaderSearch =*/false);
+  PP.Initialize(*Target);
+
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> Tokens;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    Tokens.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(6U, Tokens.size());
+
+  // Make sure the FileIDs are different.
+  SourceLocation L1 = Tokens[0].getLocation();
+  SourceLocation L2 = Tokens[3].getLocation();
+  ASSERT_NE(L1, L2);
+
+  // The location of the 'int' in the first inclusion is lexically within the
+  // range of the 'int' in the second inclusion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(L1, L2, L2));
+  // The location of the 'int' in the second inclusion is lexically within the
+  // range of the 'int' in the first inclusion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(L2, L1, L1));
+  // The location of the 'x' in the second inclusion is lexically within the
+  // range of the 'int' in the first inclusion and ';' in the second inclusion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(Tokens[4].getLocation(), L1,
+                                      Tokens[5].getLocation()));
+  // The location of the 'int' in the second inclusion is lexically outside of
+  // the 'x' in the first inclusion and ';' in the second inclusion.
+  ASSERT_FALSE(SourceMgr.isPointWithin(Tokens[3].getLocation(),
+                                       Tokens[1].getLocation(),
+                                       Tokens[5].getLocation()));
+}
+
+TEST_F(SourceManagerTest, isPointWithinMacroSpelling) {
+  const char *main = "#define MYMACRO int x;\n"
+                     "MYMACRO\n"
+                     "MYMACRO\n";
+
+  std::unique_ptr<llvm::MemoryBuffer> MainBuf =
+      llvm::MemoryBuffer::getMemBuffer(main);
+  SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
+
+  TrivialModuleLoader ModLoader;
+  MemoryBufferCache PCMCache;
+  HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+                          Diags, LangOpts, &*Target);
+  Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+                  SourceMgr, PCMCache, HeaderInfo, ModLoader,
+                  /*IILookup =*/nullptr,
+                  /*OwnsHeaderSearch =*/false);
+  PP.Initialize(*Target);
+
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> Tokens;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    Tokens.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(6U, Tokens.size());
+
+  // Make sure the FileIDs are different.
+  SourceLocation L1 = Tokens[0].getLocation();
+  SourceLocation L2 = Tokens[3].getLocation();
+  ASSERT_NE(L1, L2);
+
+  // The location of the 'int' in the first expansion is lexically within the
+  // range of the 'int' in the second expansion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(L1, L2, L2));
+  // The location of the 'int' in the second expansion is lexically within the
+  // range of the 'int' in the first expansion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(L2, L1, L1));
+  // The location of the 'x' in the second expansion is lexically within the
+  // range of the 'int' in the first expansion and ';' in the second expansion.
+  ASSERT_TRUE(SourceMgr.isPointWithin(Tokens[4].getLocation(), L1,
+                                      Tokens[5].getLocation()));
+  // The location of the 'int' in the second expansion is lexically outside of
+  // the 'x' in the first expansion and ';' in the second expansion.
+  ASSERT_FALSE(SourceMgr.isPointWithin(Tokens[3].getLocation(),
+                                       Tokens[1].getLocation(),
+                                       Tokens[5].getLocation()));
+}
+
 #endif
 
 } // anonymous namespace
Index: lib/Basic/SourceManager.cpp
===================================================================
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -2028,6 +2028,40 @@
   return IBTUCacheOverflow;
 }
 
+bool SourceManager::isPointWithin(SourceLocation Loc, SourceLocation Start,
+                                  SourceLocation End) const {
+  assert(Start.isValid() && End.isValid() && Loc.isValid() &&
+         "Passed invalid source location!");
+
+  std::pair<FileID, unsigned> PointLoc = getDecomposedLoc(getSpellingLoc(Loc));
+
+  auto isOrderedInSameFile =
+      [&](SourceLocation RangeLoc,
+          llvm::function_ref<bool(unsigned, unsigned)> Comparator) {
+        std::pair<FileID, unsigned> DecomposedRangeLoc =
+            getDecomposedLoc(getSpellingLoc(RangeLoc));
+        // Ensure that we check for FileEntry equivalency to account for
+        // multiple inclusions.
+        if (PointLoc.first != DecomposedRangeLoc.first &&
+            getFileEntryForID(PointLoc.first) !=
+                getFileEntryForID(DecomposedRangeLoc.first))
+          return false;
+        return Comparator(PointLoc.second, DecomposedRangeLoc.second);
+      };
+
+  // The point must be in the same file as the starting and end location.
+  // The point's offset must be >= than the starting location's offset and
+  // <= than the ending location's offset.
+  return isOrderedInSameFile(Start,
+                             [](unsigned PointOffset, unsigned StartLocOffset) {
+                               return PointOffset >= StartLocOffset;
+                             }) &&
+         isOrderedInSameFile(End,
+                             [](unsigned PointOffset, unsigned EndLocOffset) {
+                               return PointOffset <= EndLocOffset;
+                             });
+}
+
 /// Determines the order of 2 source locations in the translation unit.
 ///
 /// \returns true if LHS source location comes before RHS, false otherwise.
Index: include/clang/Basic/SourceManager.h
===================================================================
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -1577,13 +1577,13 @@
     return LHSLoaded;
   }
 
-  /// Return true if the Point is within Start and End.
+  /// Returns true if the point is within the start and end range.
+  ///
+  /// This check does a lexical check if the given point is located within a
+  /// range in one particular source file (regardless of whether the point is
+  /// located in the same inclusion span as the range).
   bool isPointWithin(SourceLocation Location, SourceLocation Start,
-                     SourceLocation End) const {
-    return Location == Start || Location == End ||
-           (isBeforeInTranslationUnit(Start, Location) &&
-            isBeforeInTranslationUnit(Location, End));
-  }
+                     SourceLocation End) const;
 
   // Iterators over FileInfos.
   using fileinfo_iterator =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to