diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 115 | ||||
-rw-r--r-- | clang/lib/Frontend/RewriteObjC.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Frontend/TextDiagnosticPrinter.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Lex/PPLexerChange.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Lex/TokenLexer.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Rewrite/HTMLRewrite.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Rewrite/Rewriter.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 5 |
10 files changed, 182 insertions, 33 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c64f97a97f1..6d90884ba94 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -423,10 +423,14 @@ namespace { /// (which requires a < after the Doxygen-comment delimiter). Otherwise, /// we only return true when we find a non-member comment. static bool -isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment, - bool Member = false) { +isDoxygenComment(SourceManager &SourceMgr, Diagnostic &Diags, + SourceRange Comment, bool Member = false) { const char *BufferStart - = SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin())).first; + = SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin()), + Diags).first; + if (!BufferStart) + return false; + const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin()); const char* End = BufferStart + SourceMgr.getFileOffset(Comment.getEnd()); @@ -444,7 +448,7 @@ isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment, /// \brief Retrieve the comment associated with the given declaration, if /// it has one. -const char *ASTContext::getCommentForDecl(const Decl *D) { +const char *ASTContext::getCommentForDecl(const Decl *D, Diagnostic &Diags) { if (!D) return 0; @@ -489,12 +493,14 @@ const char *ASTContext::getCommentForDecl(const Decl *D) { std::pair<FileID, unsigned> DeclStartDecomp = SourceMgr.getDecomposedLoc(DeclStartLoc); const char *FileBufferStart - = SourceMgr.getBufferData(DeclStartDecomp.first).first; - + = SourceMgr.getBufferData(DeclStartDecomp.first, Diags).first; + if (!FileBufferStart) + return 0; + // First check whether we have a comment for a member. if (LastComment != Comments.end() && !isa<TagDecl>(D) && !isa<NamespaceDecl>(D) && - isDoxygenComment(SourceMgr, *LastComment, true)) { + isDoxygenComment(SourceMgr, Diags, *LastComment, true)) { std::pair<FileID, unsigned> LastCommentEndDecomp = SourceMgr.getDecomposedLoc(LastComment->getEnd()); if (DeclStartDecomp.first == LastCommentEndDecomp.first && @@ -526,7 +532,7 @@ const char *ASTContext::getCommentForDecl(const Decl *D) { return 0; // Check that we actually have a Doxygen comment. - if (!isDoxygenComment(SourceMgr, *LastComment)) + if (!isDoxygenComment(SourceMgr, Diags, *LastComment)) return 0; // Compute the starting line for the declaration and for the end of the @@ -561,7 +567,7 @@ const char *ASTContext::getCommentForDecl(const Decl *D) { } // If this comment is not a Doxygen comment, we're done. - if (!isDoxygenComment(SourceMgr, *FirstComment)) { + if (!isDoxygenComment(SourceMgr, Diags, *FirstComment)) { ++FirstComment; break; } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 156b809b51f..dcbd4f166bf 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -13,12 +13,15 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" +#include "clang/Basic/Diagnostic.h" #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 <algorithm> +#include <string> + using namespace clang; using namespace SrcMgr; using llvm::MemoryBuffer; @@ -27,6 +30,75 @@ 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<const llvm::MemoryBuffer *>()) { + Data = Buffer; + return; + } + + Data = new FailureData(*Other.Data.get<FailureData *>()); +} + +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<FailureData *>()) + delete FD; +} + +bool BufferResult::isInvalid() const { + return Data.is<FailureData *>(); +} + +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<const llvm::MemoryBuffer *>()) + return Buffer; + + FailureData *Fail = Data.get<FailureData *>(); + 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; } @@ -54,10 +126,13 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) { Buffer = B; } -const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const { +BufferResult ContentCache::getBuffer() const { // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer && Entry) { - Buffer = MemoryBuffer::getFile(Entry->getName(), ErrorStr,Entry->getSize()); + std::string ErrorStr; + struct stat FileInfo; + Buffer = MemoryBuffer::getFile(Entry->getName(), &ErrorStr, + Entry->getSize(), &FileInfo); // 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 @@ -75,8 +150,21 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const { char *Ptr = const_cast<char*>(Buffer->getBufferStart()); for (unsigned i = 0, e = Entry->getSize(); i != e; ++i) Ptr[i] = FillStr[i % FillStr.size()]; + return BufferResult(Entry->getName(), ErrorStr, Buffer); + } 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); + } else if (FileInfo.st_mtime != Entry->getModificationTime()) { + ErrorStr = "file has been modified since it was originally read"; + return BufferResult(Entry->getName(), ErrorStr, Buffer); + } } } + return Buffer; } @@ -426,12 +514,9 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, return SourceLocation::getMacroLoc(NextOffset-(TokLength+1)); } -const llvm::MemoryBuffer * -SourceManager::getMemoryBufferForFile(const FileEntry *File) { +BufferResult SourceManager::getMemoryBufferForFile(const FileEntry *File) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); - if (IR == 0) - return 0; - + assert(IR && "getOrCreateContentCache() cannot return NULL"); return IR->getBuffer(); } @@ -445,14 +530,22 @@ bool SourceManager::overrideFileContents(const FileEntry *SourceFile, 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*> -SourceManager::getBufferData(FileID FID) const { - const llvm::MemoryBuffer *Buf = getBuffer(FID); +SourceManager::getBufferData(FileID FID, llvm::StringRef &FileName, + std::string &Error) const { + const llvm::MemoryBuffer *Buf = getBuffer(FID).getBuffer(FileName, Error); + if (!Error.empty()) + return std::make_pair((const char *)0, (const char *)0); return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd()); } +std::pair<const char*, const char*> +SourceManager::getBufferData(FileID FID, Diagnostic &Diags) const { + const llvm::MemoryBuffer *Buf = getBuffer(FID).getBuffer(Diags); + if (!Buf) + return std::make_pair((const char *)0, (const char *)0); + return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd()); +} //===----------------------------------------------------------------------===// // SourceLocation manipulation methods. diff --git a/clang/lib/Frontend/RewriteObjC.cpp b/clang/lib/Frontend/RewriteObjC.cpp index 3181a55088b..cd3d4ee0b96 100644 --- a/clang/lib/Frontend/RewriteObjC.cpp +++ b/clang/lib/Frontend/RewriteObjC.cpp @@ -706,7 +706,11 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { void RewriteObjC::RewriteInclude() { SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); + std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID, + Diags); + if (!MainBuf.first) + return; + const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; size_t ImportLen = strlen("import"); @@ -731,7 +735,11 @@ void RewriteObjC::RewriteInclude() { } void RewriteObjC::RewriteTabs() { - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); + std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID, + Diags); + if (!MainBuf.first) + return; + const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; @@ -973,7 +981,10 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { } void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); + std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID, + Diags); + if (!MainBuf.first) + return; SourceLocation LocStart = PDecl->getLocStart(); diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 60c1f4b9b8a..2b243fad248 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -330,9 +330,15 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. - std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID); + llvm::StringRef ErrorFileName; + std::string ErrorStr; + std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID, + ErrorFileName, + ErrorStr); const char *BufStart = BufferInfo.first; - + if (!BufStart) + return; + unsigned ColNo = SM.getColumnNumber(FID, FileOffset); unsigned CaretEndColNo = ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 3207062ccad..149041559ab 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -229,7 +229,14 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc, // the token this macro expanded to. Loc = SM.getInstantiationLoc(Loc); std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); - std::pair<const char *,const char *> Buffer = SM.getBufferData(LocInfo.first); + llvm::StringRef FileName; + std::string ErrorStr; + std::pair<const char *,const char *> Buffer = SM.getBufferData(LocInfo.first, + FileName, + ErrorStr); + if (!Buffer.first) + return 0; + const char *StrData = Buffer.first+LocInfo.second; if (isWhitespace(StrData[0])) diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 0b26ccbecba..4fba7b7bee1 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -80,9 +80,9 @@ 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, &ErrorStr); - if (!ErrorStr.empty()) + const llvm::MemoryBuffer *InputFile + = getSourceManager().getBuffer(FID).getBuffer(getDiagnostics()); + if (!InputFile) return true; EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir); diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index efd1efed293..7ccaa89fe3e 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -439,7 +439,10 @@ bool TokenLexer::PasteTokens(Token &Tok) { SourceManager &SourceMgr = PP.getSourceManager(); FileID LocFileID = SourceMgr.getFileID(ResultTokLoc); - const char *ScratchBufStart = SourceMgr.getBufferData(LocFileID).first; + const char *ScratchBufStart + = SourceMgr.getBufferData(LocFileID, PP.getDiagnostics()).first; + if (!ScratchBufStart) + return false; // Make a lexer to lex this string from. Lex just this one token. // Make a lexer object so that we lex and expand the paste result. diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index 342b0e6ef5e..cf1c779b3ea 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -43,8 +43,18 @@ void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, // Include the whole end token in the range. EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts()); + llvm::StringRef FileName; + std::string ErrorStr; + const char *BufferStart = SM.getBufferData(FID, FileName, ErrorStr).first; + if (!BufferStart) { + // FIXME: Add a diagnostic object somewhere? + fprintf(stderr, "error: cannot open file '%s': %s\n", + FileName.str().c_str(), ErrorStr.c_str()); + return; + } + HighlightRange(R.getEditBuffer(FID), BOffset, EOffset, - SM.getBufferData(FID).first, StartTag, EndTag); + BufferStart, StartTag, EndTag); } /// HighlightRange - This is the same as the above method, but takes diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp index 9744496ac4f..84c0979d6dd 100644 --- a/clang/lib/Rewrite/Rewriter.cpp +++ b/clang/lib/Rewrite/Rewriter.cpp @@ -165,7 +165,17 @@ RewriteBuffer &Rewriter::getEditBuffer(FileID FID) { return I->second; I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer())); - std::pair<const char*, const char*> MB = SourceMgr->getBufferData(FID); + llvm::StringRef FileName; + std::string ErrorStr; + + std::pair<const char*, const char*> MB + = SourceMgr->getBufferData(FID, FileName, ErrorStr); + if (!MB.first) { + // FIXME: Add a diagnostic object somewhere? + fprintf(stderr, "error: cannot open file '%s': %s\n", + FileName.str().c_str(), ErrorStr.c_str()); + } + I->second.Initialize(MB.first, MB.second); return I->second; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 544d66b503e..7e66d7e910d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -60,7 +60,10 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, std::pair<FileID, unsigned> LocInfo = SourceMgr.getDecomposedLoc(StrTokSpellingLoc); std::pair<const char *,const char *> Buffer = - SourceMgr.getBufferData(LocInfo.first); + SourceMgr.getBufferData(LocInfo.first, Diags); + if (!Buffer.first) + return StrTokSpellingLoc; + const char *StrData = Buffer.first+LocInfo.second; // Create a langops struct and enable trigraphs. This is sufficient for |