summaryrefslogtreecommitdiff
path: root/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-12-15 18:49:47 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-12-15 18:49:47 +0000
commit34d02d0b37f16015f317a935c48ce8b7b64ae77b (patch)
tree2fd5819f49caecc5f520219b6b9254fe94ebb138 /lib/Basic/SourceManager.cpp
parent1569ce68681d909594d64f9b056d71f5dd7563bf (diff)
downloadsrc-test2-34d02d0b37f16015f317a935c48ce8b7b64ae77b.tar.gz
src-test2-34d02d0b37f16015f317a935c48ce8b7b64ae77b.zip
Notes
Diffstat (limited to 'lib/Basic/SourceManager.cpp')
-rw-r--r--lib/Basic/SourceManager.cpp196
1 files changed, 86 insertions, 110 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index a85bef0f29ed..354bf7befbb3 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -41,64 +41,42 @@ 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 unless it
-/// needs to be truncated due to a truncateAt() call.
+/// file is not lazily brought in from disk to satisfy this query.
unsigned ContentCache::getSize() const {
return Buffer ? Buffer->getBufferSize() : Entry->getSize();
}
-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::replaceBuffer(const llvm::MemoryBuffer *B) {
+ assert(B != Buffer);
+
+ delete Buffer;
+ Buffer = B;
}
-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;
+const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const {
+ // Lazily create the Buffer for ContentCaches that wrap files.
+ if (!Buffer && Entry) {
+ Buffer = MemoryBuffer::getFile(Entry->getName(), ErrorStr,Entry->getSize());
+
+ // If we were unable to open the file, then we are in an inconsistent
+ // situation where the content cache referenced a file which no longer
+ // exists. Most likely, we were using a stat cache with an invalid entry but
+ // the file could also have been removed during processing. Since we can't
+ // really deal with this situation, just create an empty buffer.
+ //
+ // FIXME: This is definitely not ideal, but our immediate clients can't
+ // currently handle returning a null entry here. Ideally we should detect
+ // that we are in an inconsistent situation and error out as quickly as
+ // possible.
+ if (!Buffer) {
+ const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
+ Buffer = MemoryBuffer::getNewMemBuffer(Entry->getSize(), "<invalid>");
+ char *Ptr = const_cast<char*>(Buffer->getBufferStart());
+ for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
+ Ptr[i] = FillStr[i % FillStr.size()];
}
}
-
- 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;
- }
+ return Buffer;
}
unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
@@ -332,16 +310,6 @@ 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;
}
@@ -413,8 +381,6 @@ FileID SourceManager::createFileID(const ContentCache *File,
= SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
SLocEntryLoaded[PreallocatedID] = true;
FileID FID = FileID::get(PreallocatedID);
- if (File->FirstFID.isInvalid())
- File->FirstFID = FID;
return LastFileIDLookup = FID;
}
@@ -428,8 +394,6 @@ FileID SourceManager::createFileID(const ContentCache *File,
// 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);
- if (File->FirstFID.isInvalid())
- File->FirstFID = FID;
return LastFileIDLookup = FID;
}
@@ -461,6 +425,25 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
}
+const llvm::MemoryBuffer *
+SourceManager::getMemoryBufferForFile(const FileEntry *File) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
+ if (IR == 0)
+ return 0;
+
+ return IR->getBuffer();
+}
+
+bool SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ const llvm::MemoryBuffer *Buffer) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ if (IR == 0)
+ return true;
+
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer);
+ return false;
+}
+
/// getBufferData - Return a pointer to the start and end of the source buffer
/// data for the specified FileID.
std::pair<const char*, const char*>
@@ -1007,8 +990,33 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
if (i < Col-1)
return SourceLocation();
- return getLocForStartOfFile(Content->FirstFID).
- getFileLocWithOffset(FilePos + Col - 1);
+ // Find the first file ID that corresponds to the given file.
+ FileID FirstFID;
+
+ // First, check the main file ID, since it is common to look for a
+ // location in the main file.
+ if (!MainFileID.isInvalid()) {
+ const SLocEntry &MainSLoc = getSLocEntry(MainFileID);
+ if (MainSLoc.isFile() && MainSLoc.getFile().getContentCache() == Content)
+ FirstFID = MainFileID;
+ }
+
+ if (FirstFID.isInvalid()) {
+ // The location we're looking for isn't in the main file; look
+ // through all of the source locations.
+ for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getSLocEntry(I);
+ if (SLoc.isFile() && SLoc.getFile().getContentCache() == Content) {
+ FirstFID = FileID::get(I);
+ break;
+ }
+ }
+ }
+
+ if (FirstFID.isInvalid())
+ return SourceLocation();
+
+ return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + Col - 1);
}
/// \brief Determines the order of 2 source locations in the translation unit.
@@ -1087,52 +1095,20 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
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)
- return LastResForBeforeTUCheck = true;
- else {
- assert(REntry == 0 && "Locations in not #included files ?");
- return LastResForBeforeTUCheck = false;
- }
-}
+ // There is no common ancestor, most probably because one location is in the
+ // predefines buffer.
+ //
+ // FIXME: We should rearrange the external interface so this simply never
+ // happens; it can't conceptually happen. Also see PR5662.
-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;
-}
+ // If exactly one location is a memory buffer, assume it preceeds the other.
+ bool LIsMB = !getSLocEntry(LOffs.first).getFile().getContentCache()->Entry;
+ bool RIsMB = !getSLocEntry(ROffs.first).getFile().getContentCache()->Entry;
+ if (LIsMB != RIsMB)
+ return LastResForBeforeTUCheck = LIsMB;
-/// \brief Determine whether this file was truncated.
-bool SourceManager::isTruncatedFile(FileID FID) const {
- return getSLocEntry(FID).getFile().getContentCache()->isTruncated();
+ // Otherwise, just assume FileIDs were created in order.
+ return LastResForBeforeTUCheck = (LOffs.first < ROffs.first);
}
/// PrintStats - Print statistics to stderr.