forked from OSchip/llvm-project
				
			Fix header-search problems with precompiled headers, where the
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>. llvm-svn: 98636
This commit is contained in:
		
							parent
							
								
									298a83ecfe
								
							
						
					
					
						commit
						5712ebced0
					
				| 
						 | 
					@ -245,10 +245,7 @@ namespace clang {
 | 
				
			||||||
      SM_SLOC_INSTANTIATION_ENTRY = 4,
 | 
					      SM_SLOC_INSTANTIATION_ENTRY = 4,
 | 
				
			||||||
      /// \brief Describes the SourceManager's line table, with
 | 
					      /// \brief Describes the SourceManager's line table, with
 | 
				
			||||||
      /// information about #line directives.
 | 
					      /// information about #line directives.
 | 
				
			||||||
      SM_LINE_TABLE = 5,
 | 
					      SM_LINE_TABLE = 5
 | 
				
			||||||
      /// \brief Describes one header file info [isImport, DirInfo, NumIncludes]
 | 
					 | 
				
			||||||
      /// ControllingMacro is optional.
 | 
					 | 
				
			||||||
      SM_HEADER_FILE_INFO = 6
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// \brief Record types used within a preprocessor block.
 | 
					    /// \brief Record types used within a preprocessor block.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ public:
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Receives a HeaderFileInfo entry.
 | 
					  /// \brief Receives a HeaderFileInfo entry.
 | 
				
			||||||
  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {}
 | 
					  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Receives __COUNTER__ value.
 | 
					  /// \brief Receives __COUNTER__ value.
 | 
				
			||||||
  virtual void ReadCounter(unsigned Value) {}
 | 
					  virtual void ReadCounter(unsigned Value) {}
 | 
				
			||||||
| 
						 | 
					@ -130,7 +130,7 @@ public:
 | 
				
			||||||
                                    FileID PCHBufferID,
 | 
					                                    FileID PCHBufferID,
 | 
				
			||||||
                                    llvm::StringRef OriginalFileName,
 | 
					                                    llvm::StringRef OriginalFileName,
 | 
				
			||||||
                                    std::string &SuggestedPredefines);
 | 
					                                    std::string &SuggestedPredefines);
 | 
				
			||||||
  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
 | 
					  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
 | 
				
			||||||
  virtual void ReadCounter(unsigned Value);
 | 
					  virtual void ReadCounter(unsigned Value);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -214,9 +214,10 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
 | 
					  void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  typedef std::vector<HeaderFileInfo>::iterator header_file_iterator;
 | 
					  typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
 | 
				
			||||||
  header_file_iterator header_file_begin() { return FileInfo.begin(); }
 | 
					  header_file_iterator header_file_begin() const { return FileInfo.begin(); }
 | 
				
			||||||
  header_file_iterator header_file_end() { return FileInfo.end(); }
 | 
					  header_file_iterator header_file_end() const { return FileInfo.end(); }
 | 
				
			||||||
 | 
					  unsigned header_file_size() const { return FileInfo.size(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Used by PCHReader.
 | 
					  // Used by PCHReader.
 | 
				
			||||||
  void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
 | 
					  void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -300,8 +300,10 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
 | 
					void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
 | 
				
			||||||
  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
 | 
					                                      unsigned ID) {
 | 
				
			||||||
 | 
					  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
 | 
				
			||||||
 | 
					  ++NumHeaderInfos;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PCHValidator::ReadCounter(unsigned Value) {
 | 
					void PCHValidator::ReadCounter(unsigned Value) {
 | 
				
			||||||
| 
						 | 
					@ -850,17 +852,6 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
 | 
				
			||||||
        return Failure;
 | 
					        return Failure;
 | 
				
			||||||
      break;
 | 
					      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_FILE_ENTRY:
 | 
				
			||||||
    case pch::SM_SLOC_BUFFER_ENTRY:
 | 
					    case pch::SM_SLOC_BUFFER_ENTRY:
 | 
				
			||||||
    case pch::SM_SLOC_INSTANTIATION_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())
 | 
					      const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
 | 
				
			||||||
        .setHasLineDirectives();
 | 
					        .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;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -573,7 +573,6 @@ void PCHWriter::WriteBlockInfoBlock() {
 | 
				
			||||||
  RECORD(SM_SLOC_BUFFER_BLOB);
 | 
					  RECORD(SM_SLOC_BUFFER_BLOB);
 | 
				
			||||||
  RECORD(SM_SLOC_INSTANTIATION_ENTRY);
 | 
					  RECORD(SM_SLOC_INSTANTIATION_ENTRY);
 | 
				
			||||||
  RECORD(SM_LINE_TABLE);
 | 
					  RECORD(SM_LINE_TABLE);
 | 
				
			||||||
  RECORD(SM_HEADER_FILE_INFO);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Preprocessor Block.
 | 
					  // Preprocessor Block.
 | 
				
			||||||
  BLOCK(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::VBR, 8)); // Include location
 | 
				
			||||||
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
 | 
					  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
 | 
				
			||||||
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
 | 
					  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
 | 
					  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
 | 
				
			||||||
  return Stream.EmitAbbrev(Abbrev);
 | 
					  return Stream.EmitAbbrev(Abbrev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1019,20 +1023,6 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
 | 
				
			||||||
    Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
 | 
					    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
 | 
					  // Write out the source location entry table. We skip the first
 | 
				
			||||||
  // entry, which is always the same dummy entry.
 | 
					  // entry, which is always the same dummy entry.
 | 
				
			||||||
  std::vector<uint32_t> SLocEntryOffsets;
 | 
					  std::vector<uint32_t> SLocEntryOffsets;
 | 
				
			||||||
| 
						 | 
					@ -1069,6 +1059,16 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
 | 
				
			||||||
        // The source location entry is a file. The blob associated
 | 
					        // The source location entry is a file. The blob associated
 | 
				
			||||||
        // with this entry is the file name.
 | 
					        // 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.
 | 
					        // Turn the file name into an absolute path, if it isn't already.
 | 
				
			||||||
        const char *Filename = Content->Entry->getName();
 | 
					        const char *Filename = Content->Entry->getName();
 | 
				
			||||||
        llvm::sys::Path FilePath(Filename, strlen(Filename));
 | 
					        llvm::sys::Path FilePath(Filename, strlen(Filename));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					/* Helper for the headermap.m test */
 | 
				
			||||||
 | 
					int x = 17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue