[cfe-commits] r90329 - in /cfe/trunk: include/clang/Basic/FileManager.h lib/Basic/FileManager.cpp lib/Frontend/InitPreprocessor.cpp test/Misc/Inputs/remapped-file-2 test/Misc/Inputs/remapped-file-3 test/Misc/remap-file.c

Douglas Gregor dgregor at apple.com
Wed Dec 2 10:12:29 PST 2009


Author: dgregor
Date: Wed Dec  2 12:12:28 2009
New Revision: 90329

URL: http://llvm.org/viewvc/llvm-project?rev=90329&view=rev
Log:
Extend -remap-file=from;to to permit mapping from a non-existent
file. This is accomplished by introducing the notion of a "virtual"
file into the file manager, which provides a FileEntry* for a named
file whose size and modification time are known but which may not
exist on disk.

Added a cute little test that remaps both a .c file and a .h file it
includes to alternative files.


Added:
    cfe/trunk/test/Misc/Inputs/remapped-file-2
    cfe/trunk/test/Misc/Inputs/remapped-file-3
Modified:
    cfe/trunk/include/clang/Basic/FileManager.h
    cfe/trunk/lib/Basic/FileManager.cpp
    cfe/trunk/lib/Frontend/InitPreprocessor.cpp
    cfe/trunk/test/Misc/remap-file.c

Modified: cfe/trunk/include/clang/Basic/FileManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileManager.h?rev=90329&r1=90328&r2=90329&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/FileManager.h (original)
+++ cfe/trunk/include/clang/Basic/FileManager.h Wed Dec  2 12:12:28 2009
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_FILEMANAGER_H
 #define LLVM_CLANG_FILEMANAGER_H
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/OwningPtr.h"
@@ -151,6 +152,9 @@
   ///
   unsigned NextFileUID;
 
+  /// \brief The virtual files that we have allocated.
+  llvm::SmallVector<FileEntry *, 4> VirtualFileEntries;
+
   // Statistics.
   unsigned NumDirLookups, NumFileLookups;
   unsigned NumDirCacheMisses, NumFileCacheMisses;
@@ -199,6 +203,11 @@
   const FileEntry *getFile(const char *FilenameStart,
                            const char *FilenameEnd);
 
+  /// \brief Retrieve a file entry for a "virtual" file that acts as
+  /// if there were a file with the given name on disk. The file
+  /// itself is not accessed.
+  const FileEntry *getVirtualFile(const llvm::StringRef &Filename,
+                                  off_t Size, time_t ModificationTime);
   void PrintStats() const;
 };
 

Modified: cfe/trunk/lib/Basic/FileManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/FileManager.cpp?rev=90329&r1=90328&r2=90329&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/FileManager.cpp (original)
+++ cfe/trunk/lib/Basic/FileManager.cpp Wed Dec  2 12:12:28 2009
@@ -147,6 +147,12 @@
 FileManager::~FileManager() {
   delete &UniqueDirs;
   delete &UniqueFiles;
+  for (llvm::SmallVectorImpl<FileEntry *>::iterator
+         V = VirtualFileEntries.begin(),
+         VEnd = VirtualFileEntries.end();
+       V != VEnd; 
+       ++V)
+    delete *V;
 }
 
 void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) {
@@ -184,6 +190,30 @@
     assert(false && "Stat cache not found for removal");
 }
 
+/// \brief Retrieve the directory that the given file name resides in.
+static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
+                                                  const char *NameStart,
+                                                  const char *NameEnd) {
+  // Figure out what directory it is in.   If the string contains a / in it,
+  // strip off everything after it.
+  // FIXME: this logic should be in sys::Path.
+  const char *SlashPos = NameEnd-1;
+  while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
+    --SlashPos;
+  // Ignore duplicate //'s.
+  while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1]))
+    --SlashPos;
+
+  if (SlashPos < NameStart) {
+    // Use the current directory if file has no path component.
+    const char *Name = ".";
+    return FileMgr.getDirectory(Name, Name+1);
+  } else if (SlashPos == NameEnd-1)
+    return 0;       // If filename ends with a /, it's a directory.
+  else
+    return FileMgr.getDirectory(NameStart, SlashPos);
+}
+
 /// getDirectory - Lookup, cache, and verify the specified directory.  This
 /// returns null if the directory doesn't exist.
 ///
@@ -252,33 +282,16 @@
   // By default, initialize it to invalid.
   NamedFileEnt.setValue(NON_EXISTENT_FILE);
 
-  // Figure out what directory it is in.   If the string contains a / in it,
-  // strip off everything after it.
-  // FIXME: this logic should be in sys::Path.
-  const char *SlashPos = NameEnd-1;
-  while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
-    --SlashPos;
-  // Ignore duplicate //'s.
-  while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1]))
-    --SlashPos;
-
-  const DirectoryEntry *DirInfo;
-  if (SlashPos < NameStart) {
-    // Use the current directory if file has no path component.
-    const char *Name = ".";
-    DirInfo = getDirectory(Name, Name+1);
-  } else if (SlashPos == NameEnd-1)
-    return 0;       // If filename ends with a /, it's a directory.
-  else
-    DirInfo = getDirectory(NameStart, SlashPos);
-
-  if (DirInfo == 0)  // Directory doesn't exist, file can't exist.
-    return 0;
 
   // Get the null-terminated file name as stored as the key of the
   // FileEntries map.
   const char *InterndFileName = NamedFileEnt.getKeyData();
 
+  const DirectoryEntry *DirInfo
+    = getDirectoryFromFile(*this, NameStart, NameEnd);
+  if (DirInfo == 0)  // Directory doesn't exist, file can't exist.
+    return 0;
+
   // FIXME: Use the directory info to prune this, before doing the stat syscall.
   // FIXME: This will reduce the # syscalls.
 
@@ -312,6 +325,44 @@
   return &UFE;
 }
 
+const FileEntry *
+FileManager::getVirtualFile(const llvm::StringRef &Filename,
+                            off_t Size, time_t ModificationTime) {
+  const char *NameStart = Filename.begin(), *NameEnd = Filename.end();
+
+  ++NumFileLookups;
+
+  // See if there is already an entry in the map.
+  llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
+    FileEntries.GetOrCreateValue(NameStart, NameEnd);
+
+  // See if there is already an entry in the map.
+  if (NamedFileEnt.getValue())
+    return NamedFileEnt.getValue() == NON_EXISTENT_FILE
+                 ? 0 : NamedFileEnt.getValue();
+
+  ++NumFileCacheMisses;
+
+  // By default, initialize it to invalid.
+  NamedFileEnt.setValue(NON_EXISTENT_FILE);
+
+  const DirectoryEntry *DirInfo
+    = getDirectoryFromFile(*this, NameStart, NameEnd);
+  if (DirInfo == 0)  // Directory doesn't exist, file can't exist.
+    return 0;
+
+  FileEntry *UFE = new FileEntry();
+  VirtualFileEntries.push_back(UFE);
+  NamedFileEnt.setValue(UFE);
+
+  UFE->Name    = NamedFileEnt.getKeyData();
+  UFE->Size    = Size;
+  UFE->ModTime = ModificationTime;
+  UFE->Dir     = DirInfo;
+  UFE->UID     = NextFileUID++;
+  return UFE;
+}
+
 void FileManager::PrintStats() const {
   llvm::errs() << "\n*** File Manager Stats:\n";
   llvm::errs() << UniqueFiles.size() << " files found, "

Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=90329&r1=90328&r2=90329&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Wed Dec  2 12:12:28 2009
@@ -19,6 +19,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/System/Path.h"
@@ -502,11 +503,11 @@
       continue;
     }
 
-    // Find the file that we're mapping from.
-    const FileEntry *FromFile = FileMgr.getFile(Remap->first);
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+                                                       ToFile->getSize(),
+                                                       0);
     if (!FromFile) {
-      // FIXME: We could actually recover from this, by faking a
-      // FileEntry based on the "ToFile".
       Diags.Report(diag::err_fe_remap_missing_from_file)
         << Remap->first;
       continue;

Added: cfe/trunk/test/Misc/Inputs/remapped-file-2
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/Inputs/remapped-file-2?rev=90329&view=auto

==============================================================================
--- cfe/trunk/test/Misc/Inputs/remapped-file-2 (added)
+++ cfe/trunk/test/Misc/Inputs/remapped-file-2 Wed Dec  2 12:12:28 2009
@@ -0,0 +1,3 @@
+#include "nonexistent.h"
+
+int *f() { return fp; }

Added: cfe/trunk/test/Misc/Inputs/remapped-file-3
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/Inputs/remapped-file-3?rev=90329&view=auto

==============================================================================
--- cfe/trunk/test/Misc/Inputs/remapped-file-3 (added)
+++ cfe/trunk/test/Misc/Inputs/remapped-file-3 Wed Dec  2 12:12:28 2009
@@ -0,0 +1,2 @@
+extern float *fp;
+

Modified: cfe/trunk/test/Misc/remap-file.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/remap-file.c?rev=90329&r1=90328&r2=90329&view=diff

==============================================================================
--- cfe/trunk/test/Misc/remap-file.c (original)
+++ cfe/trunk/test/Misc/remap-file.c Wed Dec  2 12:12:28 2009
@@ -1,5 +1,8 @@
-// RUN: clang-cc -remap-file="%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck %s
-
-// CHECK: remap-file.c:1:28: warning: incompatible pointer types
+// RUN: clang-cc -remap-file="%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXIST %s
+// RUN: clang-cc -remap-file="%S/nonexistent.c;%S/Inputs/remapped-file" -fsyntax-only %S/nonexistent.c 2>&1 | FileCheck -check-prefix=CHECK-NONEXIST %s
+// RUN: clang-cc -remap-file="%S/nonexistent.c;%S/Inputs/remapped-file-2" -remap-file="%S/nonexistent.h;%S/Inputs/remapped-file-3" -fsyntax-only %S/nonexistent.c 2>&1 | FileCheck -check-prefix=CHECK-HEADER %s
 
+// CHECK-EXIST: remap-file.c:1:28: warning: incompatible pointer types
+// CHECK-NONEXIST: nonexistent.c:1:28: warning: incompatible pointer types
+// CHECK-HEADER: nonexistent.c:3:19: warning: incompatible pointer types
 int





More information about the cfe-commits mailing list