[cfe-commits] r144830 - in /cfe/trunk: include/clang/Basic/SourceManager.h include/clang/Serialization/ASTBitCodes.h lib/Basic/SourceManager.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/Modules/normal-module-map.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 16 12:05:18 PST 2011


Author: dgregor
Date: Wed Nov 16 14:05:18 2011
New Revision: 144830

URL: http://llvm.org/viewvc/llvm-project?rev=144830&view=rev
Log:
Implement (de-)serialization of the buffer contents for an overridden
file in the source manager. This allows us to properly create and use
modules described by module map files without umbrella headers (or
with incompletely umbrella headers). More generally, we can actually
build a PCH file that makes use of  file -> buffer remappings, which
could be useful in libclang in the future.

Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/Basic/SourceManager.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Modules/normal-module-map.cpp

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Wed Nov 16 14:05:18 2011
@@ -102,8 +102,15 @@
 
     /// NumLines - The number of lines in this ContentCache.  This is only valid
     /// if SourceLineCache is non-null.
-    unsigned NumLines;
+    unsigned NumLines : 31;
 
+    /// \brief Indicates whether the buffer itself was provided to override
+    /// the actual file contents.
+    ///
+    /// When true, the original entry may be a virtual file that does not
+    /// exist.
+    unsigned BufferOverridden : 1;
+    
     /// getBuffer - Returns the memory buffer for the associated content.
     ///
     /// \param Diag Object through which diagnostics will be emitted if the

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Nov 16 14:05:18 2011
@@ -452,7 +452,8 @@
       SM_SLOC_BUFFER_ENTRY = 2,
       /// \brief Describes a blob that contains the data for a buffer
       /// entry. This kind of record always directly follows a
-      /// SM_SLOC_BUFFER_ENTRY record.
+      /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
+      /// overridden buffer.
       SM_SLOC_BUFFER_BLOB = 3,
       /// \brief Describes a source location entry (SLocEntry) for a
       /// macro expansion.

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Wed Nov 16 14:05:18 2011
@@ -580,6 +580,7 @@
   assert(IR && "getOrCreateContentCache() cannot return NULL");
 
   const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
+  const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true;
 }
 
 void SourceManager::overrideFileContents(const FileEntry *SourceFile,

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Nov 16 14:05:18 2011
@@ -1081,9 +1081,18 @@
     return Failure;
 
   case SM_SLOC_FILE_ENTRY: {
-    std::string Filename(BlobStart, BlobStart + BlobLen);
+    if (Record.size() < 7) {
+      Error("source location entry is incorrect");
+      return Failure;
+    }
+
+    bool OverriddenBuffer = Record[6];
+    
+    std::string OrigFilename(BlobStart, BlobStart + BlobLen);
+    std::string Filename = OrigFilename;
     MaybeAddSystemRootToFilename(Filename);
-    const FileEntry *File = FileMgr.getFile(Filename);
+    const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false,
+                                            /*CacheFailure=*/!OverriddenBuffer);
     if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() &&
         OriginalDir != CurrentDir) {
       std::string resolved = resolveFileRelativeToOriginalDir(Filename,
@@ -1103,11 +1112,6 @@
       return Failure;
     }
 
-    if (Record.size() < 6) {
-      Error("source location entry is incorrect");
-      return Failure;
-    }
-
     if (!DisableValidation &&
         ((off_t)Record[4] != File->getSize()
 #if !defined(LLVM_ON_WIN32)
@@ -1131,18 +1135,35 @@
                                         ID, BaseOffset + Record[0]);
     SrcMgr::FileInfo &FileInfo =
           const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
-    FileInfo.NumCreatedFIDs = Record[6];
+    FileInfo.NumCreatedFIDs = Record[7];
     if (Record[3])
       FileInfo.setHasLineDirectives();
 
-    const DeclID *FirstDecl = F->FileSortedDecls + Record[7];
-    unsigned NumFileDecls = Record[8];
+    const DeclID *FirstDecl = F->FileSortedDecls + Record[8];
+    unsigned NumFileDecls = Record[9];
     if (NumFileDecls) {
       assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
       FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
                                                              NumFileDecls));
     }
     
+    if (OverriddenBuffer &&
+        !SourceMgr.getOrCreateContentCache(File)->BufferOverridden) {
+      unsigned Code = SLocEntryCursor.ReadCode();
+      Record.clear();
+      unsigned RecCode
+        = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+      
+      if (RecCode != SM_SLOC_BUFFER_BLOB) {
+        Error("AST record has invalid code");
+        return Failure;
+      }
+      
+      llvm::MemoryBuffer *Buffer
+        = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+                                           Filename);
+      SourceMgr.overrideFileContents(File, Buffer);
+    }
     break;
   }
 
@@ -1160,8 +1181,8 @@
     }
 
     llvm::MemoryBuffer *Buffer
-    = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
-                                       Name);
+      = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+                                         Name);
     FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID,
                                                          BaseOffset + Offset);
 
@@ -2341,6 +2362,10 @@
       return Failure;
 
     case SM_SLOC_FILE_ENTRY: {
+      // If the buffer was overridden, the file need not exist.
+      if (Record[6])
+        break;
+      
       StringRef Filename(BlobStart, BlobLen);
       const FileEntry *File = getFileEntry(Filename);
 
@@ -2352,7 +2377,7 @@
         return IgnorePCH;
       }
 
-      if (Record.size() < 6) {
+      if (Record.size() < 7) {
         Error("source location entry is incorrect");
         return Failure;
       }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Nov 16 14:05:18 2011
@@ -1174,6 +1174,7 @@
   // FileEntry fields.
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // BufferOverridden
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls
@@ -1421,7 +1422,8 @@
     // Figure out which record code to use.
     unsigned Code;
     if (SLoc->isFile()) {
-      if (SLoc->getFile().getContentCache()->OrigEntry) {
+      const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache();
+      if (Cache->OrigEntry) {
         Code = SM_SLOC_FILE_ENTRY;
         SLocFileEntryOffsets.push_back(Stream.GetCurrentBitNo());
       } else
@@ -1442,7 +1444,7 @@
       const SrcMgr::ContentCache *Content = File.getContentCache();
       if (Content->OrigEntry) {
         assert(Content->OrigEntry == Content->ContentsEntry &&
-               "Writing to AST an overriden file is not supported");
+               "Writing to AST an overridden file is not supported");
 
         // The source location entry is a file. The blob associated
         // with this entry is the file name.
@@ -1450,7 +1452,7 @@
         // Emit size/modification time for this file.
         Record.push_back(Content->OrigEntry->getSize());
         Record.push_back(Content->OrigEntry->getModificationTime());
-
+        Record.push_back(Content->BufferOverridden);
         Record.push_back(File.NumCreatedFIDs);
         
         FileDeclIDsTy::iterator FDI = FileDeclIDs.find(SLoc);
@@ -1461,7 +1463,7 @@
           Record.push_back(0);
           Record.push_back(0);
         }
-
+        
         // Turn the file name into an absolute path, if it isn't already.
         const char *Filename = Content->OrigEntry->getName();
         llvm::SmallString<128> FilePath(Filename);
@@ -1477,6 +1479,16 @@
 
         Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
         Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
+        
+        if (Content->BufferOverridden) {
+          Record.clear();
+          Record.push_back(SM_SLOC_BUFFER_BLOB);
+          const llvm::MemoryBuffer *Buffer
+            = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
+          Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
+                                    StringRef(Buffer->getBufferStart(),
+                                              Buffer->getBufferSize() + 1));          
+        }
       } else {
         // The source location entry is a buffer. The blob associated
         // with this entry contains the contents of the buffer.

Modified: cfe/trunk/test/Modules/normal-module-map.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/normal-module-map.cpp?rev=144830&r1=144829&r2=144830&view=diff
==============================================================================
--- cfe/trunk/test/Modules/normal-module-map.cpp (original)
+++ cfe/trunk/test/Modules/normal-module-map.cpp Wed Nov 16 14:05:18 2011
@@ -1,4 +1,8 @@
 // RUN: rm -rf %t
+// FIXME: Eventually, we should be able to remove these explicit module creation lines
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libA -emit-module-from-map %S/Inputs/normal-module-map/module.map
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map
 // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify
 #include "Umbrella/Umbrella.h"
 
@@ -8,9 +12,7 @@
 
 __import_module__ Umbrella2;
 
-// FIXME: The expected error here is temporary, since we don't yet have the
-// logic to build a module from a module map.
-#include "a1.h" // expected-error{{module 'libA' not found}}
+#include "a1.h"
 #include "b1.h"
 #include "nested/nested2.h"
 





More information about the cfe-commits mailing list