From 36c35ba0aca641e60e5dbee8efbc620c08b9bd61 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 16 Mar 2010 00:35:39 +0000 Subject: [PATCH] Use SourceManager's Diagnostic object for all file-reading errors, simplifying the SourceManager interfaces somewhat. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98598 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticCommonKinds.td | 9 +- include/clang/Basic/SourceManager.h | 60 ++------- lib/AST/ASTImporter.cpp | 2 +- lib/Basic/SourceManager.cpp | 123 +++++-------------- lib/Frontend/CacheTokens.cpp | 2 +- lib/Frontend/PCHWriter.cpp | 3 +- lib/Lex/PPLexerChange.cpp | 3 +- 7 files changed, 56 insertions(+), 146 deletions(-) diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index d79f7ad42f..849e6437fb 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -63,7 +63,12 @@ def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_invalid_feature : Error<"invalid target feature '%0'">; -// Anywhere we open a file +// Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; - +def err_file_size_changed : Error< + "size of file '%0' changed since it was first processed (from %1 to %2)">, + DefaultFatal; +def err_file_modified : Error< + "file '%0' modified since it was first processed">, DefaultFatal; + } diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 4d423058fb..5e3cfd2b3c 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -35,50 +35,6 @@ class FileManager; class FileEntry; class LineTableInfo; -/// \brief Class used as a return value by operations that return an -/// \c llvm::MemoryBuffer. -/// -/// Since not all source-manager routines that return buffers are guaranteed -/// to succeed, -class BufferResult { - struct FailureData; - llvm::PointerUnion Data; - - // Cannot copy buffer result structures - BufferResult &operator=(const BufferResult &Other); - -public: - BufferResult(const BufferResult &Other); - BufferResult(const llvm::MemoryBuffer *Buffer) : Data(Buffer) { } - BufferResult(const char *FileName, llvm::StringRef ErrorStr, - const llvm::MemoryBuffer *Buffer = 0); - ~BufferResult(); - - // \brief Determine whether there was any failure when finding this buffer. - bool isInvalid() const; - - /// \brief Retrieve the memory buffer that this result refers to. If an - /// error occurs, emits a diagnostic via the given diagnostics object and - /// may return NULL. - const llvm::MemoryBuffer *getBuffer(Diagnostic &Diags) const; - - /// \brief Retrieve the memory buffer that this result refers to. If an error - /// occurs, provides the file name and a non-empty error string to indicate - /// what failed, and may return NULL. - const llvm::MemoryBuffer *getBuffer(llvm::StringRef &FileName, - std::string &Error) const; - - // FIXME: TEMPORARY! Allows a buffer result to be interpreted as a buffer, - // which is very unsafe (but is used throughout Clang). Note that this will - // spit a diagnostic to standard error before returning the buffer. - operator const llvm::MemoryBuffer *() const; - - // FIXME: TEMPORARY! Allows a buffer result to be interpreted like a smart - // pointer to a buffer, which is very unsafe. Note that this will emit a - // diagnostic to standard error before returning the buffer. - const llvm::MemoryBuffer * operator->() const { return *this; } -}; - /// SrcMgr - Public enums and private classes that are part of the /// SourceManager implementation. /// @@ -115,8 +71,14 @@ namespace SrcMgr { /// if SourceLineCache is non-null. unsigned NumLines; - /// getBuffer - Returns the memory buffer for the associated content. - BufferResult getBuffer() const; + /// getBuffer - Returns the memory buffer for the associated content. + /// + /// \param Diag Object through which diagnostics will be emitted it the + /// buffer cannot be retrieved. + /// + /// \param Invalid If non-NULL, will be set \c true if an error occurred. + const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + bool *Invalid = 0) 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 @@ -455,7 +417,7 @@ public: unsigned Offset = 0); /// \brief Retrieve the memory buffer associated with the given file. - BufferResult getMemoryBufferForFile(const FileEntry *File); + const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File); /// \brief Override the contents of the given source file by providing an /// already-allocated buffer. @@ -476,8 +438,8 @@ public: /// getBuffer - Return the buffer for the specified FileID. If there is an /// error opening this buffer the first time, this manufactures a temporary /// buffer and returns a non-empty error string. - BufferResult getBuffer(FileID FID) const{ - return getSLocEntry(FID).getFile().getContentCache()->getBuffer(); + const llvm::MemoryBuffer *getBuffer(FileID FID) const { + return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Diag); } /// getFileEntryForID - Returns the FileEntry record for the provided FileID. diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 3b4995958b..dd2528a6b3 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3089,7 +3089,7 @@ FileID ASTImporter::Import(FileID FromID) { FromSLoc.getFile().getFileCharacteristic()); } else { // FIXME: We want to re-use the existing MemoryBuffer! - const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(); + const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags()); llvm::MemoryBuffer *ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBufferStart(), FromBuf->getBufferEnd(), diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index ac2fe3d69e..f0a0d4c1bb 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -22,7 +22,6 @@ #include #include #include -#include using namespace clang; using namespace SrcMgr; @@ -32,75 +31,6 @@ using llvm::MemoryBuffer; // SourceManager Helper Classes //===----------------------------------------------------------------------===// -struct BufferResult::FailureData { - const llvm::MemoryBuffer *Buffer; - const char *FileName; - std::string ErrorStr; -}; - -BufferResult::BufferResult(const BufferResult &Other) { - if (const llvm::MemoryBuffer *Buffer - = Other.Data.dyn_cast()) { - Data = Buffer; - return; - } - - Data = new FailureData(*Other.Data.get()); -} - -BufferResult::BufferResult(const char *FileName, llvm::StringRef ErrorStr, - const llvm::MemoryBuffer *Buffer) { - FailureData *FD = new FailureData; - FD->FileName = FileName; - FD->ErrorStr = ErrorStr; - FD->Buffer = Buffer; - Data = FD; -} - -BufferResult::~BufferResult() { - if (FailureData *FD = Data.dyn_cast()) - delete FD; -} - -bool BufferResult::isInvalid() const { - return Data.is(); -} - -const llvm::MemoryBuffer *BufferResult::getBuffer(Diagnostic &Diags) const { - llvm::StringRef FileName; - std::string ErrorMsg; - const llvm::MemoryBuffer *Result = getBuffer(FileName, ErrorMsg); - if (!ErrorMsg.empty()) { - Diags.Report(diag::err_cannot_open_file) - << FileName << ErrorMsg; - } - return Result; -} - -const llvm::MemoryBuffer *BufferResult::getBuffer(llvm::StringRef &FileName, - std::string &Error) const { - if (const llvm::MemoryBuffer *Buffer - = Data.dyn_cast()) - return Buffer; - - FailureData *Fail = Data.get(); - FileName = Fail->FileName; - Error = Fail->ErrorStr; - return Fail->Buffer; -} - -BufferResult::operator const llvm::MemoryBuffer *() const { - llvm::StringRef FileName; - std::string ErrorMsg; - const llvm::MemoryBuffer *Result = getBuffer(FileName, ErrorMsg); - if (!ErrorMsg.empty()) { - fprintf(stderr, "error: cannot open file '%s': %s\n", - FileName.str().c_str(), ErrorMsg.c_str()); - } - - return Result; -} - ContentCache::~ContentCache() { delete Buffer; } @@ -128,7 +58,11 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) { Buffer = B; } -BufferResult ContentCache::getBuffer() const { +const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, + bool *Invalid) const { + if (Invalid) + *Invalid = false; + // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer && Entry) { std::string ErrorStr; @@ -152,17 +86,23 @@ BufferResult ContentCache::getBuffer() const { char *Ptr = const_cast(Buffer->getBufferStart()); for (unsigned i = 0, e = Entry->getSize(); i != e; ++i) Ptr[i] = FillStr[i % FillStr.size()]; - return BufferResult(Entry->getName(), ErrorStr, Buffer); + Diag.Report(diag::err_cannot_open_file) + << Entry->getName() << ErrorStr; + if (Invalid) + *Invalid = true; } else { // Check that the file's size and modification time is the same as // in the file entry (which may have come from a stat cache). - // FIXME: Make these strings localizable. if (FileInfo.st_size != Entry->getSize()) { - ErrorStr = "file has changed size since it was originally read"; - return BufferResult(Entry->getName(), ErrorStr, Buffer); + Diag.Report(diag::err_file_size_changed) + << Entry->getName() << (unsigned)Entry->getSize() + << (unsigned)FileInfo.st_size; + if (Invalid) + *Invalid = true; } else if (FileInfo.st_mtime != Entry->getModificationTime()) { - ErrorStr = "file has been modified since it was originally read"; - return BufferResult(Entry->getName(), ErrorStr, Buffer); + Diag.Report(diag::err_file_modified) << Entry->getName(); + if (Invalid) + *Invalid = true; } } } @@ -516,10 +456,11 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, return SourceLocation::getMacroLoc(NextOffset-(TokLength+1)); } -BufferResult SourceManager::getMemoryBufferForFile(const FileEntry *File) { +const llvm::MemoryBuffer * +SourceManager::getMemoryBufferForFile(const FileEntry *File) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); assert(IR && "getOrCreateContentCache() cannot return NULL"); - return IR->getBuffer(); + return IR->getBuffer(Diag); } bool SourceManager::overrideFileContents(const FileEntry *SourceFile, @@ -537,7 +478,7 @@ SourceManager::getBufferData(FileID FID, bool *Invalid) const { if (Invalid) *Invalid = false; - const llvm::MemoryBuffer *Buf = getBuffer(FID).getBuffer(Diag); + const llvm::MemoryBuffer *Buf = getBuffer(FID); if (!Buf) { if (*Invalid) *Invalid = true; @@ -767,7 +708,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const { // Note that calling 'getBuffer()' may lazily page in a source file. return getSLocEntry(LocInfo.first).getFile().getContentCache() - ->getBuffer()->getBufferStart() + LocInfo.second; + ->getBuffer(Diag)->getBufferStart() + LocInfo.second; } @@ -796,11 +737,13 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const { -static DISABLE_INLINE void ComputeLineNumbers(ContentCache* FI, +static DISABLE_INLINE void ComputeLineNumbers(Diagnostic &Diag, + ContentCache* FI, llvm::BumpPtrAllocator &Alloc); -static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){ +static void ComputeLineNumbers(Diagnostic &Diag, ContentCache* FI, + llvm::BumpPtrAllocator &Alloc){ // Note that calling 'getBuffer()' may lazily page in the file. - const MemoryBuffer *Buffer = FI->getBuffer(); + const MemoryBuffer *Buffer = FI->getBuffer(Diag); // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. @@ -857,7 +800,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const { // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) - ComputeLineNumbers(Content, ContentCacheAlloc); + ComputeLineNumbers(Diag, Content, ContentCacheAlloc); // Okay, we know we have a line number table. Do a binary search to find the // line number that this character position lands on. @@ -1015,7 +958,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // before the MemBuffer as this will avoid unnecessarily paging in the // MemBuffer. const char *Filename = - C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); + C->Entry ? C->Entry->getName() : C->getBuffer(Diag)->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second); unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second); SourceLocation IncludeLoc = FI.getIncludeLoc(); @@ -1072,7 +1015,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) - ComputeLineNumbers(Content, ContentCacheAlloc); + ComputeLineNumbers(Diag, Content, ContentCacheAlloc); // Find the first file ID that corresponds to the given file. FileID FirstFID; @@ -1101,15 +1044,15 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, return SourceLocation(); if (Line > Content->NumLines) { - unsigned Size = Content->getBuffer()->getBufferSize(); + unsigned Size = Content->getBuffer(Diag)->getBufferSize(); if (Size > 0) --Size; return getLocForStartOfFile(FirstFID).getFileLocWithOffset(Size); } unsigned FilePos = Content->SourceLineCache[Line - 1]; - const char *Buf = Content->getBuffer()->getBufferStart() + FilePos; - unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf; + const char *Buf = Content->getBuffer(Diag)->getBufferStart() + FilePos; + unsigned BufLength = Content->getBuffer(Diag)->getBufferEnd() - Buf; unsigned i = 0; // Check that the given column is valid. diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 3d7f5c0e85..02d6cec8fc 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -474,7 +474,7 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) { if (!P.isAbsolute()) continue; - const llvm::MemoryBuffer *B = C.getBuffer(); + const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics()); if (!B) continue; FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index ba406c83af..c256b4103a 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1089,7 +1089,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // We add one to the size so that we capture the trailing NULL // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). - const llvm::MemoryBuffer *Buffer = Content->getBuffer(); + const llvm::MemoryBuffer *Buffer + = Content->getBuffer(PP.getDiagnostics()); const char *Name = Buffer->getBufferIdentifier(); Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, llvm::StringRef(Name, strlen(Name) + 1)); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 4fba7b7bee..81e6bf8090 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -80,8 +80,7 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, } // Get the MemoryBuffer for this FID, if it fails, we fail. - const llvm::MemoryBuffer *InputFile - = getSourceManager().getBuffer(FID).getBuffer(getDiagnostics()); + const llvm::MemoryBuffer *InputFile = getSourceManager().getBuffer(FID); if (!InputFile) return true; -- 2.40.0