aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-02 06:49:09 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-02 06:49:09 +0000
commit2968442603b029949246467253eeac8139a5b6d8 (patch)
treeff548e890078ba6293daa74c947dcdf57c410798 /lib
parenta46e4d91d8f3eb341f2387768db66dcfe8dd0afa (diff)
Extend the source manager with the ability to override the contents of
files with the contents of an arbitrary memory buffer. Use this new functionality to drastically clean up the way in which we handle file truncation for code-completion: all of the truncation/completion logic is now encapsulated in the preprocessor where it belongs (<rdar://problem/7434737>). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90300 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Basic/SourceManager.cpp106
-rw-r--r--lib/Frontend/CompilerInstance.cpp2
-rw-r--r--lib/Lex/Lexer.cpp31
-rw-r--r--lib/Lex/Preprocessor.cpp60
4 files changed, 97 insertions, 102 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index c27675f38b..8cc7a8438d 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -41,66 +41,29 @@ 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();
}
+void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) {
+ if (B == Buffer)
+ return;
+
+ delete Buffer;
+ Buffer = B;
+}
+
const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) 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(), ErrorStr,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.
@@ -332,16 +295,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;
}
@@ -457,6 +410,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*>
@@ -1124,28 +1096,6 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
return LastResForBeforeTUCheck = (LOffs.first < ROffs.first);
}
-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 {
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 1083d5ef1c..2d58beead8 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -287,7 +287,7 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
}
// Truncate the named file at the given line/column.
- PP.getSourceManager().truncateFileAt(Entry, Line, Column);
+ PP.SetCodeCompletionPoint(Entry, Line, Column);
// Set up the creation routine for code-completion.
if (UseDebugPrinter)
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 52a7a04567..451e1cebff 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -70,7 +70,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
" to simplify lexing!");
Is_PragmaLexer = false;
- IsEofCodeCompletion = false;
// Start of the file is a start of line.
IsAtStartOfLine = true;
@@ -105,10 +104,6 @@ Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP)
// Default to keeping comments if the preprocessor wants them.
SetCommentRetentionState(PP.getCommentRetentionState());
-
- // If the input file is truncated, the EOF is a code-completion token.
- if (PP.getSourceManager().isTruncatedFile(FID))
- IsEofCodeCompletion = true;
}
/// Lexer constructor - Create a new raw lexer object. This object is only
@@ -1326,24 +1321,16 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
// Otherwise, check if we are code-completing, then issue diagnostics for
// unterminated #if and missing newline.
- if (IsEofCodeCompletion) {
- bool isIntendedFile = true;
- if (PP && FileLoc.isFileID()) {
- SourceManager &SM = PP->getSourceManager();
- isIntendedFile = SM.isTruncatedFile(SM.getFileID(FileLoc));
- }
+ if (PP && PP->isCodeCompletionFile(FileLoc)) {
+ // We're at the end of the file, but we've been asked to consider the
+ // end of the file to be a code-completion token. Return the
+ // code-completion token.
+ Result.startToken();
+ FormTokenWithChars(Result, CurPtr, tok::code_completion);
- if (isIntendedFile) {
- // We're at the end of the file, but we've been asked to consider the
- // end of the file to be a code-completion token. Return the
- // code-completion token.
- Result.startToken();
- FormTokenWithChars(Result, CurPtr, tok::code_completion);
-
- // Only do the eof -> code_completion translation once.
- IsEofCodeCompletion = false;
- return true;
- }
+ // Only do the eof -> code_completion translation once.
+ PP->SetCodeCompletionPoint(0, 0, 0);
+ return true;
}
// If we are in a #if directive, emit an error.
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 066909475f..c757820494 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -50,7 +50,8 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup),
- BuiltinInfo(Target), CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
+ BuiltinInfo(Target), CodeCompletionFile(0), CurPPLexer(0), CurDirLookup(0),
+ Callbacks(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
OwnsHeaderSearch = OwnsHeaders;
@@ -188,6 +189,63 @@ void Preprocessor::PrintStats() {
<< NumFastTokenPaste << " on the fast path.\n";
}
+bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
+ unsigned TruncateAtLine,
+ unsigned TruncateAtColumn) {
+ using llvm::MemoryBuffer;
+
+ CodeCompletionFile = File;
+
+ // Okay to clear out the code-completion point by passing NULL.
+ if (!CodeCompletionFile)
+ return false;
+
+ // Load the actual file's contents.
+ const MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File);
+ if (!Buffer)
+ return true;
+
+ // 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());
+ SourceMgr.overrideFileContents(File, TruncatedBuffer);
+ }
+
+ return false;
+}
+
+bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) {
+ return CodeCompletionFile && FileLoc.isFileID() &&
+ SourceMgr.getFileEntryForID(SourceMgr.getFileID(FileLoc))
+ == CodeCompletionFile;
+}
+
//===----------------------------------------------------------------------===//
// Token Spelling
//===----------------------------------------------------------------------===//