Extend clang_createTranslationUnitFromSourceFile() to support creating
translation units that include unsaved files.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94258 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index ddbdf53..6cd545f 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -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;
}
diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp
index f70479b..f3b60dc 100644
--- a/tools/CIndex/CIndexCodeCompletion.cpp
+++ b/tools/CIndex/CIndexCodeCompletion.cpp
@@ -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.
diff --git a/tools/CIndex/CIndexer.cpp b/tools/CIndex/CIndexer.cpp
index f26c8ce..53636a4 100644
--- a/tools/CIndex/CIndexer.cpp
+++ b/tools/CIndex/CIndexer.cpp
@@ -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;
+}
+
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index 1a4e4b7..d01454f 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -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