[clang] e881d85 - Allow interfaces to operate on in-memory buffers with no source location info.

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 26 06:46:48 PDT 2022


Author: Tapasweni Pathak
Date: 2022-06-26T13:21:23Z
New Revision: e881d85371bf9b024e0668f1667fefde4df05711

URL: https://github.com/llvm/llvm-project/commit/e881d85371bf9b024e0668f1667fefde4df05711
DIFF: https://github.com/llvm/llvm-project/commit/e881d85371bf9b024e0668f1667fefde4df05711.diff

LOG: Allow interfaces to operate on in-memory buffers with no source location info.

This patch is a part of the upstreaming efforts. Cling has the ability to spawn
child interpreters (mainly for auto completions). The child interpreter import
Decls using the ASTImporter which casuses the assertion here
https://github.com/llvm/llvm-project/blob/65eb74e94b414fcde6bfa810d1c30c7fcb136b77/clang/include/clang/Basic/SourceLocation.h#L322

The patch is co-developed with V. Vassilev.

Differential revision: https://reviews.llvm.org/D88780

Added: 
    

Modified: 
    clang/include/clang/Basic/SourceManager.h
    clang/unittests/Basic/SourceManagerTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h
index 73e6353109d92..5bdeecb07cd9e 100644
--- a/clang/include/clang/Basic/SourceManager.h
+++ b/clang/include/clang/Basic/SourceManager.h
@@ -1473,24 +1473,35 @@ class SourceManager : public RefCountedBase<SourceManager> {
 
   /// Returns whether \p Loc is located in a <built-in> file.
   bool isWrittenInBuiltinFile(SourceLocation Loc) const {
-    StringRef Filename(getPresumedLoc(Loc).getFilename());
+    PresumedLoc Presumed = getPresumedLoc(Loc);
+    if (Presumed.isInvalid())
+      return false;
+    StringRef Filename(Presumed.getFilename());
     return Filename.equals("<built-in>");
   }
 
   /// Returns whether \p Loc is located in a <command line> file.
   bool isWrittenInCommandLineFile(SourceLocation Loc) const {
-    StringRef Filename(getPresumedLoc(Loc).getFilename());
+    PresumedLoc Presumed = getPresumedLoc(Loc);
+    if (Presumed.isInvalid())
+      return false;
+    StringRef Filename(Presumed.getFilename());
     return Filename.equals("<command line>");
   }
 
   /// Returns whether \p Loc is located in a <scratch space> file.
   bool isWrittenInScratchSpace(SourceLocation Loc) const {
-    StringRef Filename(getPresumedLoc(Loc).getFilename());
+    PresumedLoc Presumed = getPresumedLoc(Loc);
+    if (Presumed.isInvalid())
+      return false;
+    StringRef Filename(Presumed.getFilename());
     return Filename.equals("<scratch space>");
   }
 
   /// Returns if a SourceLocation is in a system header.
   bool isInSystemHeader(SourceLocation Loc) const {
+    if (Loc.isInvalid())
+      return false;
     return isSystem(getFileCharacteristic(Loc));
   }
 

diff  --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp
index dadfcc94ac0d3..e98100faedbe2 100644
--- a/clang/unittests/Basic/SourceManagerTest.cpp
+++ b/clang/unittests/Basic/SourceManagerTest.cpp
@@ -51,6 +51,73 @@ class SourceManagerTest : public ::testing::Test {
   IntrusiveRefCntPtr<TargetInfo> Target;
 };
 
+TEST_F(SourceManagerTest, isInMemoryBuffersNoSourceLocationInfo) {
+  // Check for invalid source location for each method
+  SourceLocation LocEmpty;
+  bool isWrittenInBuiltInFileFalse = SourceMgr.isWrittenInBuiltinFile(LocEmpty);
+  bool isWrittenInCommandLineFileFalse =
+      SourceMgr.isWrittenInCommandLineFile(LocEmpty);
+  bool isWrittenInScratchSpaceFalse =
+      SourceMgr.isWrittenInScratchSpace(LocEmpty);
+
+  EXPECT_FALSE(isWrittenInBuiltInFileFalse);
+  EXPECT_FALSE(isWrittenInCommandLineFileFalse);
+  EXPECT_FALSE(isWrittenInScratchSpaceFalse);
+
+  // Check for valid source location per filename for each method
+  const char *Source = "int x";
+
+  std::unique_ptr<llvm::MemoryBuffer> BuiltInBuf =
+      llvm::MemoryBuffer::getMemBuffer(Source);
+  const FileEntry *BuiltInFile =
+      FileMgr.getVirtualFile("<built-in>", BuiltInBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(BuiltInFile, std::move(BuiltInBuf));
+  FileID BuiltInFileID =
+      SourceMgr.getOrCreateFileID(BuiltInFile, SrcMgr::C_User);
+  SourceMgr.setMainFileID(BuiltInFileID);
+  SourceLocation LocBuiltIn =
+      SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  bool isWrittenInBuiltInFileTrue =
+      SourceMgr.isWrittenInBuiltinFile(LocBuiltIn);
+
+  std::unique_ptr<llvm::MemoryBuffer> CommandLineBuf =
+      llvm::MemoryBuffer::getMemBuffer(Source);
+  const FileEntry *CommandLineFile = FileMgr.getVirtualFile(
+      "<command line>", CommandLineBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(CommandLineFile, std::move(CommandLineBuf));
+  FileID CommandLineFileID =
+      SourceMgr.getOrCreateFileID(CommandLineFile, SrcMgr::C_User);
+  SourceMgr.setMainFileID(CommandLineFileID);
+  SourceLocation LocCommandLine =
+      SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  bool isWrittenInCommandLineFileTrue =
+      SourceMgr.isWrittenInCommandLineFile(LocCommandLine);
+
+  std::unique_ptr<llvm::MemoryBuffer> ScratchSpaceBuf =
+      llvm::MemoryBuffer::getMemBuffer(Source);
+  const FileEntry *ScratchSpaceFile = FileMgr.getVirtualFile(
+      "<scratch space>", ScratchSpaceBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(ScratchSpaceFile, std::move(ScratchSpaceBuf));
+  FileID ScratchSpaceFileID =
+      SourceMgr.getOrCreateFileID(ScratchSpaceFile, SrcMgr::C_User);
+  SourceMgr.setMainFileID(ScratchSpaceFileID);
+  SourceLocation LocScratchSpace =
+      SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  bool isWrittenInScratchSpaceTrue =
+      SourceMgr.isWrittenInScratchSpace(LocScratchSpace);
+
+  EXPECT_TRUE(isWrittenInBuiltInFileTrue);
+  EXPECT_TRUE(isWrittenInCommandLineFileTrue);
+  EXPECT_TRUE(isWrittenInScratchSpaceTrue);
+}
+
+TEST_F(SourceManagerTest, isInSystemHeader) {
+  // Check for invalid source location
+  SourceLocation LocEmpty;
+  bool isInSystemHeaderFalse = SourceMgr.isInSystemHeader(LocEmpty);
+  ASSERT_FALSE(isInSystemHeaderFalse);
+}
+
 TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
   const char *source =
     "#define M(x) [x]\n"


        


More information about the cfe-commits mailing list