]> granicus.if.org Git - clang/commitdiff
Add PCH support for #import.
authorSteve Naroff <snaroff@apple.com>
Fri, 24 Apr 2009 20:03:17 +0000 (20:03 +0000)
committerSteve Naroff <snaroff@apple.com>
Fri, 24 Apr 2009 20:03:17 +0000 (20:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69987 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/PCHBitCodes.h
include/clang/Lex/HeaderSearch.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Lex/HeaderSearch.cpp
lib/Lex/PPLexerChange.cpp
test/PCH/objc_import.h [new file with mode: 0644]
test/PCH/objc_import.m [new file with mode: 0644]

index c7c201ddd50d88928c82cd0d773dd295730280ca..31a30b8f4d81b8e2b6a694fae92526fe20cf62f6 100644 (file)
@@ -211,7 +211,11 @@ namespace clang {
       
       /// \brief The value of the next __COUNTER__ to dispense.
       /// [PP_COUNTER_VALUE, Val]
-      PP_COUNTER_VALUE = 4
+      PP_COUNTER_VALUE = 4,
+      
+      /// \brief Describes one header file info [isImport, DirInfo, NumIncludes]
+      /// ControlloingMacro is optional.
+      PP_HEADER_FILE_INFO = 5
     };
 
     /// \defgroup PCHAST Precompiled header AST constants
index ef860c589e742ad903f5efba300401b65079eb43..fe7e7aef3bac0a24414f8d320c03b2f807154fda 100644 (file)
@@ -23,7 +23,31 @@ class FileEntry;
 class FileManager;
 class IdentifierInfo;
 
-  
+/// HeaderFileInfo - The preprocessor keeps track of this information for each
+/// file that is #included.
+struct HeaderFileInfo {
+  /// isImport - True if this is a #import'd or #pragma once file.
+  bool isImport : 1;
+  
+  /// 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.  This is an instance of
+  /// SrcMgr::CharacteristicKind.
+  unsigned DirInfo : 2;
+  
+  /// NumIncludes - This is the number of times the file has been included
+  /// already.
+  unsigned short NumIncludes;
+  
+  /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
+  /// that protects the entire contents of the file, this is the identifier
+  /// for the macro that controls whether or not it has any effect.
+  const IdentifierInfo *ControllingMacro;
+  
+  HeaderFileInfo() : isImport(false), DirInfo(SrcMgr::C_User),
+    NumIncludes(0), ControllingMacro(0) {}
+};
+
 /// HeaderSearch - This class encapsulates the information needed to find the
 /// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
 class HeaderSearch {
@@ -39,35 +63,10 @@ class HeaderSearch {
   unsigned SystemDirIdx;
   bool NoCurDirSearch;
   
-  /// 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 : 1;
-    
-    /// 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.  This is an instance of
-    /// SrcMgr::CharacteristicKind.
-    unsigned DirInfo : 2;
-    
-    /// NumIncludes - This is the number of times the file has been included
-    /// already.
-    unsigned short NumIncludes;
-    
-    /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
-    /// that protects the entire contents of the file, this is the identifier
-    /// for the macro that controls whether or not it has any effect.
-    const IdentifierInfo *ControllingMacro;
-    
-    PerFileInfo() : isImport(false), DirInfo(SrcMgr::C_User),
-      NumIncludes(0), ControllingMacro(0) {}
-  };
-  
   /// FileInfo - This contains all of the preprocessor-specific data about files
   /// that are included.  The vector is indexed by the FileEntry's UID.
   ///
-  std::vector<PerFileInfo> FileInfo;
+  std::vector<HeaderFileInfo> FileInfo;
 
   /// LookupFileCache - This is keeps track of each lookup performed by
   /// LookupFile.  The first part of the value is the starting index in
@@ -190,13 +189,20 @@ public:
   const HeaderMap *CreateHeaderMap(const FileEntry *FE);
   
   void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
+
+  typedef std::vector<HeaderFileInfo>::iterator header_file_iterator;
+  header_file_iterator header_file_begin() { return FileInfo.begin(); }
+  header_file_iterator header_file_end() { return FileInfo.end(); }
+
+  // Used by PCHReader.
+  void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
   
   void PrintStats();
 private:
       
-  /// getFileInfo - Return the PerFileInfo structure for the specified
+  /// getFileInfo - Return the HeaderFileInfo structure for the specified
   /// FileEntry.
-  PerFileInfo &getFileInfo(const FileEntry *FE);
+  HeaderFileInfo &getFileInfo(const FileEntry *FE);
 };
 
 }  // end namespace clang
index d97cf810baf9ae507e9786fb7434e482a7a577a1..62d0ba4f9f095b7da54c0ab3f8be2c9bed44d051 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang/AST/Type.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
 #include "clang/Basic/OnDiskHashTable.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/SourceManagerInternals.h"
@@ -1444,6 +1445,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
   RecordData Record;
   llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
   MacroInfo *Macro = 0;
+  
   while (true) {
     unsigned Code = Stream.ReadCode();
     switch (Code) {
@@ -1536,7 +1538,9 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
       Macro->AddTokenToBody(Tok);
       break;
     }
-    }
+    case pch::PP_HEADER_FILE_INFO:
+      break; // Already processed by ReadPreprocessorBlock().
+  }
   }
 }
 
@@ -1545,6 +1549,7 @@ bool PCHReader::ReadPreprocessorBlock() {
     return Error("Malformed preprocessor block record");
   
   RecordData Record;
+  unsigned NumHeaderInfos = 0;
   while (true) {
     unsigned Code = Stream.ReadCode();
     switch (Code) {
@@ -1581,8 +1586,16 @@ bool PCHReader::ReadPreprocessorBlock() {
     case pch::PP_MACRO_OBJECT_LIKE:
     case pch::PP_MACRO_FUNCTION_LIKE:
     case pch::PP_TOKEN:
-      // Once we've hit a macro definition or a token, we're done.
-      return false;
+      break;
+    case pch::PP_HEADER_FILE_INFO: {
+      HeaderFileInfo HFI;
+      HFI.isImport = Record[0];
+      HFI.DirInfo = Record[1];
+      HFI.NumIncludes = Record[2];
+      HFI.ControllingMacro = DecodeIdentifierInfo(Record[3]);
+      PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+      break;
+    }
     }
   }
 }
index 1af093a1cc7d47f9ec09a8f7d5fd67f2026b81f5..de4b9990b12406d2c0f26389d046eb065992c094 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang/AST/Type.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/OnDiskHashTable.h"
 #include "clang/Basic/SourceManager.h"
@@ -1547,7 +1548,22 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
     }
     ++NumMacros;
   }
-  
+
+  // Loop over all the header files.
+  HeaderSearch &HS = PP.getHeaderSearchInfo();  
+  for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), 
+                                          E = HS.header_file_end();
+       I != E; ++I) {
+    Record.push_back((*I).isImport);
+    Record.push_back((*I).DirInfo);
+    Record.push_back((*I).NumIncludes);
+    if ((*I).ControllingMacro)
+      AddIdentifierRef((*I).ControllingMacro, Record);
+    else
+      Record.push_back(0);
+    Stream.EmitRecord(pch::PP_HEADER_FILE_INFO, Record);
+    Record.clear();
+  }
   Stream.ExitBlock();
 }
 
index 2cc29ecbed8aedcca5c546ac9ba2b6a2f32c0bc2..ddea8e52a02199f4b82aad3a488dd946e7cc29e2 100644 (file)
@@ -377,14 +377,20 @@ LookupSubframeworkHeader(const char *FilenameStart,
 //===----------------------------------------------------------------------===//
 
 
-/// getFileInfo - Return the PerFileInfo structure for the specified
+/// getFileInfo - Return the HeaderFileInfo structure for the specified
 /// FileEntry.
-HeaderSearch::PerFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
+HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
   if (FE->getUID() >= FileInfo.size())
     FileInfo.resize(FE->getUID()+1);
   return FileInfo[FE->getUID()];
 }  
 
+void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) {
+  if (UID >= FileInfo.size())
+    FileInfo.resize(UID+1);
+  FileInfo[UID] = HFI;
+}
+
 /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
 /// #include, #include_next, or #import directive.  Return false if #including
 /// the file will have no effect or true if we should include it.
@@ -392,7 +398,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
   ++NumIncluded; // Count # of attempted #includes.
 
   // Get information about this file.
-  PerFileInfo &FileInfo = getFileInfo(File);
+  HeaderFileInfo &FileInfo = getFileInfo(File);
   
   // If this is a #import directive, check that we have not already imported
   // this header.
index 6f61c6516b323407c17ceb324175273660dcf556..2a05ba336fcacf1e3fa01516b3e7fd6e7798668d 100644 (file)
@@ -179,7 +179,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
   if (CurPPLexer) {  // Not ending a macro, ignore it.
     if (const IdentifierInfo *ControllingMacro = 
           CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
-      // Okay, this has a controlling macro, remember in PerFileInfo.
+      // Okay, this has a controlling macro, remember in HeaderFileInfo.
       if (const FileEntry *FE = 
             SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))
         HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
diff --git a/test/PCH/objc_import.h b/test/PCH/objc_import.h
new file mode 100644 (file)
index 0000000..8af87ab
--- /dev/null
@@ -0,0 +1,7 @@
+/* For use with the objc_import.m test */
+
+@interface TestPCH
++ alloc;
+- (void)instMethod;
+@end
+
diff --git a/test/PCH/objc_import.m b/test/PCH/objc_import.m
new file mode 100644 (file)
index 0000000..86c1c25
--- /dev/null
@@ -0,0 +1,15 @@
+// Test this without pch.
+// RUN: clang-cc -include %S/objc_import.h -fsyntax-only -verify %s &&
+
+// Test with pch.
+// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_import.h &&
+// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s 
+
+#import "objc_import.h"
+
+void func() {
+ TestPCH *xx;
+
+ xx = [TestPCH alloc];
+ [xx instMethod];
+}