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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56688 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 770ac80..c8a0b49 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -112,10 +112,11 @@
     /// ChunkNo - Really large buffers are broken up into chunks that are
     /// each (1 << SourceLocation::FilePosBits) in size.  This specifies the
     /// chunk number of this FileID.
-    unsigned ChunkNo:30;
+    unsigned ChunkNo : 30;
     
-    /// isSystemHeader - Set for system header files.
-    bool isSysHeader:1;
+    /// DirCharacteristic - This is an instance of DirectoryLookup::DirType,
+    /// indicating whether this is a system header dir or not.
+    unsigned DirCharacteristic : 2;
     
     /// Content - Information about the source buffer itself.
     const ContentCache* Content;
@@ -123,19 +124,22 @@
   public:
     /// get - Return a FileIDInfo object.
     static FileIDInfo get(SourceLocation IL, unsigned CN, 
-                          const ContentCache *Con, bool SysHeader) {
+                          const ContentCache *Con, unsigned DirCharacter) {
       FileIDInfo X;
       X.IncludeLoc = IL;
       X.ChunkNo = CN;
       X.Content = Con;
-      X.isSysHeader = SysHeader;
+      X.DirCharacteristic = DirCharacter;
       return X;
     }
     
     SourceLocation getIncludeLoc() const { return IncludeLoc; }
     unsigned getChunkNo() const { return ChunkNo; }
     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.
     void Emit(llvm::Serializer& S) const;
@@ -250,10 +254,10 @@
   /// being #included from the specified IncludePosition.  This returns 0 on
   /// error and translates NULL into standard input.
   unsigned createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
-                        bool isSysHeader = false) {
+                        unsigned DirCharacter) {
     const SrcMgr::ContentCache *IR = getContentCache(SourceFile);
     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.
@@ -261,17 +265,17 @@
                             SourceLocation IncludePos) {
     
     assert (MainFileID == 0 && "MainFileID already set!");
-    MainFileID = createFileID(SourceFile,IncludePos);
+    MainFileID = createFileID(SourceFile, IncludePos, 0);
     return MainFileID;
   }
   
   /// createFileIDForMemBuffer - Create a new FileID that represents the
   /// specified memory buffer.  This does no caching of the buffer and takes
   /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
-  unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
-                                    bool isSysHeader = false) {
+  unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
     return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
-                        isSysHeader);
+                        // FIXME: USE ENUM
+                        0/*normal header*/);
   }
   
   /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
@@ -432,8 +436,13 @@
 
   /// isInSystemHeader - Returns if a SourceLocation is in a system header.
   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.
   ///
@@ -453,7 +462,7 @@
   ///  include position.  This works regardless of whether the ContentCache
   ///  corresponds to a file or some other input source.
   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
   ///  file.  This returns null on failure.
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index cc056ea..96a4153 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -458,9 +458,6 @@
   /// #include.
   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
   /// current line until the tok::eom token is found.
   void DiscardUntilEndOfDirective();
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 7534ac4..66a8514 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -76,14 +76,14 @@
 /// corresponds to a file or some other input source.
 unsigned SourceManager::createFileID(const ContentCache *File,
                                      SourceLocation IncludePos,
-                                     bool isSysHeader) {
+                                     unsigned DirCharacter) {
   // 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
   // this, we create one FileID for each chunk of the file that fits in a
   // FilePos field.
   unsigned FileSize = File->Buffer->getBufferSize();
   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) &&
            "Ran out of file ID's!");
     return FileIDs.size();
@@ -95,7 +95,7 @@
   unsigned ChunkNo = 0;
   while (1) {
     FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File,
-                                      isSysHeader));
+                                      DirCharacter));
 
     if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break;
     FileSize -= (1 << SourceLocation::FilePosBits);
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 70cd0ed..504bc45 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -600,7 +600,8 @@
 /// HandleIncludeDirective - The "#include" tokens have just been read, read the
 /// file to be included from the lexer, then include it!  This is a common
 /// 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,
                                           const DirectoryLookup *LookupFrom,
                                           bool isImport) {
@@ -666,15 +667,22 @@
     return Diag(FilenameTok, diag::err_pp_file_not_found,
                 std::string(FilenameStart, FilenameEnd));
   
-  // Ask HeaderInfo if we should enter this #include file.
-  if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) {
-    // If it returns true, #including this file will have no effect.
+  // Ask HeaderInfo if we should enter this #include file.  If not, #including
+  // this file will have no effect.
+  if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport))
     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.
   unsigned FileID = SourceMgr.createFileID(File, FilenameTok.getLocation(),
-                                           isSystemHeader(File));
+                                           FileCharacter);
   if (FileID == 0)
     return Diag(FilenameTok, diag::err_pp_file_not_found,
                 std::string(FilenameStart, FilenameEnd));
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index d1c44cf..1522bf5 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -78,7 +78,7 @@
   Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
   EnterSourceFileWithLexer(TheLexer, CurDir);
 }  
-  
+
 /// EnterSourceFile - Add a source file to the top of the include stack and
 /// start lexing tokens from it instead of the current buffer.
 void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, 
@@ -95,12 +95,10 @@
   
   // Notify the client, if desired, that we are in a new source file.
   if (Callbacks && !CurLexer->Is_PragmaLexer) {
-    DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir;
-    
-    // Get the file entry for the current file.
-    if (const FileEntry *FE = 
-           SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
-      FileType = HeaderInfo.getFileDirFlavor(FE);
+    DirectoryLookup::DirType FileType =
+     // FIXME:
+      (DirectoryLookup::DirType)
+       SourceMgr.getDirCharacteristic(CurLexer->getFileLoc());
     
     Callbacks->FileChanged(CurLexer->getFileLoc(),
                            PPCallbacks::EnterFile, FileType);
@@ -182,13 +180,11 @@
 
     // Notify the client, if desired, that we are in a new source file.
     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),
                              PPCallbacks::ExitFile, FileType);
     }
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 36e80c9..691f46a 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -117,17 +117,6 @@
   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
 /// the specified Token's location, translating the token's start
 /// position in the current buffer into a SourcePosition object for rendering.