Index: cfe/trunk/include/clang/Basic/SourceLocation.h =================================================================== --- cfe/trunk/include/clang/Basic/SourceLocation.h +++ cfe/trunk/include/clang/Basic/SourceLocation.h @@ -220,6 +220,10 @@ bool operator!=(const SourceRange &X) const { return B != X.B || E != X.E; } + + void print(raw_ostream &OS, const SourceManager &SM) const; + std::string printToString(const SourceManager &SM) const; + void dump(const SourceManager &SM) const; }; /// Represents a character-granular source range. Index: cfe/trunk/lib/Basic/SourceLocation.cpp =================================================================== --- cfe/trunk/lib/Basic/SourceLocation.cpp +++ cfe/trunk/lib/Basic/SourceLocation.cpp @@ -80,6 +80,60 @@ llvm::errs() << '\n'; } +LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const { + print(llvm::errs(), SM); + llvm::errs() << '\n'; +} + +static PresumedLoc PrintDifference(raw_ostream &OS, const SourceManager &SM, + SourceLocation Loc, PresumedLoc Previous) { + if (Loc.isFileID()) { + + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + + if (PLoc.isInvalid()) { + OS << ""; + return Previous; + } + + if (Previous.isInvalid() || + strcmp(PLoc.getFilename(), Previous.getFilename()) != 0) { + OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' + << PLoc.getColumn(); + } else if (Previous.isInvalid() || PLoc.getLine() != Previous.getLine()) { + OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); + } else { + OS << "col" << ':' << PLoc.getColumn(); + } + return PLoc; + } + auto PrintedLoc = PrintDifference(OS, SM, SM.getExpansionLoc(Loc), Previous); + + OS << " '; + return PrintedLoc; +} + +void SourceRange::print(raw_ostream &OS, const SourceManager &SM) const { + + OS << '<'; + auto PrintedLoc = PrintDifference(OS, SM, B, {}); + if (B != E) { + OS << ", "; + PrintDifference(OS, SM, E, PrintedLoc); + } + OS << '>'; +} + +LLVM_DUMP_METHOD std::string +SourceRange::printToString(const SourceManager &SM) const { + std::string S; + llvm::raw_string_ostream OS(S); + print(OS, SM); + return OS.str(); +} + //===----------------------------------------------------------------------===// // FullSourceLoc //===----------------------------------------------------------------------===// Index: cfe/trunk/unittests/Basic/SourceManagerTest.cpp =================================================================== --- cfe/trunk/unittests/Basic/SourceManagerTest.cpp +++ cfe/trunk/unittests/Basic/SourceManagerTest.cpp @@ -155,6 +155,54 @@ EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, nullptr)); } +TEST_F(SourceManagerTest, locationPrintTest) { + const char *header = "#define IDENTITY(x) x\n"; + + const char *Source = "int x;\n" + "include \"test-header.h\"\n" + "IDENTITY(int y);\n" + "int z;"; + + std::unique_ptr HeaderBuf = + llvm::MemoryBuffer::getMemBuffer(header); + std::unique_ptr Buf = + llvm::MemoryBuffer::getMemBuffer(Source); + + const FileEntry *SourceFile = + FileMgr.getVirtualFile("/mainFile.cpp", Buf->getBufferSize(), 0); + SourceMgr.overrideFileContents(SourceFile, std::move(Buf)); + + const FileEntry *HeaderFile = + FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0); + SourceMgr.overrideFileContents(HeaderFile, std::move(HeaderBuf)); + + FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User); + FileID HeaderFileID = SourceMgr.getOrCreateFileID(HeaderFile, SrcMgr::C_User); + SourceMgr.setMainFileID(MainFileID); + + auto BeginLoc = SourceMgr.getLocForStartOfFile(MainFileID); + auto EndLoc = SourceMgr.getLocForEndOfFile(MainFileID); + + auto BeginEOLLoc = SourceMgr.translateLineCol(MainFileID, 1, 7); + + auto HeaderLoc = SourceMgr.getLocForStartOfFile(HeaderFileID); + + EXPECT_EQ(BeginLoc.printToString(SourceMgr), "/mainFile.cpp:1:1"); + EXPECT_EQ(EndLoc.printToString(SourceMgr), "/mainFile.cpp:4:7"); + + EXPECT_EQ(BeginEOLLoc.printToString(SourceMgr), "/mainFile.cpp:1:7"); + EXPECT_EQ(HeaderLoc.printToString(SourceMgr), "/test-header.h:1:1"); + + EXPECT_EQ(SourceRange(BeginLoc, BeginLoc).printToString(SourceMgr), + ""); + EXPECT_EQ(SourceRange(BeginLoc, BeginEOLLoc).printToString(SourceMgr), + ""); + EXPECT_EQ(SourceRange(BeginLoc, EndLoc).printToString(SourceMgr), + ""); + EXPECT_EQ(SourceRange(BeginLoc, HeaderLoc).printToString(SourceMgr), + ""); +} + #if defined(LLVM_ON_UNIX) TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {