[cfe-commits] r156107 - in /cfe/trunk: include/clang/Basic/DiagnosticSerializationKinds.td include/clang/Basic/FileManager.h include/clang/Basic/SourceManager.h lib/Basic/FileManager.cpp lib/Basic/SourceManager.cpp lib/Serialization/ASTReader.cpp test/PCH/remap-file-from-pch.cpp test/PCH/remap-file-from-pch.cpp.h test/PCH/remap-file-from-pch.cpp.remap.h

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu May 3 14:50:39 PDT 2012


Author: akirtzidis
Date: Thu May  3 16:50:39 2012
New Revision: 156107

URL: http://llvm.org/viewvc/llvm-project?rev=156107&view=rev
Log:
[PCH] When validating that the files coming from PCH did not change, also
validate that we didn't override the contents of any of such files.

If this is detected, emit a diagnostic error and recover gracefully
by using the contents of the original file that the PCH was built from.

Part of rdar://11305263

Added:
    cfe/trunk/test/PCH/remap-file-from-pch.cpp
    cfe/trunk/test/PCH/remap-file-from-pch.cpp.h
    cfe/trunk/test/PCH/remap-file-from-pch.cpp.remap.h
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
    cfe/trunk/include/clang/Basic/FileManager.h
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/lib/Basic/FileManager.cpp
    cfe/trunk/lib/Basic/SourceManager.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Thu May  3 16:50:39 2012
@@ -22,6 +22,8 @@
 def err_fe_pch_file_modified : Error<
     "file '%0' has been modified since the precompiled header was built">,
     DefaultFatal;
+def err_fe_pch_file_overridden : Error<
+    "file '%0' from the precompiled header has been overridden">;
 
 def warn_pch_target_triple : Error<
     "PCH file was compiled for the target '%0' but the current translation "

Modified: cfe/trunk/include/clang/Basic/FileManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileManager.h?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/FileManager.h (original)
+++ cfe/trunk/include/clang/Basic/FileManager.h Thu May  3 16:50:39 2012
@@ -226,6 +226,11 @@
   void GetUniqueIDMapping(
                     SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
 
+  /// \brief Modifies the size and modification time of a previously created
+  /// FileEntry. Use with caution.
+  static void modifyFileEntry(FileEntry *File, off_t Size,
+                              time_t ModificationTime);
+
   void PrintStats() const;
 };
 

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Thu May  3 16:50:39 2012
@@ -21,7 +21,9 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <map>
 #include <vector>
@@ -501,9 +503,24 @@
   /// files, should report the original file name. Defaults to true.
   bool OverridenFilesKeepOriginalName;
 
-  /// \brief Files that have been overriden with the contents from another file.
-  llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+  struct OverriddenFilesInfoTy {
+    /// \brief Files that have been overriden with the contents from another
+    /// file.
+    llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+    /// \brief Files that were overridden with a memory buffer.
+    llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
+  };
 
+  /// \brief Lazily create the object keeping overridden files info, since
+  /// it is uncommonly used.
+  OwningPtr<OverriddenFilesInfoTy> OverriddenFilesInfo;
+
+  OverriddenFilesInfoTy &getOverriddenFilesInfo() {
+    if (!OverriddenFilesInfo)
+      OverriddenFilesInfo.reset(new OverriddenFilesInfoTy);
+    return *OverriddenFilesInfo;
+  }
+  
   /// MemBufferInfos - Information about various memory buffers that we have
   /// read in.  All FileEntry* within the stored ContentCache objects are NULL,
   /// as they do not refer to a file.
@@ -715,6 +732,23 @@
   void overrideFileContents(const FileEntry *SourceFile,
                             const FileEntry *NewFile);
 
+  /// \brief Returns true if the file contents have been overridden.
+  bool isFileOverridden(const FileEntry *File) {
+    if (OverriddenFilesInfo) {
+      if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
+        return true;
+      if (OverriddenFilesInfo->OverriddenFiles.find(File) !=
+          OverriddenFilesInfo->OverriddenFiles.end())
+        return true;
+    }
+    return false;
+  }
+
+  /// \brief Disable overridding the contents of a file, previously enabled
+  /// with \see overrideFileContents.
+  /// This should be called before parsing has begun.
+  void disableFileContentsOverride(const FileEntry *File);
+
   //===--------------------------------------------------------------------===//
   // FileID manipulation methods.
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Basic/FileManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/FileManager.cpp?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/FileManager.cpp (original)
+++ cfe/trunk/lib/Basic/FileManager.cpp Thu May  3 16:50:39 2012
@@ -584,6 +584,12 @@
       UIDToFiles[(*VFE)->getUID()] = *VFE;
 }
 
+void FileManager::modifyFileEntry(FileEntry *File,
+                                  off_t Size, time_t ModificationTime) {
+  File->Size = Size;
+  File->ModTime = ModificationTime;
+}
+
 
 void FileManager::PrintStats() const {
   llvm::errs() << "\n*** File Manager Stats:\n";

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Thu May  3 16:50:39 2012
@@ -71,7 +71,7 @@
 
 void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
                                  bool DoNotFree) {
-  if (B == Buffer.getPointer()) {
+  if (B && B == Buffer.getPointer()) {
     assert(0 && "Replacing with the same buffer");
     Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
     return;
@@ -440,16 +440,20 @@
   EntryAlign = std::max(8U, EntryAlign);
   Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
 
-  // If the file contents are overridden with contents from another file,
-  // pass that file to ContentCache.
-  llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
-      overI = OverriddenFiles.find(FileEnt);
-  if (overI == OverriddenFiles.end())
+  if (OverriddenFilesInfo) {
+    // If the file contents are overridden with contents from another file,
+    // pass that file to ContentCache.
+    llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
+        overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
+    if (overI == OverriddenFilesInfo->OverriddenFiles.end())
+      new (Entry) ContentCache(FileEnt);
+    else
+      new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
+                                                              : overI->second,
+                               overI->second);
+  } else {
     new (Entry) ContentCache(FileEnt);
-  else
-    new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
-                                                            : overI->second,
-                             overI->second);
+  }
 
   return Entry;
 }
@@ -622,6 +626,8 @@
 
   const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
   const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true;
+
+  getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
 }
 
 void SourceManager::overrideFileContents(const FileEntry *SourceFile,
@@ -632,7 +638,20 @@
   assert(FileInfos.count(SourceFile) == 0 &&
          "This function should be called at the initialization stage, before "
          "any parsing occurs.");
-  OverriddenFiles[SourceFile] = NewFile;
+  getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
+}
+
+void SourceManager::disableFileContentsOverride(const FileEntry *File) {
+  if (!isFileOverridden(File))
+    return;
+
+  const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
+  const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(0);
+  const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry;
+
+  assert(OverriddenFilesInfo);
+  OverriddenFilesInfo->OverriddenFiles.erase(File);
+  OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
 }
 
 StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
@@ -1887,10 +1906,14 @@
 }
 
 size_t SourceManager::getDataStructureSizes() const {
-  return llvm::capacity_in_bytes(MemBufferInfos)
+  size_t size = llvm::capacity_in_bytes(MemBufferInfos)
     + llvm::capacity_in_bytes(LocalSLocEntryTable)
     + llvm::capacity_in_bytes(LoadedSLocEntryTable)
     + llvm::capacity_in_bytes(SLocEntryLoaded)
-    + llvm::capacity_in_bytes(FileInfos)
-    + llvm::capacity_in_bytes(OverriddenFiles);
+    + llvm::capacity_in_bytes(FileInfos);
+  
+  if (OverriddenFilesInfo)
+    size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
+
+  return size;
 }

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=156107&r1=156106&r2=156107&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu May  3 16:50:39 2012
@@ -2473,6 +2473,26 @@
         Error("source location entry is incorrect");
         return Failure;
       }
+      
+      off_t StoredSize = (off_t)Record[4];
+      time_t StoredTime = (time_t)Record[5];
+
+      // Check if there was a request to override the contents of the file
+      // that was part of the precompiled header. Overridding such a file
+      // can lead to problems when lexing using the source locations from the
+      // PCH.
+      SourceManager &SM = getSourceManager();
+      if (SM.isFileOverridden(File)) {
+        Error(diag::err_fe_pch_file_overridden, Filename);
+        // After emitting the diagnostic, recover by disabling the override so
+        // that the original file will be used.
+        SM.disableFileContentsOverride(File);
+        // The FileEntry is a virtual file entry with the size of the contents
+        // that would override the original contents. Set it to the original's
+        // size/time.
+        FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
+                                StoredSize, StoredTime);
+      }
 
       // The stat info from the FileEntry came from the cached stat
       // info of the PCH, so we cannot trust it.
@@ -2482,12 +2502,12 @@
         StatBuf.st_mtime = File->getModificationTime();
       }
 
-      if (((off_t)Record[4] != StatBuf.st_size
+      if ((StoredSize != StatBuf.st_size
 #if !defined(LLVM_ON_WIN32)
           // In our regression testing, the Windows file system seems to
           // have inconsistent modification times that sometimes
           // erroneously trigger this error-handling path.
-           || (time_t)Record[5] != StatBuf.st_mtime
+           || StoredTime != StatBuf.st_mtime
 #endif
           )) {
         Error(diag::err_fe_pch_file_modified, Filename);

Added: cfe/trunk/test/PCH/remap-file-from-pch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/remap-file-from-pch.cpp?rev=156107&view=auto
==============================================================================
--- cfe/trunk/test/PCH/remap-file-from-pch.cpp (added)
+++ cfe/trunk/test/PCH/remap-file-from-pch.cpp Thu May  3 16:50:39 2012
@@ -0,0 +1,10 @@
+//  %clang_cc1 -remap-file "%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXIST %s
+
+// RUN: %clang_cc1 -x c++-header %s.h -emit-pch -o %t.pch
+// RUN: %clang_cc1 %s -include-pch %t.pch -remap-file "%s.h;%s.remap.h" -fsyntax-only 2>&1 | FileCheck %s
+
+const char *str = STR;
+int ge = zool;
+
+// CHECK: file '{{.*}}/remap-file-from-pch.cpp.h' from the precompiled header has been overridden
+// CHECK: use of undeclared identifier 'zool'

Added: cfe/trunk/test/PCH/remap-file-from-pch.cpp.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/remap-file-from-pch.cpp.h?rev=156107&view=auto
==============================================================================
--- cfe/trunk/test/PCH/remap-file-from-pch.cpp.h (added)
+++ cfe/trunk/test/PCH/remap-file-from-pch.cpp.h Thu May  3 16:50:39 2012
@@ -0,0 +1,2 @@
+
+#define STR "nexus"

Added: cfe/trunk/test/PCH/remap-file-from-pch.cpp.remap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/remap-file-from-pch.cpp.remap.h?rev=156107&view=auto
==============================================================================
--- cfe/trunk/test/PCH/remap-file-from-pch.cpp.remap.h (added)
+++ cfe/trunk/test/PCH/remap-file-from-pch.cpp.remap.h Thu May  3 16:50:39 2012
@@ -0,0 +1,4 @@
+
+#define STR          "nexus"
+
+int zool;





More information about the cfe-commits mailing list