]> granicus.if.org Git - clang/commitdiff
Implement <rdar://problem/7303432> [Clang/Index] In-memory-style AST generation API...
authorSteve Naroff <snaroff@apple.com>
Thu, 15 Oct 2009 20:04:39 +0000 (20:04 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 15 Oct 2009 20:04:39 +0000 (20:04 +0000)
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

include/clang-c/Index.h
tools/CIndex/CIndex.cpp
tools/CIndex/CIndex.exports

index 3178017e45be85b0eebf9b2bab39e8bec6e492ad..3e7ceb3d7948263348fd4bd702fd82e43dbf0efc 100644 (file)
@@ -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);
 
 /*
index 9204d1863d67c365f7222e8a37c7fb8e34843d0e..9ab3f790ec961ab659d2fa0a853182d87902cac8 100644 (file)
@@ -23,6 +23,9 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/ASTUnit.h"
 #include <cstdio>
+#include <dlfcn.h>
+#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) 
 {
index c1ca0c77351986f3ef7644b2127dd53e8389dd6c..ea647b46a628229486b7cfdda6c01e38fb194040 100644 (file)
@@ -18,6 +18,7 @@ _clang_getURI
 _clang_loadDeclaration
 _clang_loadTranslationUnit
 _clang_createTranslationUnit
+_clang_createTranslationUnitFromSourceFile
 _clang_disposeTranslationUnit
 _clang_isDeclaration
 _clang_isReference