summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-03-15 22:54:52 +0000
committerDouglas Gregor <dgregor@apple.com>2010-03-15 22:54:52 +0000
commit802b77601e50161f0b0d2451a722e11f3b49cdfb (patch)
treefa9b72b5282af43966aff1b27012e481accbf26b /clang
parent45c1505bf60a17a02846a823fac6d8544a27501c (diff)
downloadbcm5719-llvm-802b77601e50161f0b0d2451a722e11f3b49cdfb.tar.gz
bcm5719-llvm-802b77601e50161f0b0d2451a722e11f3b49cdfb.zip
Introduce a new BufferResult class to act as the return type of
SourceManager's getBuffer() (and similar) operations. This abstract can be used to force callers to cope with errors in getBuffer(), such as missing files and changed files. Fix a bunch of callers to use the new interface. Add some very basic checks for file consistency (file size, modification time) into ContentCache::getBuffer(), although these checks don't help much until we've updated the main callers (e.g., SourceManager::getSpelling()). llvm-svn: 98585
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h3
-rw-r--r--clang/include/clang/Basic/DiagnosticCommonKinds.td3
-rw-r--r--clang/include/clang/Basic/SourceManager.h76
-rw-r--r--clang/lib/AST/ASTContext.cpp24
-rw-r--r--clang/lib/Basic/SourceManager.cpp115
-rw-r--r--clang/lib/Frontend/RewriteObjC.cpp17
-rw-r--r--clang/lib/Frontend/TextDiagnosticPrinter.cpp10
-rw-r--r--clang/lib/Lex/Lexer.cpp9
-rw-r--r--clang/lib/Lex/PPLexerChange.cpp6
-rw-r--r--clang/lib/Lex/TokenLexer.cpp5
-rw-r--r--clang/lib/Rewrite/HTMLRewrite.cpp12
-rw-r--r--clang/lib/Rewrite/Rewriter.cpp12
-rw-r--r--clang/lib/Sema/SemaChecking.cpp5
-rw-r--r--clang/tools/CIndex/CIndex.cpp23
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?
OpenPOWER on IntegriCloud