]> granicus.if.org Git - clang/commitdiff
Fix header-search problems with precompiled headers, where the
authorDouglas Gregor <dgregor@apple.com>
Tue, 16 Mar 2010 16:35:32 +0000 (16:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 16 Mar 2010 16:35:32 +0000 (16:35 +0000)
presence or absence of header map arguments when using the precompiled
header would cause Clang to get confused about which headers had
already been included/imported, along with their controlling
macros. The fundamental problem is that the serialization of the
header search information was relying on the UIDs of FileEntry objects
at PCH generation time and PCH load time to be equivalent, which
effectively means that we had to probe the same files in the same
order. Differing header map arguments caused an extra FileEntry
lookup, but it's easy to imagine other minor command-line arguments
triggering this problem.

Header-search information is now encoded along with the
source-location entry for a file, so that we register information
about a file's properties as a header at the same time we create the
FileEntry for that file.

Fixes <rdar://problem/7743243>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98636 91177308-0d34-0410-b5e6-96231b3b80d8

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

index e234e9838a12ee0b53c63f32535108fb76292830..e2c27e6ddfab7bcd044eca15bab4e4c96c0d8a95 100644 (file)
@@ -245,10 +245,7 @@ namespace clang {
       SM_SLOC_INSTANTIATION_ENTRY = 4,
       /// \brief Describes the SourceManager's line table, with
       /// information about #line directives.
-      SM_LINE_TABLE = 5,
-      /// \brief Describes one header file info [isImport, DirInfo, NumIncludes]
-      /// ControllingMacro is optional.
-      SM_HEADER_FILE_INFO = 6
+      SM_LINE_TABLE = 5
     };
 
     /// \brief Record types used within a preprocessor block.
index 065006fce5c4a30fa239df614ae6fb63c18138da..7aafb2d5dee498544323281e8952178dd9245580 100644 (file)
@@ -106,7 +106,7 @@ public:
   }
 
   /// \brief Receives a HeaderFileInfo entry.
-  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {}
+  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {}
 
   /// \brief Receives __COUNTER__ value.
   virtual void ReadCounter(unsigned Value) {}
@@ -130,7 +130,7 @@ public:
                                     FileID PCHBufferID,
                                     llvm::StringRef OriginalFileName,
                                     std::string &SuggestedPredefines);
-  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
+  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
   virtual void ReadCounter(unsigned Value);
 };
 
index 16b8379045e59a6863925fdb04d1b90097c46abe..978585caf0e4244582e5b9245a34de6b5f7c108d 100644 (file)
@@ -214,9 +214,10 @@ public:
 
   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(); }
+  typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
+  header_file_iterator header_file_begin() const { return FileInfo.begin(); }
+  header_file_iterator header_file_end() const { return FileInfo.end(); }
+  unsigned header_file_size() const { return FileInfo.size(); }
 
   // Used by PCHReader.
   void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
index 49eb2a0e600d5b7d9b48cdf35adb0c2ac2a9310f..f1c0247b814a398d51dff341a7fc857b68786eb2 100644 (file)
@@ -300,8 +300,10 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
   return false;
 }
 
-void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
-  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
+                                      unsigned ID) {
+  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
+  ++NumHeaderInfos;
 }
 
 void PCHValidator::ReadCounter(unsigned Value) {
@@ -850,17 +852,6 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
         return Failure;
       break;
 
-    case pch::SM_HEADER_FILE_INFO: {
-      HeaderFileInfo HFI;
-      HFI.isImport = Record[0];
-      HFI.DirInfo = Record[1];
-      HFI.NumIncludes = Record[2];
-      HFI.ControllingMacroID = Record[3];
-      if (Listener)
-        Listener->ReadHeaderFileInfo(HFI);
-      break;
-    }
-
     case pch::SM_SLOC_FILE_ENTRY:
     case pch::SM_SLOC_BUFFER_ENTRY:
     case pch::SM_SLOC_INSTANTIATION_ENTRY:
@@ -918,6 +909,14 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
       const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
         .setHasLineDirectives();
 
+    // Reconstruct header-search information for this file.
+    HeaderFileInfo HFI;
+    HFI.isImport = Record[4];
+    HFI.DirInfo = Record[5];
+    HFI.NumIncludes = Record[6];
+    HFI.ControllingMacroID = Record[7];
+    if (Listener)
+      Listener->ReadHeaderFileInfo(HFI, File->getUID());
     break;
   }
 
index c256b4103a7dc4c6451c5ac005f319aaf4b9cccd..e55599b7ecaa3a119a6b40eb24c4001ee518ab92 100644 (file)
@@ -573,7 +573,6 @@ void PCHWriter::WriteBlockInfoBlock() {
   RECORD(SM_SLOC_BUFFER_BLOB);
   RECORD(SM_SLOC_INSTANTIATION_ENTRY);
   RECORD(SM_LINE_TABLE);
-  RECORD(SM_HEADER_FILE_INFO);
 
   // Preprocessor Block.
   BLOCK(PREPROCESSOR_BLOCK);
@@ -918,6 +917,11 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+  // HeaderFileInfo fields.
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isImport
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // DirInfo
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumIncludes
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // ControllingMacro
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
   return Stream.EmitAbbrev(Abbrev);
 }
@@ -1019,20 +1023,6 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
     Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
   }
 
-  // Write out entries for all of the header files we know about.
-  HeaderSearch &HS = PP.getHeaderSearchInfo();
-  Record.clear();
-  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);
-    AddIdentifierRef(I->ControllingMacro, Record);
-    Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record);
-    Record.clear();
-  }
-
   // Write out the source location entry table. We skip the first
   // entry, which is always the same dummy entry.
   std::vector<uint32_t> SLocEntryOffsets;
@@ -1069,6 +1059,16 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
         // The source location entry is a file. The blob associated
         // with this entry is the file name.
 
+        // Emit header-search information associated with this file.
+        HeaderFileInfo HFI;
+        HeaderSearch &HS = PP.getHeaderSearchInfo();
+        if (Content->Entry->getUID() < HS.header_file_size())
+          HFI = HS.header_file_begin()[Content->Entry->getUID()];
+        Record.push_back(HFI.isImport);
+        Record.push_back(HFI.DirInfo);
+        Record.push_back(HFI.NumIncludes);
+        AddIdentifierRef(HFI.ControllingMacro, Record);
+
         // Turn the file name into an absolute path, if it isn't already.
         const char *Filename = Content->Entry->getName();
         llvm::sys::Path FilePath(Filename, strlen(Filename));
diff --git a/test/PCH/headermap.h b/test/PCH/headermap.h
new file mode 100644 (file)
index 0000000..efab2d8
--- /dev/null
@@ -0,0 +1,3 @@
+/* Helper for the headermap.m test */
+int x = 17;
+
diff --git a/test/PCH/headermap.m b/test/PCH/headermap.m
new file mode 100644 (file)
index 0000000..6ba83d7
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: touch %t.hmap
+
+// RUN: %clang_cc1 -x objective-c -emit-pch -o %t.h.pch %S/headermap.h
+// RUN: %clang_cc1 -include-pch %t.h.pch %s
+
+// RUN: %clang_cc1 -x objective-c -emit-pch -o %t.h.pch %S/headermap.h
+// RUN: %clang_cc1 -include-pch %t.h.pch -I%t.hmap %s
+
+// RUN: %clang_cc1 -x objective-c -I%t.hmap -emit-pch -o %t.h.pch %S/headermap.h
+// RUN: %clang_cc1 -include-pch %t.h.pch %s
+
+// RUN: %clang_cc1 -x objective-c -I%t.hmap -emit-pch -o %t.h.pch %S/headermap.h
+// RUN: %clang_cc1 -include-pch %t.h.pch -I%t.hmap %s
+#import "headermap.h"
+