diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticCommonKinds.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/SourceManager.h | 76 | ||||
-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 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndex.cpp | 23 |
14 files changed, 271 insertions, 49 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 71ddc8794bb..ffd0dec6b9a 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -40,6 +40,7 @@ namespace clang { class ASTRecordLayout; class BlockExpr; class CharUnits; + class Diagnostic; class Expr; class ExternalASTSource; class IdentifierTable; @@ -356,7 +357,7 @@ public: TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } - const char *getCommentForDecl(const Decl *D); + const char *getCommentForDecl(const Decl *D, Diagnostic &Diags); // Builtin Types. CanQualType VoidTy; diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 66f84dbbbab..d79f7ad42fa 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -63,4 +63,7 @@ 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 +def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; + } diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 015d82a63cc..05480419abf 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -17,21 +17,68 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/Support/Allocator.h" #include "llvm/System/DataTypes.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseMap.h" #include <vector> #include <cassert> namespace llvm { class MemoryBuffer; +class StringRef; } namespace clang { +class Diagnostic; class SourceManager; 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<const llvm::MemoryBuffer *, FailureData *> 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. /// @@ -68,10 +115,8 @@ namespace SrcMgr { /// if SourceLineCache is non-null. unsigned NumLines; - /// getBuffer - Returns the memory buffer for the associated content. If - /// there is an error opening this buffer the first time, this manufactures - /// a temporary buffer and returns a non-empty error string. - const llvm::MemoryBuffer *getBuffer(std::string *ErrorStr = 0) const; + /// getBuffer - Returns the memory buffer for the associated content. + BufferResult getBuffer() 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 @@ -407,7 +452,7 @@ public: unsigned Offset = 0); /// \brief Retrieve the memory buffer associated with the given file. - const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File); + BufferResult getMemoryBufferForFile(const FileEntry *File); /// \brief Override the contents of the given source file by providing an /// already-allocated buffer. @@ -428,8 +473,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. - const llvm::MemoryBuffer *getBuffer(FileID FID, std::string *Error = 0) const{ - return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Error); + BufferResult getBuffer(FileID FID) const{ + return getSLocEntry(FID).getFile().getContentCache()->getBuffer(); } /// getFileEntryForID - Returns the FileEntry record for the provided FileID. @@ -439,8 +484,21 @@ public: /// getBufferData - Return a pointer to the start and end of the source buffer /// data for the specified FileID. - std::pair<const char*, const char*> getBufferData(FileID FID) const; + /// + /// If an error occurs while reading in the file, provides the file name + /// and a non-empty error string and returns a pair of NULL pointers. + std::pair<const char*, const char*> getBufferData(FileID FID, + llvm::StringRef &FileName, + std::string &Error) const; + /// getBufferData - Return a pointer to the start and end of the source buffer + /// data for the specified FileID. + /// + /// If an error occurs while reading in the file, emits a diagnostic to the + /// given \c Diagnostic object and returns a pair of NULL pointers. + std::pair<const char*, const char*> getBufferData(FileID FID, + Diagnostic &Diags) const; + //===--------------------------------------------------------------------===// // SourceLocation manipulation methods. 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 diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index b52a32ed9b5..c570ee4935d 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -2043,7 +2043,10 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { std::pair<FileID, unsigned> LocInfo = CXXUnit->getSourceManager().getDecomposedLoc(Loc); std::pair<const char *,const char *> Buffer - = CXXUnit->getSourceManager().getBufferData(LocInfo.first); + = CXXUnit->getSourceManager().getBufferData(LocInfo.first, + CXXUnit->getPreprocessor().getDiagnostics()); + if (!Buffer.first) + return createCXString(""); return createCXString(llvm::StringRef(Buffer.first+LocInfo.second, CXTok.int_data[2])); @@ -2096,7 +2099,11 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Create a lexer std::pair<const char *,const char *> Buffer - = SourceMgr.getBufferData(BeginLocInfo.first); + = SourceMgr.getBufferData(BeginLocInfo.first, + CXXUnit->getPreprocessor().getDiagnostics()); + if (!Buffer.first) + return; + Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), CXXUnit->getASTContext().getLangOptions(), Buffer.first, Buffer.first + BeginLocInfo.second, Buffer.second); @@ -2125,12 +2132,16 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXTok.int_data[0] = CXToken_Literal; CXTok.ptr_data = (void *)Tok.getLiteralData(); } else if (Tok.is(tok::identifier)) { - // Lookup the identifier to determine whether we have a + // Lookup the identifier to determine whether we have a keyword. std::pair<FileID, unsigned> LocInfo = SourceMgr.getDecomposedLoc(Tok.getLocation()); - const char *StartPos - = CXXUnit->getSourceManager().getBufferData(LocInfo.first).first + - LocInfo.second; + std::pair<const char *, const char *> Buf + = CXXUnit->getSourceManager().getBufferData(LocInfo.first, + CXXUnit->getPreprocessor().getDiagnostics()); + if (!Buf.first) + return; + + const char *StartPos= Buf.first + LocInfo.second; IdentifierInfo *II = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok, StartPos); CXTok.int_data[0] = II->getTokenID() == tok::identifier? |