Fix the rest of rdar://6243860 hopefully. This requires changing FileIDInfo

to whether the fileid is a 'extern c system header' in addition to whether it
is a system header, most of this is spreading plumbing around.  Once we have that,
PPLexerChange bases its "file enter/exit" notifications to PPCallbacks to
base the system header state on FileIDInfo instead of HeaderSearch.  Finally,
in Preprocessor::HandleIncludeDirective, mirror logic in GCC: the system headerness
of a file being entered can be set due to the #includer or the #includee.

llvm-svn: 56688
This commit is contained in:
Chris Lattner 2008-09-26 20:12:23 +00:00
parent 71efd8159e
commit c88a23e8d7
6 changed files with 50 additions and 51 deletions

View File

@ -112,10 +112,11 @@ namespace SrcMgr {
/// ChunkNo - Really large buffers are broken up into chunks that are /// ChunkNo - Really large buffers are broken up into chunks that are
/// each (1 << SourceLocation::FilePosBits) in size. This specifies the /// each (1 << SourceLocation::FilePosBits) in size. This specifies the
/// chunk number of this FileID. /// chunk number of this FileID.
unsigned ChunkNo:30; unsigned ChunkNo : 30;
/// isSystemHeader - Set for system header files. /// DirCharacteristic - This is an instance of DirectoryLookup::DirType,
bool isSysHeader:1; /// indicating whether this is a system header dir or not.
unsigned DirCharacteristic : 2;
/// Content - Information about the source buffer itself. /// Content - Information about the source buffer itself.
const ContentCache* Content; const ContentCache* Content;
@ -123,19 +124,22 @@ namespace SrcMgr {
public: public:
/// get - Return a FileIDInfo object. /// get - Return a FileIDInfo object.
static FileIDInfo get(SourceLocation IL, unsigned CN, static FileIDInfo get(SourceLocation IL, unsigned CN,
const ContentCache *Con, bool SysHeader) { const ContentCache *Con, unsigned DirCharacter) {
FileIDInfo X; FileIDInfo X;
X.IncludeLoc = IL; X.IncludeLoc = IL;
X.ChunkNo = CN; X.ChunkNo = CN;
X.Content = Con; X.Content = Con;
X.isSysHeader = SysHeader; X.DirCharacteristic = DirCharacter;
return X; return X;
} }
SourceLocation getIncludeLoc() const { return IncludeLoc; } SourceLocation getIncludeLoc() const { return IncludeLoc; }
unsigned getChunkNo() const { return ChunkNo; } unsigned getChunkNo() const { return ChunkNo; }
const ContentCache* getContentCache() const { return Content; } const ContentCache* getContentCache() const { return Content; }
bool isSystemHeader() const { return isSysHeader; }
/// getDirCharacteristic - Return whether this is a system header or not.
/// FIXME: rename from dir to file?
unsigned getDirCharacteristic() const { return DirCharacteristic; }
/// Emit - Emit this FileIDInfo to Bitcode. /// Emit - Emit this FileIDInfo to Bitcode.
void Emit(llvm::Serializer& S) const; void Emit(llvm::Serializer& S) const;
@ -250,10 +254,10 @@ public:
/// being #included from the specified IncludePosition. This returns 0 on /// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input. /// error and translates NULL into standard input.
unsigned createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, unsigned createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
bool isSysHeader = false) { unsigned DirCharacter) {
const SrcMgr::ContentCache *IR = getContentCache(SourceFile); const SrcMgr::ContentCache *IR = getContentCache(SourceFile);
if (IR == 0) return 0; // Error opening file? if (IR == 0) return 0; // Error opening file?
return createFileID(IR, IncludePos, isSysHeader); return createFileID(IR, IncludePos, DirCharacter);
} }
/// createMainFileID - Create the FileID for the main source file. /// createMainFileID - Create the FileID for the main source file.
@ -261,17 +265,17 @@ public:
SourceLocation IncludePos) { SourceLocation IncludePos) {
assert (MainFileID == 0 && "MainFileID already set!"); assert (MainFileID == 0 && "MainFileID already set!");
MainFileID = createFileID(SourceFile,IncludePos); MainFileID = createFileID(SourceFile, IncludePos, 0);
return MainFileID; return MainFileID;
} }
/// createFileIDForMemBuffer - Create a new FileID that represents the /// createFileIDForMemBuffer - Create a new FileID that represents the
/// specified memory buffer. This does no caching of the buffer and takes /// specified memory buffer. This does no caching of the buffer and takes
/// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once. /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
bool isSysHeader = false) {
return createFileID(createMemBufferContentCache(Buffer), SourceLocation(), return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
isSysHeader); // FIXME: USE ENUM
0/*normal header*/);
} }
/// createMainFileIDForMembuffer - Create the FileID for a memory buffer /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
@ -432,8 +436,13 @@ public:
/// isInSystemHeader - Returns if a SourceLocation is in a system header. /// isInSystemHeader - Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const { bool isInSystemHeader(SourceLocation Loc) const {
return getFIDInfo(getPhysicalLoc(Loc).getFileID())->isSystemHeader(); // FIXME: Use proper enum here!
return getDirCharacteristic(Loc) != 0;
} }
unsigned getDirCharacteristic(SourceLocation Loc) const {
return getFIDInfo(getPhysicalLoc(Loc).getFileID())->getDirCharacteristic();
}
/// PrintStats - Print statistics to stderr. /// PrintStats - Print statistics to stderr.
/// ///
@ -453,7 +462,7 @@ private:
/// include position. This works regardless of whether the ContentCache /// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source. /// corresponds to a file or some other input source.
unsigned createFileID(const SrcMgr::ContentCache* File, unsigned createFileID(const SrcMgr::ContentCache* File,
SourceLocation IncludePos, bool isSysHeader = false); SourceLocation IncludePos, unsigned DirCharacter);
/// getContentCache - Create or return a cached ContentCache for the specified /// getContentCache - Create or return a cached ContentCache for the specified
/// file. This returns null on failure. /// file. This returns null on failure.

View File

@ -458,9 +458,6 @@ private:
/// #include. /// #include.
bool isInPrimaryFile() const; bool isInPrimaryFile() const;
/// isSystemHeader - Return true if F is a system header.
bool isSystemHeader(const FileEntry* F) const;
/// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
/// current line until the tok::eom token is found. /// current line until the tok::eom token is found.
void DiscardUntilEndOfDirective(); void DiscardUntilEndOfDirective();

View File

@ -76,14 +76,14 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
/// corresponds to a file or some other input source. /// corresponds to a file or some other input source.
unsigned SourceManager::createFileID(const ContentCache *File, unsigned SourceManager::createFileID(const ContentCache *File,
SourceLocation IncludePos, SourceLocation IncludePos,
bool isSysHeader) { unsigned DirCharacter) {
// If FileEnt is really large (e.g. it's a large .i file), we may not be able // If FileEnt is really large (e.g. it's a large .i file), we may not be able
// to fit an arbitrary position in the file in the FilePos field. To handle // to fit an arbitrary position in the file in the FilePos field. To handle
// this, we create one FileID for each chunk of the file that fits in a // this, we create one FileID for each chunk of the file that fits in a
// FilePos field. // FilePos field.
unsigned FileSize = File->Buffer->getBufferSize(); unsigned FileSize = File->Buffer->getBufferSize();
if (FileSize+1 < (1 << SourceLocation::FilePosBits)) { if (FileSize+1 < (1 << SourceLocation::FilePosBits)) {
FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File, isSysHeader)); FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File, DirCharacter));
assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) && assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
"Ran out of file ID's!"); "Ran out of file ID's!");
return FileIDs.size(); return FileIDs.size();
@ -95,7 +95,7 @@ unsigned SourceManager::createFileID(const ContentCache *File,
unsigned ChunkNo = 0; unsigned ChunkNo = 0;
while (1) { while (1) {
FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File, FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File,
isSysHeader)); DirCharacter));
if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break; if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break;
FileSize -= (1 << SourceLocation::FilePosBits); FileSize -= (1 << SourceLocation::FilePosBits);

View File

@ -600,7 +600,8 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
/// HandleIncludeDirective - The "#include" tokens have just been read, read the /// HandleIncludeDirective - The "#include" tokens have just been read, read the
/// file to be included from the lexer, then include it! This is a common /// file to be included from the lexer, then include it! This is a common
/// routine with functionality shared between #include, #include_next and /// routine with functionality shared between #include, #include_next and
/// #import. /// #import. LookupFrom is set when this is a #include_next directive, it
/// specifies the file to start searching from.
void Preprocessor::HandleIncludeDirective(Token &IncludeTok, void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
const DirectoryLookup *LookupFrom, const DirectoryLookup *LookupFrom,
bool isImport) { bool isImport) {
@ -666,15 +667,22 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
return Diag(FilenameTok, diag::err_pp_file_not_found, return Diag(FilenameTok, diag::err_pp_file_not_found,
std::string(FilenameStart, FilenameEnd)); std::string(FilenameStart, FilenameEnd));
// Ask HeaderInfo if we should enter this #include file. // Ask HeaderInfo if we should enter this #include file. If not, #including
if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) { // this file will have no effect.
// If it returns true, #including this file will have no effect. if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport))
return; return;
}
// The #included file will be considered to be a system header if either it is
// in a system include directory, or if the #includer is a system include
// header.
unsigned FileCharacter =
// FIXME: Casts
std::max((unsigned)HeaderInfo.getFileDirFlavor(File),
SourceMgr.getDirCharacteristic(getCurrentFileLexer()->getFileLoc()));
// Look up the file, create a File ID for it. // Look up the file, create a File ID for it.
unsigned FileID = SourceMgr.createFileID(File, FilenameTok.getLocation(), unsigned FileID = SourceMgr.createFileID(File, FilenameTok.getLocation(),
isSystemHeader(File)); FileCharacter);
if (FileID == 0) if (FileID == 0)
return Diag(FilenameTok, diag::err_pp_file_not_found, return Diag(FilenameTok, diag::err_pp_file_not_found,
std::string(FilenameStart, FilenameEnd)); std::string(FilenameStart, FilenameEnd));

View File

@ -78,7 +78,7 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this); Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
EnterSourceFileWithLexer(TheLexer, CurDir); EnterSourceFileWithLexer(TheLexer, CurDir);
} }
/// EnterSourceFile - Add a source file to the top of the include stack and /// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. /// start lexing tokens from it instead of the current buffer.
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
@ -95,12 +95,10 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
// Notify the client, if desired, that we are in a new source file. // Notify the client, if desired, that we are in a new source file.
if (Callbacks && !CurLexer->Is_PragmaLexer) { if (Callbacks && !CurLexer->Is_PragmaLexer) {
DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir; DirectoryLookup::DirType FileType =
// FIXME:
// Get the file entry for the current file. (DirectoryLookup::DirType)
if (const FileEntry *FE = SourceMgr.getDirCharacteristic(CurLexer->getFileLoc());
SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
FileType = HeaderInfo.getFileDirFlavor(FE);
Callbacks->FileChanged(CurLexer->getFileLoc(), Callbacks->FileChanged(CurLexer->getFileLoc(),
PPCallbacks::EnterFile, FileType); PPCallbacks::EnterFile, FileType);
@ -182,13 +180,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
// Notify the client, if desired, that we are in a new source file. // Notify the client, if desired, that we are in a new source file.
if (Callbacks && !isEndOfMacro && CurLexer) { if (Callbacks && !isEndOfMacro && CurLexer) {
DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir; DirectoryLookup::DirType FileType =
// FIXME:
(DirectoryLookup::DirType)
SourceMgr.getDirCharacteristic(CurLexer->getFileLoc());
// Get the file entry for the current file.
if (const FileEntry *FE =
SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
FileType = HeaderInfo.getFileDirFlavor(FE);
Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr), Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr),
PPCallbacks::ExitFile, FileType); PPCallbacks::ExitFile, FileType);
} }

View File

@ -117,17 +117,6 @@ Preprocessor::~Preprocessor() {
delete Callbacks; delete Callbacks;
} }
bool Preprocessor::isSystemHeader(const FileEntry* F) const {
if (F) {
DirectoryLookup::DirType DirInfo = HeaderInfo.getFileDirFlavor(F);
if (DirInfo == DirectoryLookup::SystemHeaderDir ||
DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
return true;
}
return false;
}
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at /// Diag - Forwarding function for diagnostics. This emits a diagnostic at
/// the specified Token's location, translating the token's start /// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering. /// position in the current buffer into a SourcePosition object for rendering.