Track which headers are system and non-C++-clean-system headers. Use this

information to print the 3/4 flags correctly on #line directives emitted
in -E mode.

llvm-svn: 38562
This commit is contained in:
Chris Lattner 2006-06-22 05:52:16 +00:00
parent 0c885f5581
commit c899718274
3 changed files with 93 additions and 49 deletions

View File

@ -592,6 +592,7 @@ static unsigned EModeCurLine;
static std::string EModeCurFilename;
static Preprocessor *EModePP;
static bool EmodeEmittedTokensOnThisLine;
static DirectoryLookup::DirType EmodeFileType =DirectoryLookup::NormalHeaderDir;
static void MoveToLine(unsigned LineNo) {
// If this line is "close enough" to the original line, just print newlines,
@ -607,9 +608,11 @@ static void MoveToLine(unsigned LineNo) {
std::cout << "# " << LineNo << " " << EModeCurFilename;
// FIXME: calculate system file right.
std::cout << " 3";
if (EmodeFileType == DirectoryLookup::SystemHeaderDir)
std::cout << " 3";
else if (EmodeFileType == DirectoryLookup::ExternCSystemHeaderDir)
std::cout << " 3 4";
std::cout << "\n";
EModeCurLine = LineNo;
}
@ -617,7 +620,8 @@ static void MoveToLine(unsigned LineNo) {
/// HandleFileChange - Whenever the preprocessor enters or exits a #include file
/// it invokes this handler. Update our conception of the current
static void HandleFileChange(SourceLocation Loc, bool EnteringFile) {
static void HandleFileChange(SourceLocation Loc, bool EnteringFile,
DirectoryLookup::DirType FileType) {
SourceManager &SourceMgr = EModePP->getSourceManager();
// If we are entering a new #include, make sure to skip ahead to the line the
@ -630,6 +634,7 @@ static void HandleFileChange(SourceLocation Loc, bool EnteringFile) {
EModeCurLine = SourceMgr.getLineNumber(Loc);
// FIXME: escape filename right.
EModeCurFilename = '"' + SourceMgr.getSourceName(Loc) + '"';
EmodeFileType = FileType;
if (EmodeEmittedTokensOnThisLine) {
std::cout << "\n";
@ -641,8 +646,10 @@ static void HandleFileChange(SourceLocation Loc, bool EnteringFile) {
else
std::cout << " 2";
// FIXME: calculate system file right.
std::cout << " 3";
if (FileType == DirectoryLookup::SystemHeaderDir)
std::cout << " 3";
else if (FileType == DirectoryLookup::ExternCSystemHeaderDir)
std::cout << " 3 4";
std::cout << "\n";
}

View File

@ -48,7 +48,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
FileManager &FM, SourceManager &SM)
: Diags(diags), Features(opts), FileMgr(FM), SourceMgr(SM),
SystemDirIdx(0), NoCurDirSearch(false),
CurLexer(0), CurNextDirLookup(0), CurMacroExpander(0) {
CurLexer(0), CurDirLookup(0), CurMacroExpander(0) {
// Clear stats.
NumDirectives = NumIncluded = NumDefined = NumUndefined = NumPragma = 0;
NumIf = NumElse = NumEndif = 0;
@ -267,11 +267,11 @@ unsigned Preprocessor::getSpelling(const LexerToken &Tok, char *Buffer) const {
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *Preprocessor::LookupFile(const std::string &Filename,
bool isSystem,
bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&NextDir) {
const DirectoryLookup *&CurDir) {
assert(CurLexer && "Cannot enter a #include inside a macro expansion!");
NextDir = 0;
CurDir = 0;
// If 'Filename' is absolute, check to see if it exists and no searching.
// FIXME: this should be a sys::Path interface, this doesn't handle things
@ -286,23 +286,28 @@ const FileEntry *Preprocessor::LookupFile(const std::string &Filename,
// Step #0, unless disabled, check to see if the file is in the #includer's
// directory. This search is not done for <> headers.
if (!isSystem && !FromDir && !NoCurDirSearch) {
if (!isAngled && !FromDir && !NoCurDirSearch) {
const FileEntry *CurFE =
SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID());
if (CurFE) {
// Concatenate the requested file onto the directory.
// FIXME: should be in sys::Path.
if (const FileEntry *FE =
FileMgr.getFile(CurFE->getDir()->getName()+"/"+Filename)) {
if (CurNextDirLookup)
NextDir = CurNextDirLookup;
if (CurDirLookup)
CurDir = CurDirLookup;
else
NextDir = &SearchDirs[0];
CurDir = 0;
// This file is a system header or C++ unfriendly if the old file is.
getFileInfo(FE).DirInfo = getFileInfo(CurFE).DirInfo;
return FE;
}
}
}
// If this is a system #include, ignore the user #include locs.
unsigned i = isSystem ? SystemDirIdx : 0;
unsigned i = isAngled ? SystemDirIdx : 0;
// If this is a #include_next request, start searching after the directory the
// file was found in.
@ -315,7 +320,10 @@ const FileEntry *Preprocessor::LookupFile(const std::string &Filename,
// FIXME: should be in sys::Path.
if (const FileEntry *FE =
FileMgr.getFile(SearchDirs[i].getDir()->getName()+"/"+Filename)) {
NextDir = &SearchDirs[i+1];
CurDir = &SearchDirs[i];
// This file is a system header or C++ unfriendly if the dir is.
getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic();
return FE;
}
}
@ -328,12 +336,12 @@ const FileEntry *Preprocessor::LookupFile(const std::string &Filename,
/// start lexing tokens from it instead of the current buffer. Return true
/// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID,
const DirectoryLookup *NextDir) {
const DirectoryLookup *CurDir) {
++NumEnteredSourceFiles;
// Add the current lexer to the include stack.
if (CurLexer) {
IncludeStack.push_back(IncludeStackInfo(CurLexer, CurNextDirLookup));
IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
} else {
assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
}
@ -343,12 +351,21 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
const SourceBuffer *Buffer = SourceMgr.getBuffer(FileID);
CurLexer = new Lexer(Buffer, FileID, *this);
CurNextDirLookup = NextDir;
CurLexer = new Lexer(Buffer, FileID, *this);
CurDirLookup = CurDir;
// Notify the client, if desired, that we are in a new source file.
if (FileChangeHandler)
FileChangeHandler(CurLexer->getSourceLocation(CurLexer->BufferStart), true);
if (FileChangeHandler) {
DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir;
// Get the file entry for the current file.
if (const FileEntry *FE =
SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
FileType = getFileInfo(FE).DirInfo;
FileChangeHandler(CurLexer->getSourceLocation(CurLexer->BufferStart), true,
FileType);
}
}
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
@ -357,9 +374,9 @@ void Preprocessor::EnterMacro(LexerToken &Tok) {
IdentifierTokenInfo *Identifier = Tok.getIdentifierInfo();
MacroInfo &MI = *Identifier->getMacroInfo();
if (CurLexer) {
IncludeStack.push_back(IncludeStackInfo(CurLexer, CurNextDirLookup));
CurLexer = 0;
CurNextDirLookup = 0;
IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
CurLexer = 0;
CurDirLookup = 0;
} else if (CurMacroExpander) {
MacroStack.push_back(CurMacroExpander);
}
@ -492,14 +509,22 @@ void Preprocessor::HandleEndOfFile(LexerToken &Result, bool isEndOfMacro) {
if (!IncludeStack.empty()) {
// We're done with the #included file.
delete CurLexer;
CurLexer = IncludeStack.back().TheLexer;
CurNextDirLookup = IncludeStack.back().TheDirLookup;
CurLexer = IncludeStack.back().TheLexer;
CurDirLookup = IncludeStack.back().TheDirLookup;
IncludeStack.pop_back();
// Notify the client, if desired, that we are in a new source file.
if (FileChangeHandler && !isEndOfMacro)
if (FileChangeHandler && !isEndOfMacro) {
DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir;
// Get the file entry for the current file.
if (const FileEntry *FE =
SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
FileType = getFileInfo(FE).DirInfo;
FileChangeHandler(CurLexer->getSourceLocation(CurLexer->BufferPtr),
false);
false, FileType);
}
return Lex(Result);
}
@ -923,8 +948,8 @@ void Preprocessor::HandleIncludeDirective(LexerToken &IncludeTok,
return Diag(FilenameTok, diag::err_pp_empty_filename);
// Search include directories.
const DirectoryLookup *NextDir;
const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, NextDir);
const DirectoryLookup *CurDir;
const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
if (File == 0)
return Diag(FilenameTok, diag::err_pp_file_not_found);
@ -953,7 +978,7 @@ void Preprocessor::HandleIncludeDirective(LexerToken &IncludeTok,
return Diag(FilenameTok, diag::err_pp_file_not_found);
// Finally, if all is good, enter the new file!
EnterSourceFile(FileID, NextDir);
EnterSourceFile(FileID, CurDir);
// Increment the number of times this file has been included.
++FileInfo.NumIncludes;
@ -967,12 +992,15 @@ void Preprocessor::HandleIncludeNextDirective(LexerToken &IncludeNextTok) {
// #include_next is like #include, except that we start searching after
// the current found directory. If we can't do this, issue a
// diagnostic.
const DirectoryLookup *Lookup = CurNextDirLookup;
const DirectoryLookup *Lookup = CurDirLookup;
if (IncludeStack.empty()) {
Lookup = 0;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
} else if (Lookup == 0) {
Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
++Lookup;
}
return HandleIncludeDirective(IncludeNextTok, Lookup);

View File

@ -93,7 +93,8 @@ class Preprocessor {
/// EnteringFile indicates whether this is because we are entering a new
/// #include'd file (when true) or whether we're exiting one because we ran
/// off the end (when false).
void (*FileChangeHandler)(SourceLocation Loc, bool EnteringFile);
void (*FileChangeHandler)(SourceLocation Loc, bool EnteringFile,
DirectoryLookup::DirType FileType);
enum {
/// MaxIncludeStackDepth - Maximum depth of #includes.
@ -112,9 +113,10 @@ class Preprocessor {
/// not expanding a macro. One of CurLexer and CurMacroExpander must be null.
Lexer *CurLexer;
/// CurDirLookup - The next DirectoryLookup structure to search for a file if
/// CurLexer is non-null. This allows us to implement #include_next.
const DirectoryLookup *CurNextDirLookup;
/// CurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
/// implement #include_next and find directory-specific properties.
const DirectoryLookup *CurDirLookup;
/// IncludeStack - This keeps track of the stack of files currently #included,
/// not counting CurLexer.
@ -139,14 +141,20 @@ class Preprocessor {
/// PreFileInfo - The preprocessor keeps track of this information for each
/// file that is #included.
struct PerFileInfo {
// isImport - True if this is a #import'd or #pragma once file.
bool isImport;
/// isImport - True if this is a #import'd or #pragma once file.
bool isImport : 1;
// NumIncludes - This is the number of times the file has been included
// already.
/// DirInfo - Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
/// by #pragma gcc system_header.
DirectoryLookup::DirType DirInfo : 2;
/// NumIncludes - This is the number of times the file has been included
/// already.
unsigned short NumIncludes;
PerFileInfo() : isImport(false), NumIncludes(0) {}
PerFileInfo() : isImport(false), DirInfo(DirectoryLookup::NormalHeaderDir),
NumIncludes(0) {}
};
/// FileInfo - This contains all of the preprocessor-specific data about files
@ -196,7 +204,8 @@ public:
/// EnteringFile indicates whether this is because we are entering a new
/// #include'd file (when true) or whether we're exiting one because we ran
/// off the end (when false).
void setFileChangeHandler(void (*Handler)(SourceLocation, bool)) {
void setFileChangeHandler(void (*Handler)(SourceLocation, bool,
DirectoryLookup::DirType)) {
FileChangeHandler = Handler;
}
@ -239,14 +248,14 @@ public:
void AddKeywords();
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isSystem indicates whether the file reference is
/// for system #include's or not. If successful, this returns 'UsedDir', the
/// return null on failure. isAngled indicates whether the file reference is
/// a <> reference. If successful, this returns 'UsedDir', the
/// DirectoryLookup member the file was found in, or null if not applicable.
/// If FromDir is non-null, the directory search should start with the entry
/// after the indicated lookup. This is used to implement #include_next.
const FileEntry *LookupFile(const std::string &Filename, bool isSystem,
/// If CurDir is non-null, the file was found in the specified directory
/// search location. This is used to implement #include_next.
const FileEntry *LookupFile(const std::string &Filename, bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&NextDir);
const DirectoryLookup *&CurDir);
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.