summaryrefslogtreecommitdiff
path: root/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Basic/SourceManager.cpp
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
downloadsrc-test2-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz
src-test2-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip
Notes
Diffstat (limited to 'lib/Basic/SourceManager.cpp')
-rw-r--r--lib/Basic/SourceManager.cpp302
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() { }