CIndexer.cpp revision d1e6fdb4c5325c61fedfa62751f70ee373880a52
174b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
274b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs//
3c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne//                     The LLVM Compiler Infrastructure
474b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs//
574b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs// This file is distributed under the University of Illinois Open Source
674b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs// License. See LICENSE.TXT for details.
774b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs//
8c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne//===----------------------------------------------------------------------===//
9c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne//
10c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne// This file implements the Clang-C Source Indexing library.
11c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne//
12c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne//===----------------------------------------------------------------------===//
13c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne
14c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne#include "CIndexer.h"
15c6eb44b321c543c5bcf28727228a0cceced57e2ePeter Collingbourne
1697f8461a2c553f68a258612d2322e4281c3f0915Andy Gibbs#include "clang/AST/Decl.h"
1797f8461a2c553f68a258612d2322e4281c3f0915Andy Gibbs#include "clang/AST/DeclVisitor.h"
1874b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "clang/AST/StmtVisitor.h"
1974b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "clang/Basic/FileManager.h"
2074b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "clang/Basic/SourceManager.h"
2174b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "clang/Basic/Version.h"
2274b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "clang/Sema/CodeCompleteConsumer.h"
2374b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/ADT/StringExtras.h"
2474b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/Config/config.h"
2574b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/Support/Compiler.h"
2674b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/Support/MemoryBuffer.h"
2774b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/Support/raw_ostream.h"
2874b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include "llvm/System/Program.h"
2974b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs
3074b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include <cstdio>
3174b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include <vector>
3274b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include <sstream>
3374b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs
3474b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#ifdef LLVM_ON_WIN32
3574b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include <windows.h>
3674b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#else
3774b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#include <dlfcn.h>
3874b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs#endif
3974b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs
4074b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbsusing namespace clang;
4174b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbs
4274b9fa16e5d1e1a5f3adb065043db46ad20a4575Andy Gibbsstd::string CIndexer::getClangResourcesPath() {
43  // Did we already compute the path?
44  if (!ResourcesPath.empty())
45    return ResourcesPath.str();
46
47  // Find the location where this library lives (libclang.dylib).
48#ifdef LLVM_ON_WIN32
49  MEMORY_BASIC_INFORMATION mbi;
50  char path[MAX_PATH];
51  VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
52               sizeof(mbi));
53  GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
54
55  llvm::sys::Path LibClangPath(path);
56  LibClangPath.eraseComponent();
57#else
58  // This silly cast below avoids a C++ warning.
59  Dl_info info;
60  if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
61    assert(0 && "Call to dladdr() failed");
62
63  llvm::sys::Path LibClangPath(info.dli_fname);
64
65  // We now have the CIndex directory, locate clang relative to it.
66  LibClangPath.eraseComponent();
67#endif
68
69  LibClangPath.appendComponent("clang");
70  LibClangPath.appendComponent(CLANG_VERSION_STRING);
71
72  // Cache our result.
73  ResourcesPath = LibClangPath;
74  return LibClangPath.str();
75}
76
77static llvm::sys::Path GetTemporaryPath() {
78  // FIXME: This is lame; sys::Path should provide this function (in particular,
79  // it should know how to find the temporary files dir).
80  std::string Error;
81  const char *TmpDir = ::getenv("TMPDIR");
82  if (!TmpDir)
83    TmpDir = ::getenv("TEMP");
84  if (!TmpDir)
85    TmpDir = ::getenv("TMP");
86  if (!TmpDir)
87    TmpDir = "/tmp";
88  llvm::sys::Path P(TmpDir);
89  P.appendComponent("remap");
90  if (P.makeUnique(false, &Error))
91    return llvm::sys::Path("");
92
93  // FIXME: Grumble, makeUnique sometimes leaves the file around!?  PR3837.
94  P.eraseFromDisk(false, 0);
95
96  return P;
97}
98
99bool clang::RemapFiles(unsigned num_unsaved_files,
100                       struct CXUnsavedFile *unsaved_files,
101                       std::vector<std::string> &RemapArgs,
102                       std::vector<llvm::sys::Path> &TemporaryFiles) {
103  for (unsigned i = 0; i != num_unsaved_files; ++i) {
104    // Write the contents of this unsaved file into the temporary file.
105    llvm::sys::Path SavedFile(GetTemporaryPath());
106    if (SavedFile.empty())
107      return true;
108
109    std::string ErrorInfo;
110    llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
111    if (!ErrorInfo.empty())
112      return true;
113
114    OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
115    OS.close();
116    if (OS.has_error()) {
117      SavedFile.eraseFromDisk();
118      OS.clear_error();
119      return true;
120    }
121
122    // Remap the file.
123    std::string RemapArg = unsaved_files[i].Filename;
124    RemapArg += ';';
125    RemapArg += SavedFile.str();
126    RemapArgs.push_back("-Xclang");
127    RemapArgs.push_back("-remap-file");
128    RemapArgs.push_back("-Xclang");
129    RemapArgs.push_back(RemapArg);
130    TemporaryFiles.push_back(SavedFile);
131  }
132
133  return false;
134}
135
136