diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -1470,24 +1470,35 @@ /// Returns whether \p Loc is located in a 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(""); } /// Returns whether \p Loc is located in a 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(""); } /// Returns whether \p Loc is located in a 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(""); } /// 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 --- a/clang/unittests/Basic/SourceManagerTest.cpp +++ b/clang/unittests/Basic/SourceManagerTest.cpp @@ -51,6 +51,73 @@ IntrusiveRefCntPtr 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 BuiltInBuf = + llvm::MemoryBuffer::getMemBuffer(Source); + const FileEntry *BuiltInFile = + FileMgr.getVirtualFile("", 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 CommandLineBuf = + llvm::MemoryBuffer::getMemBuffer(Source); + const FileEntry *CommandLineFile = FileMgr.getVirtualFile( + "", 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 ScratchSpaceBuf = + llvm::MemoryBuffer::getMemBuffer(Source); + const FileEntry *ScratchSpaceFile = FileMgr.getVirtualFile( + "", 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" @@ -84,11 +151,11 @@ ASSERT_EQ(tok::l_square, toks[0].getKind()); ASSERT_EQ(tok::identifier, toks[1].getKind()); ASSERT_EQ(tok::r_square, toks[2].getKind()); - + SourceLocation lsqrLoc = toks[0].getLocation(); SourceLocation idLoc = toks[1].getLocation(); SourceLocation rsqrLoc = toks[2].getLocation(); - + SourceLocation macroExpStartLoc = SourceMgr.translateLineCol(mainFileID, 2, 1); SourceLocation macroExpEndLoc = SourceMgr.translateLineCol(mainFileID, 2, 6); ASSERT_TRUE(macroExpStartLoc.isFileID());