diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Basic/SourceManager.cpp | |
parent | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff) | |
download | src-test2-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz src-test2-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip |
Notes
Diffstat (limited to 'lib/Basic/SourceManager.cpp')
-rw-r--r-- | lib/Basic/SourceManager.cpp | 302 |
1 files changed, 189 insertions, 113 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 6640c61ff3b7..962cb4c42a8a 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -16,10 +16,9 @@ #include "clang/Basic/FileManager.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" -#include "llvm/Support/Streams.h" #include <algorithm> -#include <iostream> using namespace clang; using namespace SrcMgr; using llvm::MemoryBuffer; @@ -42,29 +41,74 @@ unsigned ContentCache::getSizeBytesMapped() const { /// getSize - Returns the size of the content encapsulated by this ContentCache. /// This can be the size of the source file or the size of an arbitrary /// scratch buffer. If the ContentCache encapsulates a source file, that -/// file is not lazily brought in from disk to satisfy this query. +/// file is not lazily brought in from disk to satisfy this query unless it +/// needs to be truncated due to a truncateAt() call. unsigned ContentCache::getSize() const { - return Entry ? Entry->getSize() : Buffer->getBufferSize(); + return Buffer ? Buffer->getBufferSize() : Entry->getSize(); } -const llvm::MemoryBuffer *ContentCache::getBuffer() const { +const llvm::MemoryBuffer *ContentCache::getBuffer() const { // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer && Entry) { // FIXME: Should we support a way to not have to do this check over // and over if we cannot open the file? Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize()); + if (isTruncated()) + const_cast<ContentCache *>(this)->truncateAt(TruncateAtLine, + TruncateAtColumn); } return Buffer; } +void ContentCache::truncateAt(unsigned Line, unsigned Column) { + TruncateAtLine = Line; + TruncateAtColumn = Column; + + if (!isTruncated() || !Buffer) + return; + + // Find the byte position of the truncation point. + const char *Position = Buffer->getBufferStart(); + for (unsigned Line = 1; Line < TruncateAtLine; ++Line) { + for (; *Position; ++Position) { + if (*Position != '\r' && *Position != '\n') + continue; + + // Eat \r\n or \n\r as a single line. + if ((Position[1] == '\r' || Position[1] == '\n') && + Position[0] != Position[1]) + ++Position; + ++Position; + break; + } + } + + for (unsigned Column = 1; Column < TruncateAtColumn; ++Column, ++Position) { + if (!*Position) + break; + + if (*Position == '\t') + Column += 7; + } + + // Truncate the buffer. + if (Position != Buffer->getBufferEnd()) { + MemoryBuffer *TruncatedBuffer + = MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position, + Buffer->getBufferIdentifier()); + delete Buffer; + Buffer = TruncatedBuffer; + } +} + unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { // Look up the filename in the string table, returning the pre-existing value // if it exists. - llvm::StringMapEntry<unsigned> &Entry = + llvm::StringMapEntry<unsigned> &Entry = FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U); if (Entry.getValue() != ~0U) return Entry.getValue(); - + // Otherwise, assign this the next available ID. Entry.setValue(FilenamesByID.size()); FilenamesByID.push_back(&Entry); @@ -77,25 +121,25 @@ unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, unsigned LineNo, int FilenameID) { std::vector<LineEntry> &Entries = LineEntries[FID]; - + assert((Entries.empty() || Entries.back().FileOffset < Offset) && "Adding line entries out of order!"); - + SrcMgr::CharacteristicKind Kind = SrcMgr::C_User; unsigned IncludeOffset = 0; - + if (!Entries.empty()) { // If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember // that we are still in "foo.h". if (FilenameID == -1) FilenameID = Entries.back().FilenameID; - + // If we are after a line marker that switched us to system header mode, or // that set #include information, preserve it. Kind = Entries.back().FileKind; IncludeOffset = Entries.back().IncludeOffset; } - + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind, IncludeOffset)); } @@ -110,9 +154,9 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind) { assert(FilenameID != -1 && "Unspecified filename should use other accessor"); - + std::vector<LineEntry> &Entries = LineEntries[FID]; - + assert((Entries.empty() || Entries.back().FileOffset < Offset) && "Adding line entries out of order!"); @@ -124,14 +168,14 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, } else if (EntryExit == 2) { assert(!Entries.empty() && Entries.back().IncludeOffset && "PPDirectives should have caught case when popping empty include stack"); - + // Get the include loc of the last entries' include loc as our include loc. IncludeOffset = 0; if (const LineEntry *PrevEntry = FindNearestLineEntry(FID, Entries.back().IncludeOffset)) IncludeOffset = PrevEntry->IncludeOffset; } - + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, IncludeOffset)); } @@ -139,7 +183,7 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, /// FindNearestLineEntry - Find the line entry nearest to FID that is before /// it. If there is no line entry before Offset in FID, return null. -const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, +const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, unsigned Offset) { const std::vector<LineEntry> &Entries = LineEntries[FID]; assert(!Entries.empty() && "No #line entries for this FID after all!"); @@ -158,13 +202,13 @@ const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID, /// \brief Add a new line entry that has already been encoded into /// the internal representation of the line table. -void LineTableInfo::AddEntry(unsigned FID, +void LineTableInfo::AddEntry(unsigned FID, const std::vector<LineEntry> &Entries) { LineEntries[FID] = Entries; } /// getLineTableFilenameID - Return the uniqued ID for the specified filename. -/// +/// unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { if (LineTable == 0) LineTable = new LineTableInfo(); @@ -178,12 +222,12 @@ unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID) { std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); - + const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - + if (LineTable == 0) LineTable = new LineTableInfo(); LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID); @@ -201,16 +245,16 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, "Can't set flags without setting the filename!"); return AddLineNote(Loc, LineNo, FilenameID); } - + std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); - + // Remember that this file has #line directives now if it doesn't already. const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); - + if (LineTable == 0) LineTable = new LineTableInfo(); - + SrcMgr::CharacteristicKind FileKind; if (IsExternCHeader) FileKind = SrcMgr::C_ExternCSystem; @@ -218,13 +262,13 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, FileKind = SrcMgr::C_System; else FileKind = SrcMgr::C_User; - + unsigned EntryExit = 0; if (IsFileEntry) EntryExit = 1; else if (IsFileExit) EntryExit = 2; - + LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID, EntryExit, FileKind); } @@ -241,7 +285,7 @@ LineTableInfo &SourceManager::getLineTable() { SourceManager::~SourceManager() { delete LineTable; - + // Delete FileEntry objects corresponding to content caches. Since the actual // content cache objects are bump pointer allocated, we just have to run the // dtors, but we call the deallocate method for completeness. @@ -262,10 +306,10 @@ void SourceManager::clearIDTables() { LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = 0; LastFileIDLookup = FileID(); - + if (LineTable) LineTable->clear(); - + // Use up FileID #0 as an invalid instantiation. NextOffset = 0; createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); @@ -276,11 +320,11 @@ void SourceManager::clearIDTables() { const ContentCache * SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { assert(FileEnt && "Didn't specify a file entry to use?"); - + // Do we already have information about this file? ContentCache *&Entry = FileInfos[FileEnt]; if (Entry) return Entry; - + // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned // so that FileInfo can use the low 3 bits of the pointer for its own // nefarious purposes. @@ -288,6 +332,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { EntryAlign = std::max(8U, EntryAlign); Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); new (Entry) ContentCache(FileEnt); + + if (FileEnt == TruncateFile) { + // If we had queued up a file truncation request, perform the truncation + // now. + Entry->truncateAt(TruncateAtLine, TruncateAtColumn); + TruncateFile = 0; + TruncateAtLine = 0; + TruncateAtColumn = 0; + } + return Entry; } @@ -350,12 +404,12 @@ FileID SourceManager::createFileID(const ContentCache *File, if (PreallocatedID) { // If we're filling in a preallocated ID, just load in the file // entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && + assert(PreallocatedID < SLocEntryLoaded.size() && "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && + assert(!SLocEntryLoaded[PreallocatedID] && "Source location entry already loaded"); assert(Offset && "Preallocate source location cannot have zero offset"); - SLocEntryTable[PreallocatedID] + SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter)); SLocEntryLoaded[PreallocatedID] = true; FileID FID = FileID::get(PreallocatedID); @@ -364,13 +418,13 @@ FileID SourceManager::createFileID(const ContentCache *File, return LastFileIDLookup = FID; } - SLocEntryTable.push_back(SLocEntry::get(NextOffset, + SLocEntryTable.push_back(SLocEntry::get(NextOffset, FileInfo::get(IncludePos, File, FileCharacter))); unsigned FileSize = File->getSize(); assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!"); NextOffset += FileSize+1; - + // Set LastFileIDLookup to the newly created file. The next getFileID call is // almost guaranteed to be from that file. FileID FID = FileID::get(SLocEntryTable.size()-1); @@ -392,9 +446,9 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, if (PreallocatedID) { // If we're filling in a preallocated ID, just load in the // instantiation entry and return. - assert(PreallocatedID < SLocEntryLoaded.size() && + assert(PreallocatedID < SLocEntryLoaded.size() && "Preallocate ID out-of-range"); - assert(!SLocEntryLoaded[PreallocatedID] && + assert(!SLocEntryLoaded[PreallocatedID] && "Source location entry already loaded"); assert(Offset && "Preallocate source location cannot have zero offset"); SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II); @@ -427,7 +481,7 @@ SourceManager::getBufferData(FileID FID) const { /// FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { assert(SLocOffset && "Invalid FileID"); - + // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file location // or are "near" the cached instantiation location. 2) others are just @@ -436,11 +490,11 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { // To handle this, we do a linear search for up to 8 steps to catch #1 quickly // then we fall back to a less cache efficient, but more scalable, binary // search to find the location. - + // See if this is near the file point - worst case we start scanning from the // most newly created FileID. std::vector<SrcMgr::SLocEntry>::const_iterator I; - + if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { // Neither loc prunes our search. I = SLocEntryTable.end(); @@ -475,7 +529,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { if (++NumProbes == 8) break; } - + // Convert "I" back into an index. We know that it is an entry whose index is // larger than the offset we are looking for. unsigned GreaterIndex = I-SLocEntryTable.begin(); @@ -487,16 +541,16 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { while (1) { unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset(); - + ++NumProbes; - + // If the offset of the midpoint is too large, chop the high side of the // range to the midpoint. if (MidOffset > SLocOffset) { GreaterIndex = MiddleIndex; continue; } - + // If the middle index contains the value, succeed and return. if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) { #if 0 @@ -514,7 +568,7 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { NumBinaryProbes += NumProbes; return Res; } - + // Otherwise, move the low-side up to the middle index. LessIndex = MiddleIndex; } @@ -551,12 +605,12 @@ SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, SourceLocation Loc; do { Loc = E->getInstantiation().getInstantiationLocStart(); - + FID = getFileID(Loc); E = &getSLocEntry(FID); Offset += Loc.getOffset()-E->getOffset(); } while (!Loc.isFileID()); - + return std::make_pair(FID, Offset); } @@ -569,12 +623,12 @@ SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, SourceLocation Loc; do { Loc = E->getInstantiation().getSpellingLoc(); - + FID = getFileID(Loc); E = &getSLocEntry(FID); Offset += Loc.getOffset()-E->getOffset(); } while (!Loc.isFileID()); - + return std::make_pair(FID, Offset); } @@ -604,10 +658,10 @@ SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const { std::pair<SourceLocation,SourceLocation> SourceManager::getInstantiationRange(SourceLocation Loc) const { if (Loc.isFileID()) return std::make_pair(Loc, Loc); - + std::pair<SourceLocation,SourceLocation> Res = getImmediateInstantiationRange(Loc); - + // Fully resolve the start and end locations to their ultimate instantiation // points. while (!Res.first.isFileID()) @@ -629,7 +683,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const { // Note that this is a hot function in the getSpelling() path, which is // heavily used by -E mode. std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL); - + // Note that calling 'getBuffer()' may lazily page in a source file. return getSLocEntry(LocInfo.first).getFile().getContentCache() ->getBuffer()->getBufferStart() + LocInfo.second; @@ -640,7 +694,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const { /// this is significantly cheaper to compute than the line number. unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const { const char *Buf = getBuffer(FID)->getBufferStart(); - + unsigned LineStart = FilePos; while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') --LineStart; @@ -663,17 +717,17 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const { static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE; -static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ +static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ // Note that calling 'getBuffer()' may lazily page in the file. const MemoryBuffer *Buffer = FI->getBuffer(); - + // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. std::vector<unsigned> LineOffsets; - + // Line #1 starts at char 0. LineOffsets.push_back(0); - + const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); unsigned Offs = 0; @@ -686,7 +740,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ ++NextBuf; Offs += NextBuf-Buf; Buf = NextBuf; - + if (Buf[0] == '\n' || Buf[0] == '\r') { // If this is \n\r or \r\n, skip both characters. if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) @@ -700,7 +754,7 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ ++Offs, ++Buf; } } - + // Copy the offsets into the FileInfo structure. FI->NumLines = LineOffsets.size(); FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size()); @@ -718,7 +772,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { else Content = const_cast<ContentCache*>(getSLocEntry(FID) .getFile().getContentCache()); - + // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) @@ -729,11 +783,11 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { unsigned *SourceLineCache = Content->SourceLineCache; unsigned *SourceLineCacheStart = SourceLineCache; unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; - + unsigned QueriedFilePos = FilePos+1; // FIXME: I would like to be convinced that this code is worth being as - // complicated as it is, binary search isn't that slow. + // complicated as it is, binary search isn't that slow. // // If it is worth being optimized, then in my opinion it could be more // performant, simpler, and more obviously correct by just "galloping" outward @@ -749,7 +803,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { if (QueriedFilePos >= LastLineNoFilePos) { // FIXME: Potential overflow? SourceLineCache = SourceLineCache+LastLineNoResult-1; - + // The query is likely to be nearby the previous one. Here we check to // see if it is within 5, 10 or 20 lines. It can be far away in cases // where big comment blocks and vertical whitespace eat up lines but @@ -771,17 +825,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; } } - + // If the spread is large, do a "radix" test as our initial guess, based on // the assumption that lines average to approximately the same length. // NOTE: This is currently disabled, as it does not appear to be profitable in // initial measurements. if (0 && SourceLineCacheEnd-SourceLineCache > 20) { unsigned FileLen = Content->SourceLineCache[Content->NumLines-1]; - + // Take a stab at guessing where it is. unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen; - + // Check for -10 and +10 lines. unsigned LowerBound = std::max(int(ApproxPos-10), 0); unsigned UpperBound = std::min(ApproxPos+10, FileLen); @@ -790,17 +844,17 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { if (SourceLineCache < SourceLineCacheStart+LowerBound && SourceLineCacheStart[LowerBound] < QueriedFilePos) SourceLineCache = SourceLineCacheStart+LowerBound; - + // If the computed upper bound is greater than the query location, move it. if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound && SourceLineCacheStart[UpperBound] >= QueriedFilePos) SourceLineCacheEnd = SourceLineCacheStart+UpperBound; } - + unsigned *Pos = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); unsigned LineNo = Pos-SourceLineCacheStart; - + LastLineNoFileIDQuery = FID; LastLineNoContentCache = Content; LastLineNoFilePos = QueriedFilePos; @@ -820,14 +874,14 @@ unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const { } /// getFileCharacteristic - return the file characteristic of the specified -/// source location, indicating whether this is a normal file, a system +/// source location, indicating whether this is a normal file, a system /// header, or an "implicit extern C" system header. /// /// This state can be modified with flags on GNU linemarker directives like: /// # 4 "foo.h" 3 /// which changes all source locations in the current file after that to be /// considered to be from a system header. -SrcMgr::CharacteristicKind +SrcMgr::CharacteristicKind SourceManager::getFileCharacteristic(SourceLocation Loc) const { assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!"); std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); @@ -837,12 +891,12 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const { // state. if (!FI.hasLineDirectives()) return FI.getFileCharacteristic(); - + assert(LineTable && "Can't have linetable entries without a LineTable!"); // See if there is a #line directive before the location. const LineEntry *Entry = LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second); - + // If this is before the first line marker, use the file characteristic. if (!Entry) return FI.getFileCharacteristic(); @@ -855,7 +909,7 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const { /// for normal clients. const char *SourceManager::getBufferName(SourceLocation Loc) const { if (Loc.isInvalid()) return "<invalid loc>"; - + return getBuffer(getFileID(Loc))->getBufferIdentifier(); } @@ -869,22 +923,22 @@ const char *SourceManager::getBufferName(SourceLocation Loc) const { /// of an instantiation location, not at the spelling location. PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { if (Loc.isInvalid()) return PresumedLoc(); - + // Presumed locations are always for instantiation points. std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); - + const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile(); const SrcMgr::ContentCache *C = FI.getContentCache(); - + // To get the source name, first consult the FileEntry (if one exists) // before the MemBuffer as this will avoid unnecessarily paging in the // MemBuffer. - const char *Filename = + const char *Filename = C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second); unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second); SourceLocation IncludeLoc = FI.getIncludeLoc(); - + // If we have #line directives in this file, update and overwrite the physical // location info if appropriate. if (FI.hasLineDirectives()) { @@ -902,9 +956,9 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // total. unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset); LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1); - + // Note that column numbers are not molested by line markers. - + // Handle virtual #include manipulation. if (Entry->IncludeOffset) { IncludeLoc = getLocForStartOfFile(LocInfo.first); @@ -933,7 +987,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, if (FI == FileInfos.end()) return SourceLocation(); ContentCache *Content = FI->second; - + // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) @@ -941,7 +995,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, if (Line > Content->NumLines) return SourceLocation(); - + unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Content->getBuffer()->getBufferStart() + FilePos; unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf; @@ -952,7 +1006,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, ++i; if (i < Col-1) return SourceLocation(); - + return getLocForStartOfFile(Content->FirstFID). getFileLocWithOffset(FilePos + Col - 1); } @@ -965,24 +1019,24 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!"); if (LHS == RHS) return false; - + std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); - + // If the source locations are in the same file, just compare offsets. if (LOffs.first == ROffs.first) return LOffs.second < ROffs.second; // If we are comparing a source location with multiple locations in the same // file, we get a big win by caching the result. - + if (LastLFIDForBeforeTUCheck == LOffs.first && LastRFIDForBeforeTUCheck == ROffs.first) return LastResForBeforeTUCheck; - + LastLFIDForBeforeTUCheck = LOffs.first; LastRFIDForBeforeTUCheck = ROffs.first; - + // "Traverse" the include/instantiation stacks of both locations and try to // find a common "ancestor". // @@ -1000,15 +1054,15 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, UpperLoc = Entry.getInstantiation().getInstantiationLocStart(); else UpperLoc = Entry.getFile().getIncludeLoc(); - + if (UpperLoc.isInvalid()) break; // We reached the top. - + ROffs = getDecomposedLoc(UpperLoc); - + if (LOffs.first == ROffs.first) return LastResForBeforeTUCheck = LOffs.second < ROffs.second; - + ROffsMap[ROffs.first] = ROffs.second; } @@ -1022,33 +1076,33 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, UpperLoc = Entry.getInstantiation().getInstantiationLocStart(); else UpperLoc = Entry.getFile().getIncludeLoc(); - + if (UpperLoc.isInvalid()) break; // We reached the top. - + LOffs = getDecomposedLoc(UpperLoc); - + std::map<FileID, unsigned>::iterator I = ROffsMap.find(LOffs.first); if (I != ROffsMap.end()) return LastResForBeforeTUCheck = LOffs.second < I->second; } - + // No common ancestor. // Now we are getting into murky waters. Most probably this is because one // location is in the predefines buffer. - + const FileEntry *LEntry = getSLocEntry(LOffs.first).getFile().getContentCache()->Entry; const FileEntry *REntry = getSLocEntry(ROffs.first).getFile().getContentCache()->Entry; - + // If the locations are in two memory buffers we give up, we can't answer // which one should be considered first. // FIXME: Should there be a way to "include" memory buffers in the translation // unit ? assert((LEntry != 0 || REntry != 0) && "Locations in memory buffers."); (void) REntry; - + // Consider the memory buffer as coming before the file in the translation // unit. if (LEntry == 0) @@ -1059,26 +1113,48 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, } } +void SourceManager::truncateFileAt(const FileEntry *Entry, unsigned Line, + unsigned Column) { + llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator FI + = FileInfos.find(Entry); + if (FI != FileInfos.end()) { + FI->second->truncateAt(Line, Column); + return; + } + + // We cannot perform the truncation until we actually see the file, so + // save the truncation information. + assert(TruncateFile == 0 && "Can't queue up multiple file truncations!"); + TruncateFile = Entry; + TruncateAtLine = Line; + TruncateAtColumn = Column; +} + +/// \brief Determine whether this file was truncated. +bool SourceManager::isTruncatedFile(FileID FID) const { + return getSLocEntry(FID).getFile().getContentCache()->isTruncated(); +} + /// PrintStats - Print statistics to stderr. /// void SourceManager::PrintStats() const { - llvm::cerr << "\n*** Source Manager Stats:\n"; - llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size() - << " mem buffers mapped.\n"; - llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, " - << NextOffset << "B of Sloc address space used.\n"; - + llvm::errs() << "\n*** Source Manager Stats:\n"; + llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size() + << " mem buffers mapped.\n"; + llvm::errs() << SLocEntryTable.size() << " SLocEntry's allocated, " + << NextOffset << "B of Sloc address space used.\n"; + unsigned NumLineNumsComputed = 0; unsigned NumFileBytesMapped = 0; for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ NumLineNumsComputed += I->second->SourceLineCache != 0; NumFileBytesMapped += I->second->getSizeBytesMapped(); } - - llvm::cerr << NumFileBytesMapped << " bytes of files mapped, " - << NumLineNumsComputed << " files with line #'s computed.\n"; - llvm::cerr << "FileID scans: " << NumLinearScans << " linear, " - << NumBinaryProbes << " binary.\n"; + + llvm::errs() << NumFileBytesMapped << " bytes of files mapped, " + << NumLineNumsComputed << " files with line #'s computed.\n"; + llvm::errs() << "FileID scans: " << NumLinearScans << " linear, " + << NumBinaryProbes << " binary.\n"; } ExternalSLocEntrySource::~ExternalSLocEntrySource() { } |