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.

llvm-svn: 101939
This commit is contained in:
Chris Lattner
2010-04-20 20:35:58 +00:00
parent 877aaa9706
commit fb24a3a4ec
14 changed files with 86 additions and 72 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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());

View File

@@ -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<SourceManager &>(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.

View File

@@ -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.

View File

@@ -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<Action> 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<Action> PA(CreatePrintParserActionsAction(PP, OS));
Parser P(PP, *PA);
if (PP.EnterMainSourceFile())
return;
PP.EnterMainSourceFile();
P.ParseTranslationUnit();
}

View File

@@ -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));

View File

@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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.
// 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}}