<br><br><div class="gmail_quote">On Fri Dec 05 2014 at 3:36:24 AM Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Dec  4 20:33:27 2014<br>
New Revision: 223443<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223443&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=223443&view=rev</a><br>
Log:<br>
[modules] Instead of storing absolute paths in a .pcm file, store the path to<br>
the root of the module and use paths relative to that directory wherever<br>
possible. This is a step towards allowing explicit modules to be relocated<br>
without being rebuilt, which is important for some kinds of distributed builds,<br>
for good paths in diagnostics, and for appropriate .d output.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h<br>
    cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h<br>
    cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h<br>
    cfe/trunk/include/clang/<u></u>Serialization/Module.h<br>
    cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp<br>
    cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h<br>
    cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/<u></u>ASTBitCodes.h?rev=223443&r1=<u></u>223442&r2=223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h Thu Dec  4 20:33:27 2014<br>
@@ -291,7 +291,10 @@ namespace clang {<br>
       MODULE_MAP_FILE = 14,<br>
<br>
       /// \brief Record code for the signature that identifiers this AST file.<br>
-      SIGNATURE = 15<br>
+      SIGNATURE = 15,<br>
+<br>
+      /// \brief Record code for the module build directory.<br>
+      MODULE_DIRECTORY = 16,<br>
     };<br>
<br>
     /// \brief Record types that occur within the input-files block<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/ASTReader.<u></u>h?rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h Thu Dec  4 20:33:27 2014<br>
@@ -1113,12 +1113,11 @@ private:<br>
   serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,<br>
                                         bool Complain = true);<br>
<br>
-  /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take<br>
-  /// into account all the necessary relocations.<br>
-  const FileEntry *getFileEntry(StringRef filename);<br>
-<br>
-  void MaybeAddSystemRootToFilename(<u></u>ModuleFile &M, std::string &Filename);<br>
+public:<br>
+  void ResolveImportedPath(ModuleFile &M, std::string &Filename);<br>
+  static void ResolveImportedPath(std::<u></u>string &Filename, StringRef Prefix);<br>
<br>
+private:<br>
   struct ImportedModule {<br>
     ModuleFile *Mod;<br>
     ModuleFile *ImportedBy;<br>
@@ -1141,7 +1140,7 @@ private:<br>
                                  const ModuleFile *ImportedBy,<br>
                                  unsigned ClientLoadCapabilities);<br>
   ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);<br>
-  bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);<br>
+  bool ParseLineTable(ModuleFile &F, const RecordData &Record);<br>
   bool ReadSourceManagerBlock(<u></u>ModuleFile &F);<br>
   llvm::BitstreamCursor &SLocCursorForID(int ID);<br>
   SourceLocation getImportLocation(ModuleFile *F);<br>
@@ -2045,6 +2044,9 @@ public:<br>
   // \brief Read a string<br>
   static std::string ReadString(const RecordData &Record, unsigned &Idx);<br>
<br>
+  // \brief Read a path<br>
+  std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);<br>
+<br>
   /// \brief Read a version tuple.<br>
   static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);<br>
<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/ASTWriter.<u></u>h?rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h Thu Dec  4 20:33:27 2014<br>
@@ -111,7 +111,10 @@ private:<br>
<br>
   /// \brief The module we're currently writing, if any.<br>
   Module *WritingModule;<br>
-<br>
+<br>
+  /// \brief The base directory for any relative paths we emit.<br>
+  std::string BaseDirectory;<br>
+<br>
   /// \brief Indicates when the AST writing is actively performing<br>
   /// serialization, rather than just queueing updates.<br>
   bool WritingAST;<br>
@@ -457,13 +460,11 @@ private:<br>
                          StringRef isysroot, const std::string &OutputFile);<br>
   void WriteInputFiles(SourceManager &SourceMgr,<br>
                        HeaderSearchOptions &HSOpts,<br>
-                       StringRef isysroot,<br>
                        bool Modules);<br>
   void WriteSourceManagerBlock(<u></u>SourceManager &SourceMgr,<br>
-                               const Preprocessor &PP,<br>
-                               StringRef isysroot);<br>
+                               const Preprocessor &PP);<br>
   void WritePreprocessor(const Preprocessor &PP, bool IsModule);<br>
-  void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot);<br>
+  void WriteHeaderSearch(const HeaderSearch &HS);<br>
   void WritePreprocessorDetail(<u></u>PreprocessingRecord &PPRec);<br>
   void WriteSubmodules(Module *WritingModule);<br>
<br>
@@ -539,7 +540,8 @@ public:<br>
   /// writing a precompiled header.<br>
   ///<br>
   /// \param isysroot if non-empty, write a relocatable file whose headers<br>
-  /// are relative to the given system root.<br>
+  /// are relative to the given system root. If we're writing a module, its<br>
+  /// build directory will be used in preference to this if both are available.<br>
   void WriteAST(Sema &SemaRef,<br>
                 const std::string &OutputFile,<br>
                 Module *WritingModule, StringRef isysroot,<br>
@@ -686,6 +688,17 @@ public:<br>
   /// \brief Add a string to the given record.<br>
   void AddString(StringRef Str, RecordDataImpl &Record);<br>
<br>
+  /// \brief Convert a path from this build process into one that is appropriate<br>
+  /// for emission in the module file.<br>
+  bool PreparePathForOutput(<u></u>SmallVectorImpl<char> &Path);<br>
+<br>
+  /// \brief Add a path to the given record.<br>
+  void AddPath(StringRef Path, RecordDataImpl &Record);<br>
+<br>
+  /// \brief Emit the current record with the given path as a blob.<br>
+  void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,<br>
+                          StringRef Path);<br>
+<br>
   /// \brief Add a version tuple to the given record<br>
   void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);<br>
<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/Module.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/Module.h?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/Module.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/Module.h Thu Dec  4 20:33:27 2014<br>
@@ -125,6 +125,9 @@ public:<br>
   /// \brief The name of the module.<br>
   std::string ModuleName;<br>
<br>
+  /// \brief The base directory of the module.<br>
+  std::string BaseDirectory;<br>
+<br>
   std::string getTimestampFilename() const {<br>
     return FileName + ".timestamp";<br>
   }<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/ASTReader.cpp?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp Thu Dec  4 20:33:27 2014<br>
@@ -1029,7 +1029,7 @@ void ASTReader::Error(unsigned DiagID,<br>
 /// \brief Read the line table in the source manager block.<br>
 /// \returns true if there was an error.<br>
 bool ASTReader::ParseLineTable(<u></u>ModuleFile &F,<br>
-                               SmallVectorImpl<uint64_t> &Record) {<br>
+                               const RecordData &Record) {<br>
   unsigned Idx = 0;<br>
   LineTableInfo &LineTable = SourceMgr.getLineTable();<br>
<br>
@@ -1037,10 +1037,7 @@ bool ASTReader::ParseLineTable(<u></u>ModuleFil<br>
   std::map<int, int> FileIDs;<br>
   for (int I = 0, N = Record[Idx++]; I != N; ++I) {<br>
     // Extract the file name<br>
-    unsigned FilenameLen = Record[Idx++];<br>
-    std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);<br>
-    Idx += FilenameLen;<br>
-    MaybeAddSystemRootToFilename(<u></u>F, Filename);<br>
+    auto Filename = ReadPath(F, Record, Idx);<br>
     FileIDs[I] = LineTable.<u></u>getLineTableFilenameID(<u></u>Filename);<br>
   }<br>
<br>
@@ -1483,11 +1480,11 @@ ASTReader::<u></u>getGlobalPreprocessedEntityID<br>
 unsigned HeaderFileInfoTrait::<u></u>ComputeHash(internal_key_ref ikey) {<br>
   return llvm::hash_combine(ikey.Size, ikey.ModTime);<br>
 }<br>
-<br>
+<br>
 HeaderFileInfoTrait::internal_<u></u>key_type<br>
 HeaderFileInfoTrait::<u></u>GetInternalKey(const FileEntry *FE) {<br>
   internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),<br>
-                             FE->getName() };<br>
+                             FE->getName(), /*Imported*/false };<br>
   return ikey;<br>
 }<br>
<br>
@@ -1495,14 +1492,24 @@ bool HeaderFileInfoTrait::EqualKey(<u></u>inter<br>
   if (a.Size != b.Size || a.ModTime != b.ModTime)<br>
     return false;<br>
<br>
-  if (strcmp(a.Filename, b.Filename) == 0)<br>
+  if (llvm::sys::path::is_absolute(<u></u>a.Filename) &&<br>
+      strcmp(a.Filename, b.Filename) == 0)<br>
     return true;<br>
<br>
   // Determine whether the actual files are equivalent.<br>
   FileManager &FileMgr = Reader.getFileManager();<br>
-  const FileEntry *FEA = FileMgr.getFile(a.Filename);<br>
-  const FileEntry *FEB = FileMgr.getFile(b.Filename);<br>
-  return (FEA && FEA == FEB);<br>
+  auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {<br>
+    if (!Key.Imported)<br>
+      return FileMgr.getFile(Key.Filename);<br>
+<br>
+    std::string Resolved = Key.Filename;<br>
+    Reader.ResolveImportedPath(M, Resolved);<br>
+    return FileMgr.getFile(Resolved);<br>
+  };<br>
+<br>
+  const FileEntry *FEA = GetFile(a);<br>
+  const FileEntry *FEB = GetFile(b);<br>
+  return FEA && FEA == FEB;<br>
 }<br>
<br>
 std::pair<unsigned, unsigned><br>
@@ -1520,6 +1527,7 @@ HeaderFileInfoTrait::ReadKey(<u></u>const unsig<br>
   ikey.Size = off_t(endian::readNext<uint64_<u></u>t, little, unaligned>(d));<br>
   ikey.ModTime = time_t(endian::readNext<<u></u>uint64_t, little, unaligned>(d));<br>
   ikey.Filename = (const char *)d;<br>
+  ikey.Imported = true;<br>
   return ikey;<br>
 }<br>
<br>
@@ -1559,11 +1567,13 @@ HeaderFileInfoTrait::ReadData(<u></u>internal_k<br>
       FileManager &FileMgr = Reader.getFileManager();<br>
       ModuleMap &ModMap =<br>
           Reader.getPreprocessor().<u></u>getHeaderSearchInfo().<u></u>getModuleMap();<br>
-      // FIXME: This is wrong. We should track the filename as written; this<br>
-      // information should be propagated through the SUBMODULE_HEADER etc<br>
-      // records rather than from here.<br>
+      // FIXME: This information should be propagated through the<br>
+      // SUBMODULE_HEADER etc records rather than from here.<br>
       // FIXME: We don't ever mark excluded headers.<br>
-      Module::Header H = { key.Filename, FileMgr.getFile(key.Filename) };<br>
+      std::string Filename = key.Filename;<br>
+      if (key.Imported)<br>
+        Reader.ResolveImportedPath(M, Filename);<br>
+      Module::Header H = { key.Filename, FileMgr.getFile(Filename) };<br>
       ModMap.addHeader(Mod, H, HFI.getHeaderRole());<br>
     }<br>
   }<br>
@@ -2084,14 +2094,14 @@ ASTReader::readInputFileInfo(<u></u>ModuleFile<br>
   off_t StoredSize;<br>
   time_t StoredTime;<br>
   bool Overridden;<br>
-<br>
+<br>
   assert(Record[0] == ID && "Bogus stored ID or offset");<br>
   StoredSize = static_cast<off_t>(Record[1]);<br>
   StoredTime = static_cast<time_t>(Record[2])<u></u>;<br>
   Overridden = static_cast<bool>(Record[3]);<br>
   Filename = Blob;<br>
-  MaybeAddSystemRootToFilename(<u></u>F, Filename);<br>
-<br>
+  ResolveImportedPath(F, Filename);<br>
+<br>
   InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };<br>
   return R;<br>
 }<br>
@@ -2229,46 +2239,24 @@ InputFile ASTReader::getInputFile(Module<br>
   return IF;<br>
 }<br>
<br>
-const FileEntry *ASTReader::getFileEntry(<u></u>StringRef filenameStrRef) {<br>
-  ModuleFile &M = ModuleMgr.getPrimaryModule();<br>
-  std::string Filename = filenameStrRef;<br>
-  MaybeAddSystemRootToFilename(<u></u>M, Filename);<br>
-  const FileEntry *File = FileMgr.getFile(Filename);<br>
-  if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() &&<br>
-      M.OriginalDir != CurrentDir) {<br>
-    std::string resolved = resolveFileRelativeToOriginalD<u></u>ir(Filename,<br>
-                                                            M.OriginalDir,<br>
-                                                            CurrentDir);<br>
-    if (!resolved.empty())<br>
-      File = FileMgr.getFile(resolved);<br>
-  }<br>
-<br>
-  return File;<br>
+/// \brief If we are loading a relocatable PCH or module file, and the filename<br>
+/// is not an absolute path, add the system or module root to the beginning of<br>
+/// the file name.<br>
+void ASTReader::<u></u>ResolveImportedPath(ModuleFile &M, std::string &Filename) {<br>
+  // Resolve relative to the base directory, if we have one.<br>
+  if (!M.BaseDirectory.empty())<br>
+    return ResolveImportedPath(Filename, M.BaseDirectory);<br>
 }<br>
<br>
-/// \brief If we are loading a relocatable PCH file, and the filename is<br>
-/// not an absolute path, add the system root to the beginning of the file<br>
-/// name.<br>
-void ASTReader::<u></u>MaybeAddSystemRootToFilename(<u></u>ModuleFile &M,<br>
-                                             std::string &Filename) {<br>
-  // If this is not a relocatable PCH file, there's nothing to do.<br>
-  if (!M.RelocatablePCH)<br>
-    return;<br>
-<br>
+void ASTReader::<u></u>ResolveImportedPath(std::<u></u>string &Filename, StringRef Prefix) {<br>
   if (Filename.empty() || llvm::sys::path::is_absolute(<u></u>Filename))<br>
     return;<br>
<br>
-  if (isysroot.empty()) {<br>
-    // If no system root was given, default to '/'<br>
-    Filename.insert(Filename.<u></u>begin(), '/');<br>
-    return;<br>
-  }<br>
-<br>
-  unsigned Length = isysroot.size();<br>
-  if (isysroot[Length - 1] != '/')<br>
+  unsigned Length = Prefix.size();<br>
+  if (Prefix[Length - 1] != '/')<br>
     Filename.insert(Filename.<u></u>begin(), '/');<br>
<br>
-  Filename.insert(Filename.<u></u>begin(), isysroot.begin(), isysroot.end());<br>
+  Filename.insert(Filename.<u></u>begin(), Prefix.begin(), Prefix.end());</blockquote><div><br></div><div>Isn't that basically llvm::sys::path::append?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 }<br>
<br>
 ASTReader::ASTReadResult<br>
@@ -2388,6 +2376,9 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
       }<br>
<br>
       F.RelocatablePCH = Record[4];<br>
+      // Relative paths in a relocatable PCH are relative to our sysroot.<br>
+      if (F.RelocatablePCH)<br>
+        F.BaseDirectory = isysroot.empty() ? "/" : isysroot;<br>
<br>
       const std::string &CurBranch = getClangFullRepositoryVersion(<u></u>);<br>
       StringRef ASTBranch = Blob;<br>
@@ -2418,10 +2409,7 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
         off_t StoredSize = (off_t)Record[Idx++];<br>
         time_t StoredModTime = (time_t)Record[Idx++];<br>
         ASTFileSignature StoredSignature = Record[Idx++];<br>
-        unsigned Length = Record[Idx++];<br>
-        SmallString<128> ImportedFile(Record.begin() + Idx,<br>
-                                      Record.begin() + Idx + Length);<br>
-        Idx += Length;<br>
+        auto ImportedFile = ReadPath(F, Record, Idx);<br>
<br>
         // Load the AST file.<br>
         switch(ReadASTCore(<u></u>ImportedFile, ImportedKind, ImportLoc, &F, Loaded,<br>
@@ -2505,7 +2493,7 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
       F.OriginalSourceFileID = FileID::get(Record[0]);<br>
       F.ActualOriginalSourceFileName = Blob;<br>
       F.OriginalSourceFileName = F.<u></u>ActualOriginalSourceFileName;<br>
-      MaybeAddSystemRootToFilename(<u></u>F, F.OriginalSourceFileName);<br>
+      ResolveImportedPath(F, F.OriginalSourceFileName);<br>
       break;<br>
<br>
     case ORIGINAL_FILE_ID:<br>
@@ -2522,6 +2510,10 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
         Listener->ReadModuleName(F.<u></u>ModuleName);<br>
       break;<br>
<br>
+    case MODULE_DIRECTORY:<br>
+      F.BaseDirectory = Blob;<br>
+      break;<br>
+<br>
     case MODULE_MAP_FILE:<br>
       if (ASTReadResult Result =<br>
               ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))<br>
@@ -3342,7 +3334,7 @@ ASTReader::<u></u>ReadModuleMapFileBlock(Record<br>
                                   const ModuleFile *ImportedBy,<br>
                                   unsigned ClientLoadCapabilities) {<br>
   unsigned Idx = 0;<br>
-  F.ModuleMapPath = ReadString(Record, Idx);<br>
+  F.ModuleMapPath = ReadPath(F, Record, Idx);<br>
<br>
   if (F.Kind == MK_ExplicitModule) {<br>
     // For an explicitly-loaded module, we don't care whether the original<br>
@@ -3389,7 +3381,7 @@ ASTReader::<u></u>ReadModuleMapFileBlock(Record<br>
     llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps;<br>
     for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {<br>
       // FIXME: we should use input files rather than storing names.<br>
-      std::string Filename = ReadString(Record, Idx);<br>
+      std::string Filename = ReadPath(F, Record, Idx);<br>
       const FileEntry *F =<br>
           FileMgr.getFile(Filename, false, false);<br>
       if (F == nullptr) {<br>
@@ -4256,6 +4248,7 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
<br>
   // Scan for ORIGINAL_FILE inside the control block.<br>
   RecordData Record;<br>
+  std::string ModuleDir;<br>
   while (1) {<br>
     llvm::BitstreamEntry Entry = Stream.<u></u>advanceSkippingSubblocks();<br>
     if (Entry.Kind == llvm::BitstreamEntry::<u></u>EndBlock)<br>
@@ -4280,9 +4273,14 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
     case MODULE_NAME:<br>
       Listener.ReadModuleName(Blob);<br>
       break;<br>
+    case MODULE_DIRECTORY:<br>
+      ModuleDir = Blob;<br>
+      break;<br>
     case MODULE_MAP_FILE: {<br>
       unsigned Idx = 0;<br>
-      Listener.ReadModuleMapFile(<u></u>ReadString(Record, Idx));<br>
+      auto Path = ReadString(Record, Idx);<br>
+      ResolveImportedPath(Path, ModuleDir);<br>
+      Listener.ReadModuleMapFile(<u></u>Path);<br>
       break;<br>
     }<br>
     case LANGUAGE_OPTIONS:<br>
@@ -4344,7 +4342,10 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
         switch ((InputFileRecordTypes)Cursor.<u></u>readRecord(Code, Record, &Blob)) {<br>
         case INPUT_FILE:<br>
           bool Overridden = static_cast<bool>(Record[3]);<br>
-          shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden);<br>
+          std::string Filename = Blob;<br>
+          ResolveImportedPath(Filename, ModuleDir);<br>
+          shouldContinue =<br>
+              Listener.visitInputFile(<u></u>Filename, isSystemFile, Overridden);<br>
           break;<br>
         }<br>
         if (!shouldContinue)<br>
@@ -4361,11 +4362,9 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
       while (Idx < N) {<br>
         // Read information about the AST file.<br>
         Idx += 5; // ImportLoc, Size, ModTime, Signature<br>
-        unsigned Length = Record[Idx++];<br>
-        SmallString<128> ImportedFile(Record.begin() + Idx,<br>
-                                      Record.begin() + Idx + Length);<br>
-        Idx += Length;<br>
-        Listener.visitImport(<u></u>ImportedFile);<br>
+        std::string Filename = ReadString(Record, Idx);<br>
+        ResolveImportedPath(Filename, ModuleDir);<br>
+        Listener.visitImport(Filename)<u></u>;<br>
       }<br>
       break;<br>
     }<br>
@@ -8050,6 +8049,13 @@ std::string ASTReader::ReadString(const<br>
   return Result;<br>
 }<br>
<br>
+std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,<br>
+                                unsigned &Idx) {<br>
+  std::string Filename = ReadString(Record, Idx);<br>
+  ResolveImportedPath(F, Filename);<br>
+  return Filename;<br>
+}<br>
+<br>
 VersionTuple ASTReader::ReadVersionTuple(<u></u>const RecordData &Record,<br>
                                          unsigned &Idx) {<br>
   unsigned Major = Record[Idx++];<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/<u></u>ASTReaderInternals.h?rev=<u></u>223443&r1=223442&r2=223443&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h Thu Dec  4 20:33:27 2014<br>
@@ -194,8 +194,8 @@ typedef llvm::OnDiskChainedHashTable<<u></u>AST<br>
 ///<br>
 /// The on-disk hash table contains a mapping from each header path to<br>
 /// information about that header (how many times it has been included, its<br>
-/// controlling macro, etc.). Note that we actually hash based on the<br>
-/// filename, and support "deep" comparisons of file names based on current<br>
+/// controlling macro, etc.). Note that we actually hash based on the size<br>
+/// and mtime, and support "deep" comparisons of file names based on current<br>
 /// inode numbers, so that the search can cope with non-normalized path names<br>
 /// and symlinks.<br>
 class HeaderFileInfoTrait {<br>
@@ -211,6 +211,7 @@ public:<br>
     off_t Size;<br>
     time_t ModTime;<br>
     const char *Filename;<br>
+    bool Imported;<br>
   };<br>
   typedef const internal_key_type &internal_key_ref;<br>
<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/ASTWriter.cpp?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp Thu Dec  4 20:33:27 2014<br>
@@ -1063,33 +1063,44 @@ void ASTWriter::<u></u>WriteBlockInfoBlock() {<br>
 ///<br>
 /// \param Filename the file name to adjust.<br>
 ///<br>
-/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and<br>
-/// the returned filename will be adjusted by this system root.<br>
+/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and<br>
+/// the returned filename will be adjusted by this root directory.<br>
 ///<br>
 /// \returns either the original filename (if it needs no adjustment) or the<br>
 /// adjusted filename (which points into the @p Filename parameter).<br>
 static const char *<br>
-<u></u>adjustFilenameForRelocatablePC<u></u>H(const char *Filename, StringRef isysroot) {<br>
+<u></u>adjustFilenameForRelocatableAS<u></u>T(const char *Filename, StringRef BaseDir) {<br>
   assert(Filename && "No file name to adjust?");<br>
<br>
-  if (isysroot.empty())<br>
+  if (BaseDir.empty())<br>
     return Filename;<br>
<br>
   // Verify that the filename and the system root have the same prefix.<br>
   unsigned Pos = 0;<br>
-  for (; Filename[Pos] && Pos < isysroot.size(); ++Pos)<br>
-    if (Filename[Pos] != isysroot[Pos])<br>
+  for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)<br>
+    if (Filename[Pos] != BaseDir[Pos])<br>
       return Filename; // Prefixes don't match.<br>
<br>
   // We hit the end of the filename before we hit the end of the system root.<br>
   if (!Filename[Pos])<br>
     return Filename;<br>
<br>
-  // If the file name has a '/' at the current position, skip over the '/'.<br>
-  // We distinguish sysroot-based includes from absolute includes by the<br>
-  // absence of '/' at the beginning of sysroot-based includes.<br>
-  if (Filename[Pos] == '/')<br>
+  // If there's not a path separator at the end of the base directory nor<br>
+  // immediately after it, then this isn't within the base directory.<br>
+  if (!llvm::sys::path::is_<u></u>separator(Filename[Pos])) {<br>
+    if (!llvm::sys::path::is_<u></u>separator(BaseDir.back()))<br>
+      return Filename;<br>
+  } else {<br>
+    // If the file name has a '/' at the current position, skip over the '/'.<br>
+    // We distinguish relative paths from absolute paths by the<br>
+    // absence of '/' at the beginning of relative paths.<br>
+    //<br>
+    // FIXME: This is wrong. We distinguish them by asking if the path is<br>
+    // absolute, which isn't the same thing. And there might be multiple '/'s<br>
+    // in a row. Use a better mechanism to indicate whether we have emitted an<br>
+    // absolute or relative path.<br>
     ++Pos;<br>
+  }<br>
<br>
   return Filename + Pos;<br>
 }<br>
@@ -1126,6 +1137,8 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
   Record.push_back(VERSION_<u></u>MINOR);<br>
   Record.push_back(CLANG_<u></u>VERSION_MAJOR);<br>
   Record.push_back(CLANG_<u></u>VERSION_MINOR);<br>
+  assert((!WritingModule || isysroot.empty()) &&<br>
+         "writing module as a relocatable PCH?");<br>
   Record.push_back(!isysroot.<u></u>empty());<br>
   Record.push_back(<u></u>ASTHasCompilerErrors);<br>
   Stream.EmitRecordWithBlob(<u></u>MetadataAbbrevCode, Record,<br>
@@ -1136,8 +1149,8 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
   Record.push_back(getSignature(<u></u>));<br>
   Stream.EmitRecord(SIGNATURE, Record);<br>
<br>
-  // Module name<br>
   if (WritingModule) {<br>
+    // Module name<br>
     BitCodeAbbrev *Abbrev = new BitCodeAbbrev();<br>
     Abbrev->Add(BitCodeAbbrevOp(<u></u>MODULE_NAME));<br>
     Abbrev->Add(BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // Name<br>
@@ -1147,25 +1160,42 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
     Stream.EmitRecordWithBlob(<u></u>AbbrevCode, Record, WritingModule->Name);<br>
   }<br>
<br>
+  if (WritingModule && WritingModule->Directory) {<br>
+    // Module directory.<br>
+    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();<br>
+    Abbrev->Add(BitCodeAbbrevOp(<u></u>MODULE_DIRECTORY));<br>
+    Abbrev->Add(BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // Directory<br>
+    unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);<br>
+    RecordData Record;<br>
+    Record.push_back(MODULE_<u></u>DIRECTORY);<br>
+<br>
+    SmallString<128> BaseDir(WritingModule-><u></u>Directory->getName());<br>
+    Context.getSourceManager().<u></u>getFileManager().<u></u>FixupRelativePath(BaseDir);<br>
+    llvm::sys::fs::make_absolute(<u></u>BaseDir);<br>
+    Stream.EmitRecordWithBlob(<u></u>AbbrevCode, Record, BaseDir);<br>
+<br>
+    // Write out all other paths relative to the base directory if possible.<br>
+    BaseDirectory.assign(BaseDir.<u></u>begin(), BaseDir.end());<br>
+  } else if (!isysroot.empty()) {<br>
+    // Write out paths relative to the sysroot if possible.<br>
+    BaseDirectory = isysroot;<br>
+  }<br>
+<br>
   // Module map file<br>
   if (WritingModule) {<br>
     Record.clear();<br>
-    auto addModMap = [&](const FileEntry *F) {<br>
-      SmallString<128> ModuleMap(F->getName());<br>
-      llvm::sys::fs::make_absolute(<u></u>ModuleMap);<br>
-      AddString(ModuleMap.str(), Record);<br>
-    };<br>
<br>
     auto &Map = PP.getHeaderSearchInfo().<u></u>getModuleMap();<br>
<br>
     // Primary module map file.<br>
-    addModMap(Map.<u></u>getModuleMapFileForUniquing(<u></u>WritingModule));<br>
+    AddPath(Map.<u></u>getModuleMapFileForUniquing(<u></u>WritingModule)->getName(), Record);<br>
<br>
     // Additional module map files.<br>
-    if (auto *AdditionalModMaps = Map.<u></u>getAdditionalModuleMapFiles(<u></u>WritingModule)) {<br>
+    if (auto *AdditionalModMaps =<br>
+            Map.<u></u>getAdditionalModuleMapFiles(<u></u>WritingModule)) {<br>
       Record.push_back(<u></u>AdditionalModMaps->size());<br>
       for (const FileEntry *F : *AdditionalModMaps)<br>
-        addModMap(F);<br>
+        AddPath(F->getName(), Record);<br>
     } else {<br>
       Record.push_back(0);<br>
     }<br>
@@ -1189,9 +1219,7 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
       Record.push_back((*M)->File-><u></u>getSize());<br>
       Record.push_back((*M)->File-><u></u>getModificationTime());<br>
       Record.push_back((*M)-><u></u>Signature);<br>
-      const std::string &FileName = (*M)->FileName;<br>
-      Record.push_back(FileName.<u></u>size());<br>
-      Record.append(FileName.begin()<u></u>, FileName.end());<br>
+      AddPath((*M)->FileName, Record);<br>
     }<br>
     Stream.EmitRecord(IMPORTS, Record);<br>
   }<br>
@@ -1339,17 +1367,10 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
     FileAbbrev->Add(<u></u>BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // File name<br>
     unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);<br>
<br>
-    SmallString<128> MainFilePath(MainFile-><u></u>getName());<br>
-<br>
-    llvm::sys::fs::make_absolute(<u></u>MainFilePath);<br>
-<br>
-    const char *MainFileNameStr = MainFilePath.c_str();<br>
-    MainFileNameStr = adjustFilenameForRelocatablePC<u></u>H(MainFileNameStr,<br>
-                                                      isysroot);<br>
     Record.clear();<br>
     Record.push_back(ORIGINAL_<u></u>FILE);<br>
     Record.push_back(SM.<u></u>getMainFileID().<u></u>getOpaqueValue());<br>
-    Stream.EmitRecordWithBlob(<u></u>FileAbbrevCode, Record, MainFileNameStr);<br>
+    EmitRecordWithPath(<u></u>FileAbbrevCode, Record, MainFile->getName());<br>
   }<br>
<br>
   Record.clear();<br>
@@ -1375,7 +1396,6 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
<br>
   WriteInputFiles(Context.<u></u>SourceMgr,<br>
                   PP.getHeaderSearchInfo().<u></u>getHeaderSearchOpts(),<br>
-                  isysroot,<br>
                   PP.getLangOpts().Modules);<br>
   Stream.ExitBlock();<br>
 }<br>
@@ -1391,7 +1411,6 @@ namespace  {<br>
<br>
 void ASTWriter::WriteInputFiles(<u></u>SourceManager &SourceMgr,<br>
                                 HeaderSearchOptions &HSOpts,<br>
-                                StringRef isysroot,<br>
                                 bool Modules) {<br>
   using namespace llvm;<br>
   Stream.EnterSubblock(INPUT_<u></u>FILES_BLOCK_ID, 4);<br>
@@ -1462,23 +1481,8 @@ void ASTWriter::WriteInputFiles(<u></u>SourceMa<br>
     // Whether this file was overridden.<br>
     Record.push_back(Entry.<u></u>BufferOverridden);<br>
<br>
-    // Turn the file name into an absolute path, if it isn't already.<br>
-    const char *Filename = Entry.File->getName();<br>
-    SmallString<128> FilePath(Filename);<br>
-<br>
-    // Ask the file manager to fixup the relative path for us. This will<br>
-    // honor the working directory.<br>
-    SourceMgr.getFileManager().<u></u>FixupRelativePath(FilePath);<br>
-<br>
-    // FIXME: This call to make_absolute shouldn't be necessary, the<br>
-    // call to FixupRelativePath should always return an absolute path.<br>
-    llvm::sys::fs::make_absolute(<u></u>FilePath);<br>
-    Filename = FilePath.c_str();<br>
-<br>
-    Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
-<br>
-    Stream.EmitRecordWithBlob(<u></u>IFAbbrevCode, Record, Filename);<br>
-  }<br>
+    EmitRecordWithPath(<u></u>IFAbbrevCode, Record, Entry.File->getName());<br>
+  }<br>
<br>
   Stream.ExitBlock();<br>
<br>
@@ -1588,6 +1592,9 @@ namespace {<br>
       // The hash is based only on size/time of the file, so that the reader can<br>
       // match even when symlinking or excess path elements ("foo/../", "../")<br>
       // change the form of the name. However, complete path is still the key.<br>
+      //<br>
+      // FIXME: Using the mtime here will cause problems for explicit module<br>
+      // imports.<br>
       return llvm::hash_combine(key.FE-><u></u>getSize(),<br>
                                 key.FE->getModificationTime())<u></u>;<br>
     }<br>
@@ -1668,7 +1675,7 @@ namespace {<br>
 /// \brief Write the header search block for the list of files that<br>
 ///<br>
 /// \param HS The header search structure to save.<br>
-void ASTWriter::WriteHeaderSearch(<u></u>const HeaderSearch &HS, StringRef isysroot) {<br>
+void ASTWriter::WriteHeaderSearch(<u></u>const HeaderSearch &HS) {<br>
   SmallVector<const FileEntry *, 16> FilesByUID;<br>
   HS.getFileMgr().<u></u>GetUniqueIDMapping(FilesByUID)<u></u>;<br>
<br>
@@ -1692,17 +1699,16 @@ void ASTWriter::WriteHeaderSearch(<u></u>const<br>
         (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))<br>
       continue;<br>
<br>
-    // Turn the file name into an absolute path, if it isn't already.<br>
+    // Massage the file path into an appropriate form.<br>
     const char *Filename = File->getName();<br>
-    Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
-<br>
-    // If we performed any translation on the file name at all, we need to<br>
-    // save this string, since the generator will refer to it later.<br>
-    if (Filename != File->getName()) {<br>
-      Filename = strdup(Filename);<br>
+    SmallString<128> FilenameTmp(Filename);<br>
+    if (PreparePathForOutput(<u></u>FilenameTmp)) {<br>
+      // If we performed any translation on the file name at all, we need to<br>
+      // save this string, since the generator will refer to it later.<br>
+      Filename = strdup(FilenameTmp.c_str());<br>
       SavedStrings.push_back(<u></u>Filename);<br>
     }<br>
-<br>
+<br>
     HeaderFileInfoTrait::key_type key = { File, Filename };<br>
     Generator.insert(key, HFI, GeneratorTrait);<br>
     ++NumHeaderSearchEntries;<br>
@@ -1752,8 +1758,7 @@ void ASTWriter::WriteHeaderSearch(<u></u>const<br>
 /// errors), we probably won't have to create file entries for any of<br>
 /// the files in the AST.<br>
 void ASTWriter::<u></u>WriteSourceManagerBlock(<u></u>SourceManager &SourceMgr,<br>
-                                        const Preprocessor &PP,<br>
-                                        StringRef isysroot) {<br>
+                                        const Preprocessor &PP) {<br>
   RecordData Record;<br>
<br>
   // Enter the source manager block.<br>
@@ -1902,17 +1907,10 @@ void ASTWriter::<u></u>WriteSourceManagerBlock(<br>
     LineTableInfo &LineTable = SourceMgr.getLineTable();<br>
<br>
     Record.clear();<br>
-    // Emit the file names<br>
+    // Emit the file names.<br>
     Record.push_back(LineTable.<u></u>getNumFilenames());<br>
-    for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {<br>
-      // Emit the file name<br>
-      const char *Filename = LineTable.getFilename(I);<br>
-      Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
-      unsigned FilenameLen = Filename? strlen(Filename) : 0;<br>
-      Record.push_back(FilenameLen);<br>
-      if (FilenameLen)<br>
-        Record.insert(Record.end(), Filename, Filename + FilenameLen);<br>
-    }<br>
+    for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I)<br>
+      AddPath(LineTable.getFilename(<u></u>I), Record);<br>
<br>
     // Emit the line entries<br>
     for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();<br>
@@ -2543,7 +2541,7 @@ void ASTWriter::WriteSubmodules(<u></u>Module *<br>
       Record.clear();<br>
       for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {<br>
         unsigned ImportedID = getSubmoduleID(Mod->Imports[I]<u></u>);<br>
-        assert(ImportedID && "Unknown submodule!");<br>
+        assert(ImportedID && "Unknown submodule!");<br>
         Record.push_back(ImportedID);<br>
       }<br>
       Stream.EmitRecord(SUBMODULE_<u></u>IMPORTS, Record);<br>
@@ -4077,6 +4075,47 @@ void ASTWriter::AddString(StringRef Str,<br>
   Record.insert(Record.end(), Str.begin(), Str.end());<br>
 }<br>
<br>
+bool ASTWriter::<u></u>PreparePathForOutput(<u></u>SmallVectorImpl<char> &Path) {<br>
+  bool Changed = false;<br>
+<br>
+  if (!llvm::sys::path::is_<u></u>absolute(StringRef(Path.data()<u></u>, Path.size()))) {<br>
+    // Ask the file manager to fixup the relative path for us. This will<br>
+    // honor the working directory.<br>
+    if (Context)<br>
+      Context->getSourceManager().<u></u>getFileManager().<u></u>FixupRelativePath(Path);<br>
+<br>
+    // We want an absolute path even if we weren't given a spelling for the<br>
+    // current working directory.<br>
+    llvm::sys::fs::make_absolute(<u></u>Path);<br>
+<br>
+    Changed = true;<br>
+  }<br>
+<br>
+  // Remove a prefix to make the path relative, if relevant.<br>
+  const char *PathBegin = Path.data();<br>
+  const char *PathPtr =<br>
+      adjustFilenameForRelocatableAS<u></u>T(PathBegin, BaseDirectory);<br>
+  if (PathPtr != PathBegin) {<br>
+    Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));<br>
+    Changed = true;<br>
+  }<br>
+<br>
+  return Changed;<br>
+}<br>
+<br>
+void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {<br>
+  SmallString<128> FilePath(Path);<br>
+  PreparePathForOutput(FilePath)<u></u>;<br>
+  AddString(FilePath, Record);<br>
+}<br>
+<br>
+void ASTWriter::EmitRecordWithPath(<u></u>unsigned Abbrev, RecordDataImpl &Record,<br>
+                                   StringRef Path) {<br>
+  SmallString<128> FilePath(Path);<br>
+  PreparePathForOutput(FilePath)<u></u>;<br>
+  Stream.EmitRecordWithBlob(<u></u>Abbrev, Record, FilePath);<br>
+}<br>
+<br>
 void ASTWriter::AddVersionTuple(<u></u>const VersionTuple &Version,<br>
                                 RecordDataImpl &Record) {<br>
   Record.push_back(Version.<u></u>getMajor());<br>
@@ -4161,6 +4200,7 @@ void ASTWriter::WriteAST(Sema &SemaRef,<br>
   Context = nullptr;<br>
   PP = nullptr;<br>
   this->WritingModule = nullptr;<br>
+  this->BaseDirectory.clear();<br>
<br>
   WritingAST = false;<br>
 }<br>
@@ -4551,11 +4591,11 @@ void ASTWriter::WriteASTCore(Sema &SemaR<br>
     Stream.EmitRecord(DECL_UPDATE_<u></u>OFFSETS, DeclUpdatesOffsetsRecord);<br>
   WriteCXXBaseSpecifiersOffsets(<u></u>);<br>
   WriteFileDeclIDsMap();<br>
-  WriteSourceManagerBlock(<u></u>Context.getSourceManager(), PP, isysroot);<br>
+  WriteSourceManagerBlock(<u></u>Context.getSourceManager(), PP);<br>
<br>
   WriteComments();<br>
   WritePreprocessor(PP, isModule);<br>
-  WriteHeaderSearch(PP.<u></u>getHeaderSearchInfo(), isysroot);<br>
+  WriteHeaderSearch(PP.<u></u>getHeaderSearchInfo());<br>
   WriteSelectors(SemaRef);<br>
   WriteReferencedSelectorsPool(<u></u>SemaRef);<br>
   WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);<br>
<br>
<br>
______________________________<u></u>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div>