summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/SourceManager.cpp106
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp2
-rw-r--r--clang/lib/Lex/Lexer.cpp31
-rw-r--r--clang/lib/Lex/Preprocessor.cpp60
4 files changed, 97 insertions, 102 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index c27675f38bc..8cc7a8438d2 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/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/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 1083d5ef1c0..2d58beead8b 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/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/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 52a7a04567a..451e1cebfff 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/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/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 066909475fe..c7578204944 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/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
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud