[cfe-commits] r94258 - in /cfe/trunk: include/clang-c/Index.h include/clang/Frontend/ASTUnit.h include/clang/Frontend/PreprocessorOptions.h lib/Frontend/ASTUnit.cpp lib/Frontend/InitPreprocessor.cpp test/Index/Inputs/remap-load-to.c test/Index/remap-cursor-at.c test/Index/remap-load.c tools/CIndex/CIndex.cpp tools/CIndex/CIndexCodeCompletion.cpp tools/CIndex/CIndexer.cpp tools/CIndex/CIndexer.h tools/c-index-test/c-index-test.c

Douglas Gregor dgregor at apple.com
Fri Jan 22 16:14:00 PST 2010


Author: dgregor
Date: Fri Jan 22 18:14:00 2010
New Revision: 94258

URL: http://llvm.org/viewvc/llvm-project?rev=94258&view=rev
Log:
Extend clang_createTranslationUnitFromSourceFile() to support creating
translation units that include unsaved files.

Added:
    cfe/trunk/test/Index/Inputs/remap-load-to.c
    cfe/trunk/test/Index/remap-cursor-at.c
    cfe/trunk/test/Index/remap-load.c
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/include/clang/Frontend/PreprocessorOptions.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/InitPreprocessor.cpp
    cfe/trunk/tools/CIndex/CIndex.cpp
    cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp
    cfe/trunk/tools/CIndex/CIndexer.cpp
    cfe/trunk/tools/CIndex/CIndexer.h
    cfe/trunk/tools/c-index-test/c-index-test.c

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Jan 22 18:14:00 2010
@@ -222,13 +222,21 @@
  *
  * \param source_filename - The name of the source file to load, or NULL if the
  * source file is included in clang_command_line_args.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for code completion, including the contents of
+ * those files.
  */
 CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
-  CXIndex CIdx,
-  const char *source_filename,
-  int num_clang_command_line_args, 
-  const char **clang_command_line_args
-);
+                                        CXIndex CIdx,
+                                        const char *source_filename,
+                                        int num_clang_command_line_args, 
+                                        const char **clang_command_line_args,
+                                        unsigned num_unsaved_files,
+                                        struct CXUnsavedFile *unsaved_files);
 
 /**
  * \defgroup CINDEX_FILES File manipulation routines

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri Jan 22 18:14:00 2010
@@ -21,6 +21,11 @@
 #include <string>
 #include <vector>
 #include <cassert>
+#include <utility>
+
+namespace llvm {
+  class MemoryBuffer;
+}
 
 namespace clang {
 class ASTContext;
@@ -111,6 +116,10 @@
     return TopLevelDecls;
   }
 
+  /// \brief A mapping from a file name to the memory buffer that stores the
+  /// remapped contents of that file.
+  typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
+  
   /// \brief Create a ASTUnit from a PCH file.
   ///
   /// \param Filename - The PCH file to load.
@@ -122,7 +131,9 @@
   static ASTUnit *LoadFromPCHFile(const std::string &Filename,
                                   Diagnostic &Diags,
                                   bool OnlyLocalDecls = false,
-                                  bool UseBumpAllocator = false);
+                                  bool UseBumpAllocator = false,
+                                  RemappedFile *RemappedFiles = 0,
+                                  unsigned NumRemappedFiles = 0);
 
   /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
   /// CompilerInvocation object.
@@ -158,7 +169,9 @@
                                       Diagnostic &Diags,
                                       llvm::StringRef ResourceFilesPath,
                                       bool OnlyLocalDecls = false,
-                                      bool UseBumpAllocator = false);
+                                      bool UseBumpAllocator = false,
+                                      RemappedFile *RemappedFiles = 0,
+                                      unsigned NumRemappedFiles = 0);
 };
 
 } // namespace clang

Modified: cfe/trunk/include/clang/Frontend/PreprocessorOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PreprocessorOptions.h?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PreprocessorOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/PreprocessorOptions.h Fri Jan 22 18:14:00 2010
@@ -16,6 +16,10 @@
 #include <utility>
 #include <vector>
 
+namespace llvm {
+  class MemoryBuffer;
+}
+
 namespace clang {
 
 class Preprocessor;
@@ -48,6 +52,12 @@
   /// pair).
   std::vector<std::pair<std::string, std::string> >  RemappedFiles;
 
+  /// \brief The set of file-to-buffer remappings, which take existing files
+  /// on the system (the first part of each pair) and gives them the contents
+  /// of the specified memory buffer (the second part of each pair).
+  std::vector<std::pair<std::string, const llvm::MemoryBuffer *> > 
+    RemappedFileBuffers;
+  
   typedef std::vector<std::pair<std::string, std::string> >::const_iterator
     remapped_file_iterator;
   remapped_file_iterator remapped_file_begin() const { 
@@ -57,6 +67,15 @@
     return RemappedFiles.end();
   }
 
+  typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+                                  const_iterator remapped_file_buffer_iterator;
+  remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+    return RemappedFileBuffers.begin();
+  }
+  remapped_file_buffer_iterator remapped_file_buffer_end() const {
+    return RemappedFileBuffers.end();
+  }
+  
 public:
   PreprocessorOptions() : UsePredefines(true) {}
 
@@ -69,6 +88,9 @@
   void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
     RemappedFiles.push_back(std::make_pair(From, To));
   }
+  void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
+    RemappedFileBuffers.push_back(std::make_pair(From, To));
+  }
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri Jan 22 18:14:00 2010
@@ -30,6 +30,7 @@
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/System/Host.h"
 #include "llvm/System/Path.h"
 using namespace clang;
@@ -103,11 +104,31 @@
 ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
                                   Diagnostic &Diags,
                                   bool OnlyLocalDecls,
-                                  bool UseBumpAllocator) {
+                                  bool UseBumpAllocator,
+                                  RemappedFile *RemappedFiles,
+                                  unsigned NumRemappedFiles) {
   llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
 
+  for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile
+      = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
+                                    RemappedFiles[I].second->getBufferSize(),
+                                             0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+        << RemappedFiles[I].first;
+      continue;
+    }
+    
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    AST->getSourceManager().overrideFileContents(FromFile, 
+                                                 RemappedFiles[I].second);    
+  }
+  
   // Gather Info for preprocessor construction later on.
 
   LangOptions LangInfo;
@@ -289,7 +310,9 @@
                                       Diagnostic &Diags,
                                       llvm::StringRef ResourceFilesPath,
                                       bool OnlyLocalDecls,
-                                      bool UseBumpAllocator) {
+                                      bool UseBumpAllocator,
+                                      RemappedFile *RemappedFiles,
+                                      unsigned NumRemappedFiles) {
   llvm::SmallVector<const char *, 16> Args;
   Args.push_back("<clang>"); // FIXME: Remove dummy argument.
   Args.insert(Args.end(), ArgBegin, ArgEnd);
@@ -327,6 +350,11 @@
                                      (const char**) CCArgs.data()+CCArgs.size(),
                                      Diags);
 
+  // Override any files that need remapping
+  for (unsigned I = 0; I != NumRemappedFiles; ++I)
+    CI.getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+                                             RemappedFiles[I].second);
+  
   // Override the resources path.
   CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
 

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

==============================================================================
--- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Fri Jan 22 18:14:00 2010
@@ -424,40 +424,61 @@
                                     SourceManager &SourceMgr,
                                     FileManager &FileMgr,
                                     const PreprocessorOptions &InitOpts) {
-  // Remap files in the source manager.
+  // Remap files in the source manager (with buffers).
+  for (PreprocessorOptions::remapped_file_buffer_iterator
+         Remap = InitOpts.remapped_file_buffer_begin(),
+         RemapEnd = InitOpts.remapped_file_buffer_end();
+       Remap != RemapEnd;
+       ++Remap) {
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+                                                Remap->second->getBufferSize(),
+                                                       0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+        << Remap->first;
+      continue;
+    }
+
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    SourceMgr.overrideFileContents(FromFile, Remap->second);
+  }
+
+  // Remap files in the source manager (with other files).
   for (PreprocessorOptions::remapped_file_iterator
-         Remap = InitOpts.remapped_file_begin(),
-         RemapEnd = InitOpts.remapped_file_end();
+       Remap = InitOpts.remapped_file_begin(),
+       RemapEnd = InitOpts.remapped_file_end();
        Remap != RemapEnd;
        ++Remap) {
     // Find the file that we're mapping to.
     const FileEntry *ToFile = FileMgr.getFile(Remap->second);
     if (!ToFile) {
       Diags.Report(diag::err_fe_remap_missing_to_file)
-        << Remap->first << Remap->second;
+      << Remap->first << Remap->second;
       continue;
     }
-
+    
     // Create the file entry for the file that we're mapping from.
     const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
                                                        ToFile->getSize(),
                                                        0);
     if (!FromFile) {
       Diags.Report(diag::err_fe_remap_missing_from_file)
-        << Remap->first;
+      << Remap->first;
       continue;
     }
-
+    
     // Load the contents of the file we're mapping to.
     std::string ErrorStr;
     const llvm::MemoryBuffer *Buffer
-      = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+    = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
     if (!Buffer) {
       Diags.Report(diag::err_fe_error_opening)
-        << Remap->second << ErrorStr;
+      << Remap->second << ErrorStr;
       continue;
     }
-
+    
     // Override the contents of the "from" file with the contents of
     // the "to" file.
     SourceMgr.overrideFileContents(FromFile, Buffer);

Added: cfe/trunk/test/Index/Inputs/remap-load-to.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/remap-load-to.c?rev=94258&view=auto

==============================================================================
--- cfe/trunk/test/Index/Inputs/remap-load-to.c (added)
+++ cfe/trunk/test/Index/Inputs/remap-load-to.c Fri Jan 22 18:14:00 2010
@@ -0,0 +1,3 @@
+int foo(int parm1, float parm2) {
+  return parm1 + parm2;
+}

Added: cfe/trunk/test/Index/remap-cursor-at.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/remap-cursor-at.c?rev=94258&view=auto

==============================================================================
--- cfe/trunk/test/Index/remap-cursor-at.c (added)
+++ cfe/trunk/test/Index/remap-cursor-at.c Fri Jan 22 18:14:00 2010
@@ -0,0 +1,5 @@
+// RUN: c-index-test -cursor-at=%s:1:15 -cursor-at=%s:2:21 -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck %s
+// RUN: CINDEXTEST_USE_EXTERNAL_AST_GENERATION=1 c-index-test -cursor-at=%s:1:15 -cursor-at=%s:2:21 -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck %s
+
+// CHECK: ParmDecl=parm1:1:13 (Definition)
+// CHECK: DeclRefExpr=parm2:1:26

Added: cfe/trunk/test/Index/remap-load.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/remap-load.c?rev=94258&view=auto

==============================================================================
--- cfe/trunk/test/Index/remap-load.c (added)
+++ cfe/trunk/test/Index/remap-load.c Fri Jan 22 18:14:00 2010
@@ -0,0 +1,13 @@
+// RUN: c-index-test -test-load-source all -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck -check-prefix=CHECK %s
+// RUN: CINDEXTEST_USE_EXTERNAL_AST_GENERATION=1 c-index-test -test-load-source all -remap-file="%s;%S/Inputs/remap-load-to.c" %s | FileCheck -check-prefix=CHECK %s
+
+// CHECK: remap-load.c:1:5: FunctionDecl=foo:1:5 (Definition) [Extent=1:5:3:1]
+// CHECK: remap-load.c:1:13: ParmDecl=parm1:1:13 (Definition) [Extent=1:9:1:17]
+// CHECK: remap-load.c:1:26: ParmDecl=parm2:1:26 (Definition) [Extent=1:20:1:30]
+// CHECK: remap-load.c:1:5: UnexposedStmt=foo [Extent=1:33:3:1]
+// CHECK: remap-load.c:1:5: UnexposedStmt=foo [Extent=2:3:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr= [Extent=2:10:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr= [Extent=2:10:2:22]
+// CHECK: remap-load.c:2:10: UnexposedExpr=parm1:1:13 [Extent=2:10:2:14]
+// CHECK: remap-load.c:2:10: DeclRefExpr=parm1:1:13 [Extent=2:10:2:14]
+// CHECK: remap-load.c:2:18: DeclRefExpr=parm2:1:26 [Extent=2:18:2:22]

Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Fri Jan 22 18:14:00 2010
@@ -873,10 +873,22 @@
 clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
                                           const char *source_filename,
                                           int num_command_line_args,
-                                          const char **command_line_args) {
+                                          const char **command_line_args,
+                                          unsigned num_unsaved_files,
+                                          struct CXUnsavedFile *unsaved_files) {
   assert(CIdx && "Passed null CXIndex");
   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
 
+  llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+  for (unsigned I = 0; I != num_unsaved_files; ++I) {
+    const llvm::MemoryBuffer *Buffer 
+    = llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
+                                       unsaved_files[I].Contents + unsaved_files[I].Length,
+                                       unsaved_files[I].Filename);
+    RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+                                           Buffer));
+  }
+    
   if (!CXXIdx->getUseExternalASTGeneration()) {
     llvm::SmallVector<const char *, 16> Args;
 
@@ -899,7 +911,9 @@
                                    CXXIdx->getDiags(),
                                    CXXIdx->getClangResourcesPath(),
                                    CXXIdx->getOnlyLocalDecls(),
-                                   /* UseBumpAllocator = */ true));
+                                   /* UseBumpAllocator = */ true,
+                                   RemappedFiles.data(),
+                                   RemappedFiles.size()));
     
     // FIXME: Until we have broader testing, just drop the entire AST if we
     // encountered an error.
@@ -930,6 +944,17 @@
   char astTmpFile[L_tmpnam];
   argv.push_back(tmpnam(astTmpFile));
 
+  // Remap any unsaved files to temporary files.
+  std::vector<llvm::sys::Path> TemporaryFiles;
+  std::vector<std::string> RemapArgs;
+  if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+    return 0;
+  
+  // The pointers into the elements of RemapArgs are stable because we
+  // won't be adding anything to RemapArgs after this point.
+  for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
+    argv.push_back(RemapArgs[i].c_str());
+  
   // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
   for (int i = 0; i < num_command_line_args; ++i)
     if (const char *arg = command_line_args[i]) {
@@ -970,11 +995,17 @@
     llvm::errs() << '\n';
   }
 
-  // Finally, we create the translation unit from the ast file.
-  ASTUnit *ATU = static_cast<ASTUnit *>(
-    clang_createTranslationUnit(CIdx, astTmpFile));
+  ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, CXXIdx->getDiags(),
+                                          CXXIdx->getOnlyLocalDecls(),
+                                          /* UseBumpAllocator = */ true,
+                                          RemappedFiles.data(),
+                                          RemappedFiles.size());
   if (ATU)
     ATU->unlinkTemporaryFile();
+  
+  for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+    TemporaryFiles[i].eraseFromDisk();
+  
   return ATU;
 }
 

Modified: cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp Fri Jan 22 18:14:00 2010
@@ -221,35 +221,10 @@
   argv.push_back("-Xclang");
   argv.push_back("-code-completion-macros");
   
+  // Remap any unsaved files to temporary files.
   std::vector<std::string> RemapArgs;
-  for (unsigned i = 0; i != num_unsaved_files; ++i) {
-    char tmpFile[L_tmpnam];
-    char *tmpFileName = tmpnam(tmpFile);
-
-    // Write the contents of this unsaved file into the temporary file.
-    llvm::sys::Path SavedFile(tmpFileName);
-    std::string ErrorInfo;
-    llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
-    if (!ErrorInfo.empty())
-      continue;
-    
-    OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
-    OS.close();
-    if (OS.has_error()) {
-      SavedFile.eraseFromDisk();
-      continue;
-    }
-
-    // Remap the file.
-    std::string RemapArg = unsaved_files[i].Filename;
-    RemapArg += ';';
-    RemapArg += tmpFileName;
-    RemapArgs.push_back("-Xclang");
-    RemapArgs.push_back("-remap-file");
-    RemapArgs.push_back("-Xclang");
-    RemapArgs.push_back(RemapArg);
-    TemporaryFiles.push_back(SavedFile);
-  }
+  if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+    return 0;
 
   // The pointers into the elements of RemapArgs are stable because we
   // won't be adding anything to RemapArgs after this point.

Modified: cfe/trunk/tools/CIndex/CIndexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexer.cpp?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndexer.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndexer.cpp Fri Jan 22 18:14:00 2010
@@ -94,3 +94,40 @@
 
   return P.str();
 }
+
+bool clang::RemapFiles(unsigned num_unsaved_files,
+                       struct CXUnsavedFile *unsaved_files,
+                       std::vector<std::string> &RemapArgs,
+                       std::vector<llvm::sys::Path> &TemporaryFiles) {
+  for (unsigned i = 0; i != num_unsaved_files; ++i) {
+    char tmpFile[L_tmpnam];
+    char *tmpFileName = tmpnam(tmpFile);
+    
+    // Write the contents of this unsaved file into the temporary file.
+    llvm::sys::Path SavedFile(tmpFileName);
+    std::string ErrorInfo;
+    llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
+    if (!ErrorInfo.empty())
+      return true;
+    
+    OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
+    OS.close();
+    if (OS.has_error()) {
+      SavedFile.eraseFromDisk();
+      return true;
+    }
+    
+    // Remap the file.
+    std::string RemapArg = unsaved_files[i].Filename;
+    RemapArg += ';';
+    RemapArg += tmpFileName;
+    RemapArgs.push_back("-Xclang");
+    RemapArgs.push_back("-remap-file");
+    RemapArgs.push_back("-Xclang");
+    RemapArgs.push_back(RemapArg);
+    TemporaryFiles.push_back(SavedFile);
+  }
+  
+  return false;
+}
+

Modified: cfe/trunk/tools/CIndex/CIndexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexer.h?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndexer.h (original)
+++ cfe/trunk/tools/CIndex/CIndexer.h Fri Jan 22 18:14:00 2010
@@ -19,6 +19,7 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "llvm/System/Path.h"
+#include <vector>
 
 using namespace clang;
 
@@ -77,4 +78,17 @@
   static CXString createCXString(const char *String, bool DupString = false);
 };
 
+namespace clang {
+  /**
+   * \brief Given a set of "unsaved" files, create temporary files and 
+   * construct the clang -cc1 argument list needed to perform the remapping.
+   *
+   * \returns true if an error occurred.
+   */
+  bool RemapFiles(unsigned num_unsaved_files,
+                  struct CXUnsavedFile *unsaved_files,
+                  std::vector<std::string> &RemapArgs,
+                  std::vector<llvm::sys::Path> &TemporaryFiles);
+}
+
 #endif

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=94258&r1=94257&r2=94258&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Jan 22 18:14:00 2010
@@ -39,6 +39,99 @@
   return 1;
 }
 
+void free_remapped_files(struct CXUnsavedFile *unsaved_files,
+                         int num_unsaved_files) {
+  int i;
+  for (i = 0; i != num_unsaved_files; ++i) {
+    free((char *)unsaved_files[i].Filename);
+    free((char *)unsaved_files[i].Contents);
+  }
+}
+
+int parse_remapped_files(int argc, const char **argv, int start_arg,
+                         struct CXUnsavedFile **unsaved_files,
+                         int *num_unsaved_files) {
+  int i;
+  int arg;
+  int prefix_len = strlen("-remap-file=");
+  *unsaved_files = 0;
+  *num_unsaved_files = 0;
+  
+  /* Count the number of remapped files. */
+  for (arg = start_arg; arg < argc; ++arg) {
+    if (strncmp(argv[arg], "-remap-file=", prefix_len))
+      break;
+    
+    ++*num_unsaved_files;
+  }
+  
+  if (*num_unsaved_files == 0)
+    return 0;
+  
+  *unsaved_files
+  = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * 
+                                   *num_unsaved_files);
+  for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
+    struct CXUnsavedFile *unsaved = *unsaved_files + i;
+    const char *arg_string = argv[arg] + prefix_len;
+    int filename_len;
+    char *filename;
+    char *contents;
+    FILE *to_file;
+    const char *semi = strchr(arg_string, ';');
+    if (!semi) {
+      fprintf(stderr, 
+              "error: -remap-file=from;to argument is missing semicolon\n");
+      free_remapped_files(*unsaved_files, i);
+      *unsaved_files = 0;
+      *num_unsaved_files = 0;
+      return -1;
+    }
+    
+    /* Open the file that we're remapping to. */
+    to_file = fopen(semi + 1, "r");
+    if (!to_file) {
+      fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
+              semi + 1);
+      free_remapped_files(*unsaved_files, i);
+      *unsaved_files = 0;
+      *num_unsaved_files = 0;
+      return -1;
+    }
+    
+    /* Determine the length of the file we're remapping to. */
+    fseek(to_file, 0, SEEK_END);
+    unsaved->Length = ftell(to_file);
+    fseek(to_file, 0, SEEK_SET);
+    
+    /* Read the contents of the file we're remapping to. */
+    contents = (char *)malloc(unsaved->Length + 1);
+    if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
+      fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
+              (feof(to_file) ? "EOF" : "error"), semi + 1);
+      fclose(to_file);
+      free_remapped_files(*unsaved_files, i);
+      *unsaved_files = 0;
+      *num_unsaved_files = 0;
+      return -1;
+    }
+    contents[unsaved->Length] = 0;
+    unsaved->Contents = contents;
+    
+    /* Close the file. */
+    fclose(to_file);
+    
+    /* Copy the file name that we're remapping from. */
+    filename_len = semi - arg_string;
+    filename = (char *)malloc(filename_len + 1);
+    memcpy(filename, arg_string, filename_len);
+    filename[filename_len] = 0;
+    unsaved->Filename = filename;
+  }
+  
+  return 0;
+}
+
 /******************************************************************************/
 /* Pretty-printing.                                                           */
 /******************************************************************************/
@@ -258,6 +351,10 @@
     getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION");
   CXIndex Idx;
   CXTranslationUnit TU;
+  struct CXUnsavedFile *unsaved_files = 0;
+  int num_unsaved_files = 0;
+  int result;
+  
   Idx = clang_createIndex(/* excludeDeclsFromPCH */
                           !strcmp(filter, "local") ? 1 : 0,
                           /* displayDiagnostics */ 1);
@@ -265,13 +362,22 @@
   if (UseExternalASTs && strlen(UseExternalASTs))
     clang_setUseExternalASTGeneration(Idx, 1);
 
-  TU = clang_createTranslationUnitFromSourceFile(Idx, 0, argc, argv);
+  if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files))
+    return -1;
+
+  TU = clang_createTranslationUnitFromSourceFile(Idx, 0, 
+                                                 argc - num_unsaved_files, 
+                                                 argv + num_unsaved_files,
+                                                 num_unsaved_files,
+                                                 unsaved_files);
   if (!TU) {
     fprintf(stderr, "Unable to load translation unit!\n");
     return 1;
   }
 
-  return perform_test_load(Idx, TU, filter, NULL, Visitor);
+  result = perform_test_load(Idx, TU, filter, NULL, Visitor);
+  free_remapped_files(unsaved_files, num_unsaved_files);
+  return result;
 }
 
 /******************************************************************************/
@@ -477,99 +583,6 @@
   fprintf(file, "\n");
 }
 
-void free_remapped_files(struct CXUnsavedFile *unsaved_files,
-                         int num_unsaved_files) {
-  int i;
-  for (i = 0; i != num_unsaved_files; ++i) {
-    free((char *)unsaved_files[i].Filename);
-    free((char *)unsaved_files[i].Contents);
-  }
-}
-
-int parse_remapped_files(int argc, const char **argv, int start_arg,
-                         struct CXUnsavedFile **unsaved_files,
-                          int *num_unsaved_files) {
-  int i;
-  int arg;
-  int prefix_len = strlen("-remap-file=");
-  *unsaved_files = 0;
-  *num_unsaved_files = 0;
-
-  /* Count the number of remapped files. */
-  for (arg = start_arg; arg < argc; ++arg) {
-    if (strncmp(argv[arg], "-remap-file=", prefix_len))
-      break;
-
-    ++*num_unsaved_files;
-  }
-
-  if (*num_unsaved_files == 0)
-    return 0;
-
-  *unsaved_files
-    = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * 
-                                     *num_unsaved_files);
-  for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
-    struct CXUnsavedFile *unsaved = *unsaved_files + i;
-    const char *arg_string = argv[arg] + prefix_len;
-    int filename_len;
-    char *filename;
-    char *contents;
-    FILE *to_file;
-    const char *semi = strchr(arg_string, ';');
-    if (!semi) {
-      fprintf(stderr, 
-              "error: -remap-file=from;to argument is missing semicolon\n");
-      free_remapped_files(*unsaved_files, i);
-      *unsaved_files = 0;
-      *num_unsaved_files = 0;
-      return -1;
-    }
-
-    /* Open the file that we're remapping to. */
-    to_file = fopen(semi + 1, "r");
-    if (!to_file) {
-      fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
-              semi + 1);
-      free_remapped_files(*unsaved_files, i);
-      *unsaved_files = 0;
-      *num_unsaved_files = 0;
-      return -1;
-    }
-
-    /* Determine the length of the file we're remapping to. */
-    fseek(to_file, 0, SEEK_END);
-    unsaved->Length = ftell(to_file);
-    fseek(to_file, 0, SEEK_SET);
-    
-    /* Read the contents of the file we're remapping to. */
-    contents = (char *)malloc(unsaved->Length + 1);
-    if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
-      fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
-              (feof(to_file) ? "EOF" : "error"), semi + 1);
-      fclose(to_file);
-      free_remapped_files(*unsaved_files, i);
-      *unsaved_files = 0;
-      *num_unsaved_files = 0;
-      return -1;
-    }
-    contents[unsaved->Length] = 0;
-    unsaved->Contents = contents;
-
-    /* Close the file. */
-    fclose(to_file);
-    
-    /* Copy the file name that we're remapping from. */
-    filename_len = semi - arg_string;
-    filename = (char *)malloc(filename_len + 1);
-    memcpy(filename, arg_string, filename_len);
-    filename[filename_len] = 0;
-    unsaved->Filename = filename;
-  }
-
-  return 0;
-}
-
 int perform_code_completion(int argc, const char **argv) {
   const char *input = argv[1];
   char *filename = 0;
@@ -624,7 +637,7 @@
   CXCursor Cursor;
   CursorSourceLocation *Locations = 0;
   unsigned NumLocations = 0, Loc;
-  
+
   /* Count the number of locations. */ 
   while (strstr(argv[NumLocations+1], "-cursor-at=") == argv[NumLocations+1])
     ++NumLocations;
@@ -645,15 +658,12 @@
                            &num_unsaved_files))
     return -1;
   
-  if (num_unsaved_files > 0) {
-    fprintf(stderr, "cannot remap files when looking for a cursor\n");
-    return -1;
-  }
-  
   CIdx = clang_createIndex(0, 1);
   TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
                                   argc - num_unsaved_files - 2 - NumLocations,
-                                   argv + num_unsaved_files + 1 + NumLocations);
+                                   argv + num_unsaved_files + 1 + NumLocations,
+                                                 num_unsaved_files,
+                                                 unsaved_files);
   if (!TU) {
     fprintf(stderr, "unable to parse input\n");
     return -1;





More information about the cfe-commits mailing list