diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ffd0dec6b9a5..d12a182078e4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -357,7 +357,7 @@ public: TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } - const char *getCommentForDecl(const Decl *D, Diagnostic &Diags); + const char *getCommentForDecl(const Decl *D); // Builtin Types. CanQualType VoidTy; diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 05480419abfe..4d423058fb9f 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -321,6 +321,9 @@ public: /// location indicates where the expanded token came from and the instantiation /// location specifies where it was expanded. class SourceManager { + /// \brief Diagnostic object. + Diagnostic &Diag; + mutable llvm::BumpPtrAllocator ContentCacheAlloc; /// FileInfos - Memoized information about all of the files tracked by this @@ -380,8 +383,8 @@ class SourceManager { explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: - SourceManager() - : ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), + SourceManager(Diagnostic &Diag) + : Diag(Diag), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), NumBinaryProbes(0) { clearIDTables(); } @@ -482,22 +485,13 @@ public: return getSLocEntry(FID).getFile().getContentCache()->Entry; } - /// 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, provides the file name - /// and a non-empty error string and returns a pair of NULL pointers. - std::pair 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 getBufferData(FileID FID, - Diagnostic &Diags) const; + /// \param FID The file ID whose contents will be returned. + /// \param Invalid If non-NULL, will be set true if an error occurred. + std::pair getBufferData(FileID FID, + bool *Invalid = 0) const; //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 7f11c85ae35b..27ec12e4e4cd 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -121,7 +121,7 @@ public: }; friend class ConcurrencyCheck; - ASTUnit(bool MainFileIsAST); + ASTUnit(Diagnostic &Diag, bool MainFileIsAST); ~ASTUnit(); bool isMainFileAST() const { return MainFileIsAST; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 6d90884ba941..07243365bf4a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -423,12 +423,13 @@ 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, Diagnostic &Diags, - SourceRange Comment, bool Member = false) { +isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment, + bool Member = false) { + bool Invalid = false; const char *BufferStart = SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin()), - Diags).first; - if (!BufferStart) + &Invalid).first; + if (Invalid) return false; const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin()); @@ -448,7 +449,7 @@ isDoxygenComment(SourceManager &SourceMgr, Diagnostic &Diags, /// \brief Retrieve the comment associated with the given declaration, if /// it has one. -const char *ASTContext::getCommentForDecl(const Decl *D, Diagnostic &Diags) { +const char *ASTContext::getCommentForDecl(const Decl *D) { if (!D) return 0; @@ -492,15 +493,16 @@ const char *ASTContext::getCommentForDecl(const Decl *D, Diagnostic &Diags) { // beginning of the file buffer. std::pair DeclStartDecomp = SourceMgr.getDecomposedLoc(DeclStartLoc); + bool Invalid = false; const char *FileBufferStart - = SourceMgr.getBufferData(DeclStartDecomp.first, Diags).first; - if (!FileBufferStart) + = SourceMgr.getBufferData(DeclStartDecomp.first, &Invalid).first; + if (Invalid) return 0; // First check whether we have a comment for a member. if (LastComment != Comments.end() && !isa(D) && !isa(D) && - isDoxygenComment(SourceMgr, Diags, *LastComment, true)) { + isDoxygenComment(SourceMgr, *LastComment, true)) { std::pair LastCommentEndDecomp = SourceMgr.getDecomposedLoc(LastComment->getEnd()); if (DeclStartDecomp.first == LastCommentEndDecomp.first && @@ -532,7 +534,7 @@ const char *ASTContext::getCommentForDecl(const Decl *D, Diagnostic &Diags) { return 0; // Check that we actually have a Doxygen comment. - if (!isDoxygenComment(SourceMgr, Diags, *LastComment)) + if (!isDoxygenComment(SourceMgr, *LastComment)) return 0; // Compute the starting line for the declaration and for the end of the @@ -567,7 +569,7 @@ const char *ASTContext::getCommentForDecl(const Decl *D, Diagnostic &Diags) { } // If this comment is not a Doxygen comment, we're done. - if (!isDoxygenComment(SourceMgr, Diags, *FirstComment)) { + if (!isDoxygenComment(SourceMgr, *FirstComment)) { ++FirstComment; break; } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index b69ba53f7b2a..ac2fe3d69e38 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -21,6 +21,7 @@ #include "llvm/System/Path.h" #include #include +#include #include using namespace clang; @@ -532,19 +533,17 @@ bool SourceManager::overrideFileContents(const FileEntry *SourceFile, } std::pair -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 -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); +SourceManager::getBufferData(FileID FID, bool *Invalid) const { + if (Invalid) + *Invalid = false; + + const llvm::MemoryBuffer *Buf = getBuffer(FID).getBuffer(Diag); + if (!Buf) { + if (*Invalid) + *Invalid = true; + const char *FakeText = ""; + return std::make_pair(FakeText, FakeText + strlen(FakeText)); + } return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd()); } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 63cf98d3da5d..3bf1fab1c27d 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -35,8 +35,9 @@ #include "llvm/System/Path.h" using namespace clang; -ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { +ASTUnit::ASTUnit(Diagnostic &Diag, bool _MainFileIsAST) + : SourceMgr(Diag), MainFileIsAST(_MainFileIsAST), + ConcurrencyCheckValue(CheckUnlocked) { } ASTUnit::~ASTUnit() { ConcurrencyCheckValue = CheckLocked; @@ -146,7 +147,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool CaptureDiagnostics) { - llvm::OwningPtr AST(new ASTUnit(true)); + llvm::OwningPtr AST(new ASTUnit(Diags, true)); AST->OnlyLocalDecls = OnlyLocalDecls; AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); @@ -311,7 +312,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, "FIXME: AST inputs not yet supported here!"); // Create the AST unit. - AST.reset(new ASTUnit(false)); + AST.reset(new ASTUnit(Diags, false)); AST->OnlyLocalDecls = OnlyLocalDecls; AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 25b804aba7fc..c43118ce56b0 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -185,7 +185,7 @@ void CompilerInstance::createFileManager() { // Source Manager void CompilerInstance::createSourceManager() { - SourceMgr.reset(new SourceManager()); + SourceMgr.reset(new SourceManager(getDiagnostics())); } // Preprocessor diff --git a/clang/lib/Frontend/RewriteObjC.cpp b/clang/lib/Frontend/RewriteObjC.cpp index cd3d4ee0b96c..888900385101 100644 --- a/clang/lib/Frontend/RewriteObjC.cpp +++ b/clang/lib/Frontend/RewriteObjC.cpp @@ -706,11 +706,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { void RewriteObjC::RewriteInclude() { SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); - std::pair MainBuf = SM->getBufferData(MainFileID, - Diags); - if (!MainBuf.first) - return; - + std::pair MainBuf = SM->getBufferData(MainFileID); const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; size_t ImportLen = strlen("import"); @@ -735,11 +731,7 @@ void RewriteObjC::RewriteInclude() { } void RewriteObjC::RewriteTabs() { - std::pair MainBuf = SM->getBufferData(MainFileID, - Diags); - if (!MainBuf.first) - return; - + std::pair MainBuf = SM->getBufferData(MainFileID); const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; @@ -981,11 +973,7 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { } void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { - std::pair MainBuf = SM->getBufferData(MainFileID, - Diags); - if (!MainBuf.first) - return; - + std::pair MainBuf = SM->getBufferData(MainFileID); SourceLocation LocStart = PDecl->getLocStart(); // FIXME: handle protocol headers that are declared across multiple lines. diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 2b243fad2482..946a6caa1514 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -330,15 +330,14 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. - llvm::StringRef ErrorFileName; - std::string ErrorStr; + bool Invalid = false; std::pair BufferInfo = SM.getBufferData(FID, - ErrorFileName, - ErrorStr); - const char *BufStart = BufferInfo.first; - if (!BufStart) + &Invalid); + if (Invalid) return; + const char *BufStart = BufferInfo.first; + 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 149041559abf..d311b7e5ddc5 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -229,12 +229,10 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc, // the token this macro expanded to. Loc = SM.getInstantiationLoc(Loc); std::pair LocInfo = SM.getDecomposedLoc(Loc); - llvm::StringRef FileName; - std::string ErrorStr; + bool Invalid = false; std::pair Buffer = SM.getBufferData(LocInfo.first, - FileName, - ErrorStr); - if (!Buffer.first) + &Invalid); + if (Invalid) return 0; const char *StrData = Buffer.first+LocInfo.second; diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 7ccaa89fe3e8..8f6876554302 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -439,9 +439,10 @@ bool TokenLexer::PasteTokens(Token &Tok) { SourceManager &SourceMgr = PP.getSourceManager(); FileID LocFileID = SourceMgr.getFileID(ResultTokLoc); + bool Invalid = false; const char *ScratchBufStart - = SourceMgr.getBufferData(LocFileID, PP.getDiagnostics()).first; - if (!ScratchBufStart) + = SourceMgr.getBufferData(LocFileID, &Invalid).first; + if (Invalid) return false; // Make a lexer to lex this string from. Lex just this one token. diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index 6fe3fc07db2c..f325121d08d0 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -22,7 +22,6 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include using namespace clang; @@ -44,15 +43,10 @@ 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()); + bool Invalid = false; + const char *BufferStart = SM.getBufferData(FID, &Invalid).first; + if (Invalid) return; - } HighlightRange(R.getEditBuffer(FID), BOffset, EOffset, BufferStart, StartTag, EndTag); diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp index 50f9fa14f16a..9744496ac4fe 100644 --- a/clang/lib/Rewrite/Rewriter.cpp +++ b/clang/lib/Rewrite/Rewriter.cpp @@ -18,7 +18,6 @@ #include "clang/Lex/Lexer.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" -#include using namespace clang; void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) { @@ -166,17 +165,7 @@ RewriteBuffer &Rewriter::getEditBuffer(FileID FID) { return I->second; I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer())); - llvm::StringRef FileName; - std::string ErrorStr; - - std::pair 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()); - } - + std::pair MB = SourceMgr->getBufferData(FID); 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 7e66d7e910d5..5ec01d001165 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -59,9 +59,10 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, // Re-lex the token to get its length and original spelling. std::pair LocInfo = SourceMgr.getDecomposedLoc(StrTokSpellingLoc); + bool Invalid = false; std::pair Buffer = - SourceMgr.getBufferData(LocInfo.first, Diags); - if (!Buffer.first) + SourceMgr.getBufferData(LocInfo.first, &Invalid); + if (Invalid) return StrTokSpellingLoc; const char *StrData = Buffer.first+LocInfo.second; diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index c570ee4935d9..c100caeecb17 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -1133,7 +1133,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, // We failed to load the ASTUnit, but we can still deserialize the // diagnostics and emit them. FileManager FileMgr; - SourceManager SourceMgr; + Diagnostic Diag; + SourceManager SourceMgr(Diag); // FIXME: Faked LangOpts! LangOptions LangOpts; llvm::SmallVector Diags; @@ -2042,10 +2043,10 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]); std::pair LocInfo = CXXUnit->getSourceManager().getDecomposedLoc(Loc); + bool Invalid = false; std::pair Buffer - = CXXUnit->getSourceManager().getBufferData(LocInfo.first, - CXXUnit->getPreprocessor().getDiagnostics()); - if (!Buffer.first) + = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); + if (Invalid) return createCXString(""); return createCXString(llvm::StringRef(Buffer.first+LocInfo.second, @@ -2098,11 +2099,9 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, return; // Create a lexer + bool Invalid = false; std::pair Buffer - = SourceMgr.getBufferData(BeginLocInfo.first, - CXXUnit->getPreprocessor().getDiagnostics()); - if (!Buffer.first) - return; + = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), CXXUnit->getASTContext().getLangOptions(), @@ -2135,10 +2134,10 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Lookup the identifier to determine whether we have a keyword. std::pair LocInfo = SourceMgr.getDecomposedLoc(Tok.getLocation()); + bool Invalid = false; std::pair Buf - = CXXUnit->getSourceManager().getBufferData(LocInfo.first, - CXXUnit->getPreprocessor().getDiagnostics()); - if (!Buf.first) + = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); + if (Invalid) return; const char *StartPos= Buf.first + LocInfo.second; diff --git a/clang/tools/CIndex/CIndexCodeCompletion.cpp b/clang/tools/CIndex/CIndexCodeCompletion.cpp index 3b7674ec0d1d..264e5064ddb4 100644 --- a/clang/tools/CIndex/CIndexCodeCompletion.cpp +++ b/clang/tools/CIndex/CIndexCodeCompletion.cpp @@ -187,6 +187,9 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// \brief Diagnostics produced while performing code completion. llvm::SmallVector Diagnostics; + /// \brief Diag object + Diagnostic Diag; + /// \brief Language options used to adjust source locations. LangOptions LangOpts; @@ -202,7 +205,7 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { }; AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults() - : CXCodeCompleteResults(), Buffer(0) { } + : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { } AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { for (unsigned I = 0, N = NumResults; I != N; ++I)