From: Steve Naroff Date: Thu, 15 Oct 2009 20:04:39 +0000 (+0000) Subject: Implement [Clang/Index] In-memory-style AST generation API... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5b7d8e254f6c2855b37b5521c0aee0a560dab237;p=clang Implement [Clang/Index] In-memory-style AST generation API (initial API implementation). Added clang_createTranslationUnitFromSourceFile(). Changed clang_createIndex() to lookup the location of clang (using dladdr). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84198 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 3178017e45..3e7ceb3d79 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -109,6 +109,12 @@ const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); CXTranslationUnit clang_createTranslationUnit( CXIndex, const char *ast_filename ); +CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, + const char *source_filename, + int num_clang_command_line_args, + const char **clang_command_line_args +); void clang_disposeTranslationUnit(CXTranslationUnit); /* diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 9204d1863d..9ab3f790ec 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -23,6 +23,9 @@ #include "clang/Basic/SourceManager.h" #include "clang/Frontend/ASTUnit.h" #include +#include +#include "llvm/System/Path.h" + using namespace clang; using namespace idx; @@ -241,9 +244,27 @@ public: extern "C" { +static const char *clangPath; + CXIndex clang_createIndex() { // FIXME: Program is leaked. + + // Find the location where this library lives (libCIndex.dylib). + // We do the lookup here to avoid poking dladdr too many times. + // This silly cast below avoids a C++ warning. + Dl_info info; + if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0) + assert(0 && "Call to dladdr() failed"); + + llvm::sys::Path CIndexPath(info.dli_fname); + std::string CIndexDir = CIndexPath.getDirname(); + + // We now have the CIndex directory, locate clang relative to it. + std::string ClangPath = CIndexDir + "/../bin/clang"; + + clangPath = ClangPath.c_str(); + return new Indexer(*new Program()); } @@ -266,6 +287,47 @@ CXTranslationUnit clang_createTranslationUnit( CXXIdx->getFileManager(), &ErrMsg); } +CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, + const char *source_filename, + int num_command_line_args, const char **command_line_args) +{ + // Generate a temporary name for the AST file. + char astTmpFile[L_tmpnam]; + + // Build up the arguments for involking clang. + const char * argv[ARG_MAX]; + int argc = 0; + argv[argc++] = clangPath; + argv[argc++] = "-emit-ast"; + argv[argc++] = source_filename; + argv[argc++] = "-o"; + argv[argc++] = tmpnam(astTmpFile); + for (int i = num_command_line_args; i < num_command_line_args; i++) + argv[argc++] = command_line_args[i]; + argv[argc] = 0; + + // Generate the AST file in a separate process. + pid_t child_pid = fork(); + if (child_pid == 0) { // Child process + + // Execute the command, passing the appropriate arguments. + execv(argv[0], (char *const *)argv); + + // If execv returns, it failed. + assert(0 && "execv() failed"); + } else { // This is run by the parent. + int child_status; + pid_t tpid; + do { // Wait for the child to terminate. + tpid = wait(&child_status); + } while (tpid != child_pid); + + // Finally, we create the translation unit from the ast file. + return clang_createTranslationUnit(CIdx, astTmpFile); + } +} + void clang_disposeTranslationUnit( CXTranslationUnit CTUnit) { diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index c1ca0c7735..ea647b46a6 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -18,6 +18,7 @@ _clang_getURI _clang_loadDeclaration _clang_loadTranslationUnit _clang_createTranslationUnit +_clang_createTranslationUnitFromSourceFile _clang_disposeTranslationUnit _clang_isDeclaration _clang_isReference