diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-23 00:14:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-23 00:14:00 +0000 |
commit | 4db64a461cb3442934afe43c83ed3f17f7c11c1d (patch) | |
tree | c9de870e2fa2e16f082b9e5124e32ac324b070c3 /tools | |
parent | e4fb82839a762e632f63e195058015e2f1ca27a8 (diff) |
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
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CIndex/CIndex.cpp | 41 | ||||
-rw-r--r-- | tools/CIndex/CIndexCodeCompletion.cpp | 31 | ||||
-rw-r--r-- | tools/CIndex/CIndexer.cpp | 37 | ||||
-rw-r--r-- | tools/CIndex/CIndexer.h | 14 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 214 |
5 files changed, 202 insertions, 135 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index ddbdf531d0..6cd545f53f 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -873,10 +873,22 @@ CXTranslationUnit 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 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, 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 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, 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 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, 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 f70479b5e8..f3b60dc8b0 100644 --- a/tools/CIndex/CIndexCodeCompletion.cpp +++ b/tools/CIndex/CIndexCodeCompletion.cpp @@ -221,35 +221,10 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, 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 f26c8ce813..53636a4ff3 100644 --- a/tools/CIndex/CIndexer.cpp +++ b/tools/CIndex/CIndexer.cpp @@ -94,3 +94,40 @@ std::string CIndexer::getClangResourcesPath() { 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 1a4e4b7b8f..d01454f9dc 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 @@ public: 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 diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 98ed772ec6..4ef3904139 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -39,6 +39,99 @@ static unsigned CreateTranslationUnit(CXIndex Idx, const char *file, 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 @@ int perform_test_load_source(int argc, const char **argv, const char *filter, 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 @@ int perform_test_load_source(int argc, const char **argv, const char *filter, 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 @@ void print_completion_result(CXCompletionResult *completion_result, 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 @@ int inspect_cursor_at(int argc, const char **argv) { 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 @@ int inspect_cursor_at(int argc, const char **argv) { &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; |