From: Chris Lattner Date: Tue, 20 Apr 2010 20:35:58 +0000 (+0000) Subject: push some source location information down through the compiler, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e127a0d80155b45dafe77f2b4380e5fa111a3345;p=clang push some source location information down through the compiler, into ContentCache::getBuffer. This allows it to produce diagnostics on the broken #include line instead of without a location. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101939 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index d1239694fc..930fb52873 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -78,8 +78,13 @@ namespace SrcMgr { /// \param Diag Object through which diagnostics will be emitted it the /// buffer cannot be retrieved. /// + /// \param Loc If specified, is the location that invalid file diagnostics + /// will be emitted at. + /// /// \param Invalid If non-NULL, will be set \c true if an error occurred. - const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + const SourceManager &SM, + SourceLocation Loc = SourceLocation(), bool *Invalid = 0) const; /// getSize - Returns the size of the content encapsulated by this @@ -447,11 +452,17 @@ 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, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Diag, - Invalid); + const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, + bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, Loc, Invalid); } + const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, SourceLocation(), Invalid); + } + /// getFileEntryForID - Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { return getSLocEntry(FID).getFile().getContentCache()->Entry; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 312a760e01..20d9fc50e4 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -366,17 +366,17 @@ public: /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. - bool EnterMainSourceFile(); + void EnterMainSourceFile(); /// EndSourceFile - Inform the preprocessor callbacks that processing is /// complete. void EndSourceFile(); /// EnterSourceFile - Add a source file to the top of the include stack and - /// start lexing tokens from it instead of the current buffer. Return true - /// and fill in ErrorStr with the error information on failure. - bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, - std::string &ErrorStr); + /// start lexing tokens from it instead of the current buffer. Emit an error + /// and don't enter the file on error. + void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, + SourceLocation Loc); /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. Args specifies the diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 5651121402..d3268030c9 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3090,7 +3090,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(getDiags()); + const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags(), FromSM); llvm::MemoryBuffer *ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index c76624139a..355b87a9dd 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -60,12 +60,17 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) { } const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, + const SourceManager &sm, + SourceLocation Loc, bool *Invalid) const { if (Invalid) *Invalid = false; // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer.getPointer() && Entry) { + // FIXME: + SourceManager &SM = const_cast(sm); + std::string ErrorStr; struct stat FileInfo; Buffer.setPointer(MemoryBuffer::getFile(Entry->getName(), &ErrorStr, @@ -94,7 +99,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, Entry->getName(), ErrorStr); else - Diag.Report(diag::err_cannot_open_file) + Diag.Report(FullSourceLoc(Loc, SM), diag::err_cannot_open_file) << Entry->getName() << ErrorStr; Buffer.setInt(true); @@ -114,7 +119,8 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, Diag.SetDelayedDiagnostic(diag::err_file_modified, Entry->getName()); else - Diag.Report(diag::err_file_modified) << Entry->getName(); + Diag.Report(FullSourceLoc(Loc, SM), diag::err_file_modified) + << Entry->getName(); Buffer.setInt(true); #endif @@ -150,7 +156,8 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, BOM = "BOCU-1"; if (BOM) { - Diag.Report(diag::err_unsupported_bom) << BOM << Entry->getName(); + Diag.Report(FullSourceLoc(Loc, SM), diag::err_unsupported_bom) + << BOM << Entry->getName(); Buffer.setInt(1); } } @@ -513,7 +520,7 @@ SourceManager::getMemoryBufferForFile(const FileEntry *File, bool *Invalid) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); assert(IR && "getOrCreateContentCache() cannot return NULL"); - return IR->getBuffer(Diag, Invalid); + return IR->getBuffer(Diag, *this, SourceLocation(), Invalid); } bool SourceManager::overrideFileContents(const FileEntry *SourceFile, @@ -760,8 +767,8 @@ const char *SourceManager::getCharacterData(SourceLocation SL, // Note that calling 'getBuffer()' may lazily page in a source file. bool CharDataInvalid = false; const llvm::MemoryBuffer *Buffer - = getSLocEntry(LocInfo.first).getFile().getContentCache()->getBuffer(Diag, - &CharDataInvalid); + = getSLocEntry(LocInfo.first).getFile().getContentCache() + ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); @@ -800,14 +807,16 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc, return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); } -static DISABLE_INLINE void ComputeLineNumbers(Diagnostic &Diag, - ContentCache* FI, - llvm::BumpPtrAllocator &Alloc, - bool &Invalid); -static void ComputeLineNumbers(Diagnostic &Diag, ContentCache* FI, - llvm::BumpPtrAllocator &Alloc, bool &Invalid) { +static DISABLE_INLINE void +ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, + llvm::BumpPtrAllocator &Alloc, + const SourceManager &SM, bool &Invalid); +static void ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, + llvm::BumpPtrAllocator &Alloc, + const SourceManager &SM, bool &Invalid) { // Note that calling 'getBuffer()' may lazily page in the file. - const MemoryBuffer *Buffer = FI->getBuffer(Diag, &Invalid); + const MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(), + &Invalid); if (Invalid) return; @@ -868,7 +877,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) { bool MyInvalid = false; - ComputeLineNumbers(Diag, Content, ContentCacheAlloc, MyInvalid); + ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); if (Invalid) *Invalid = MyInvalid; if (MyInvalid) @@ -1034,8 +1043,11 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // To get the source name, first consult the FileEntry (if one exists) // before the MemBuffer as this will avoid unnecessarily paging in the // MemBuffer. - const char *Filename = - C->Entry ? C->Entry->getName() : C->getBuffer(Diag)->getBufferIdentifier(); + const char *Filename; + if (C->Entry) + Filename = C->Entry->getName(); + else + Filename = C->getBuffer(Diag, *this)->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second); unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second); SourceLocation IncludeLoc = FI.getIncludeLoc(); @@ -1093,7 +1105,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) { bool MyInvalid = false; - ComputeLineNumbers(Diag, Content, ContentCacheAlloc, MyInvalid); + ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); if (MyInvalid) return SourceLocation(); } @@ -1125,15 +1137,15 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, return SourceLocation(); if (Line > Content->NumLines) { - unsigned Size = Content->getBuffer(Diag)->getBufferSize(); + unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize(); if (Size > 0) --Size; return getLocForStartOfFile(FirstFID).getFileLocWithOffset(Size); } unsigned FilePos = Content->SourceLineCache[Line - 1]; - const char *Buf = Content->getBuffer(Diag)->getBufferStart() + FilePos; - unsigned BufLength = Content->getBuffer(Diag)->getBufferEnd() - Buf; + const char *Buf = Content->getBuffer(Diag, *this)->getBufferStart() + FilePos; + unsigned BufLength = Content->getBuffer(Diag, *this)->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 d069e8f42f..a5fcebe994 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -475,7 +475,7 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) { if (!P.isAbsolute()) continue; - const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics()); + const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM); if (!B) continue; FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); @@ -550,8 +550,7 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { // Lex through the entire file. This will populate SourceManager with // all of the header information. Token Tok; - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); // Generate the PTH file. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index ce3e841b90..e2b2fd7deb 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -236,8 +236,7 @@ void DumpTokensAction::ExecuteAction() { Preprocessor &PP = getCompilerInstance().getPreprocessor(); // Start preprocessing the specified input file. Token Tok; - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); PP.DumpToken(Tok, true); @@ -265,8 +264,7 @@ void ParseOnlyAction::ExecuteAction() { llvm::OwningPtr PA(new MinimalAction(PP)); Parser P(PP, *PA); - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); P.ParseTranslationUnit(); } @@ -275,8 +273,7 @@ void PreprocessOnlyAction::ExecuteAction() { Token Tok; // Start parsing the specified input file. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); @@ -291,8 +288,7 @@ void PrintParseAction::ExecuteAction() { llvm::OwningPtr PA(CreatePrintParserActionsAction(PP, OS)); Parser P(PP, *PA); - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); P.ParseTranslationUnit(); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index a6faf9ba99..ee20122de7 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1,4 +1,4 @@ -//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===// +//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===// // // The LLVM Compiler Infrastructure // @@ -1104,7 +1104,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). const llvm::MemoryBuffer *Buffer - = Content->getBuffer(PP.getDiagnostics()); + = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); const char *Name = Buffer->getBufferIdentifier(); Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, llvm::StringRef(Name, strlen(Name) + 1)); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 17edd12a67..b6c18b7731 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -456,8 +456,7 @@ static int MacroIDCompare(const void* a, const void* b) { static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) { // -dM mode just scans and ignores all tokens in the files, then dumps out // the macro table at the end. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); Token Tok; do PP.Lex(Tok); @@ -502,8 +501,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, PP.addPPCallbacks(Callbacks); // After we have configured the preprocessor, enter the main file. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); // Consume all of the tokens that come from the predefines buffer. Those // should not be emitted into the output and are guaranteed to be at the diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index 4ffb2978db..954e8e23ca 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -101,8 +101,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { // Get the first preprocessing token. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); Token PPTok; PP.Lex(PPTok); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index eb8664585f..417724b777 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1098,9 +1098,8 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, // Ask HeaderInfo if we should enter this #include file. If not, #including // this file will have no effect. if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) { - if (Callbacks) { + if (Callbacks) Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); - } return; } @@ -1113,10 +1112,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, } // Finally, if all is good, enter the new file! - std::string ErrorStr; - if (EnterSourceFile(FID, CurDir, ErrorStr)) - Diag(FilenameTok, diag::err_pp_error_opening_file) - << std::string(SourceMgr.getFileEntryForID(FID)->getName()) << ErrorStr; + EnterSourceFile(FID, CurDir, FilenameTok.getLocation()); } /// HandleIncludeNextDirective - Implements #include_next. diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 335d3db627..4a40405992 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -64,8 +64,8 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const { /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. -bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, - std::string &ErrorStr) { +void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, + SourceLocation Loc) { assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!"); ++NumEnteredSourceFiles; @@ -75,19 +75,23 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, if (PTH) { if (PTHLexer *PL = PTH->CreateLexer(FID)) { EnterSourceFileWithPTH(PL, CurDir); - return false; + return; } } // Get the MemoryBuffer for this FID, if it fails, we fail. bool Invalid = false; - const llvm::MemoryBuffer *InputFile = getSourceManager().getBuffer(FID, - &Invalid); - if (Invalid) - return true; + const llvm::MemoryBuffer *InputFile = + getSourceManager().getBuffer(FID, Loc, &Invalid); + if (Invalid) { + SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID); + Diag(Loc, diag::err_pp_error_opening_file) + << std::string(SourceMgr.getBufferName(FileStart)) << ""; + return; + } EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir); - return false; + return; } /// EnterSourceFileWithLexer - Add a source file to the top of the include stack diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 4598383c1c..ce6d9ab5c0 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -490,7 +490,7 @@ SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc, /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. -bool Preprocessor::EnterMainSourceFile() { +void Preprocessor::EnterMainSourceFile() { // We do not allow the preprocessor to reenter the main file. Doing so will // cause FileID's to accumulate information from both runs (e.g. #line // information) and predefined macros aren't guaranteed to be set properly. @@ -498,9 +498,7 @@ bool Preprocessor::EnterMainSourceFile() { FileID MainFileID = SourceMgr.getMainFileID(); // Enter the main file source buffer. - std::string ErrorStr; - if (EnterSourceFile(MainFileID, 0, ErrorStr)) - return true; + EnterSourceFile(MainFileID, 0, SourceLocation()); // Tell the header info that the main file was entered. If the file is later // #imported, it won't be re-entered. @@ -515,7 +513,7 @@ bool Preprocessor::EnterMainSourceFile() { assert(!FID.isInvalid() && "Could not create FileID for predefines?"); // Start parsing the predefines. - return EnterSourceFile(FID, 0, ErrorStr); + EnterSourceFile(FID, 0, SourceLocation()); } void Preprocessor::EndSourceFile() { diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index f620927a8d..bb0bd9e1cb 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -64,8 +64,7 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer); Parser P(PP, S); - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); // Initialize the parser. P.Initialize(); diff --git a/test/Lexer/utf-16.c b/test/Lexer/utf-16.c index 7c14e3932b..2b313e49fd 100644 --- a/test/Lexer/utf-16.c +++ b/test/Lexer/utf-16.c @@ -1,4 +1,6 @@ -// RUN: not %clang -xc %s.txt -fsyntax-only 2>&1 | grep 'UTF-16 (LE) byte order mark detected' +// RUN: not %clang %s -fsyntax-only -verify // rdar://7876588 -// This test verifies that clang gives a decent error for UTF-16 source files. \ No newline at end of file +// This test verifies that clang gives a decent error for UTF-16 source files. + +#include "utf-16.c.txt" // expected-error {{UTF-16 (LE) byte order mark detected}}