CIndexer.cpp revision d1e6fdb4c5325c61fedfa62751f70ee373880a52
1ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
2ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//
3ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//                     The LLVM Compiler Infrastructure
4ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//
5ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek// This file is distributed under the University of Illinois Open Source
6ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek// License. See LICENSE.TXT for details.
7ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//
8ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//===----------------------------------------------------------------------===//
9ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//
10ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek// This file implements the Clang-C Source Indexing library.
11ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//
12ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek//===----------------------------------------------------------------------===//
13ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
14ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "CIndexer.h"
15ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
16ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/AST/Decl.h"
17ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/AST/DeclVisitor.h"
18ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/AST/StmtVisitor.h"
19ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/Basic/FileManager.h"
20ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/Basic/SourceManager.h"
21ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/Basic/Version.h"
22ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "clang/Sema/CodeCompleteConsumer.h"
23ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/ADT/StringExtras.h"
24ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/Config/config.h"
25ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/Support/Compiler.h"
26ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/Support/MemoryBuffer.h"
27ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/Support/raw_ostream.h"
28ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include "llvm/System/Program.h"
29ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
30ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include <cstdio>
31ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include <vector>
32ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include <sstream>
33ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
34ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#ifdef LLVM_ON_WIN32
35ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include <windows.h>
36ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#else
37ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#include <dlfcn.h>
38ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#endif
39ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
40ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenekusing namespace clang;
41ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
42d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregorstd::string CIndexer::getClangResourcesPath() {
43ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  // Did we already compute the path?
44d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  if (!ResourcesPath.empty())
45d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor    return ResourcesPath.str();
46d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor
47d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  // Find the location where this library lives (libclang.dylib).
48ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#ifdef LLVM_ON_WIN32
49ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  MEMORY_BASIC_INFORMATION mbi;
50ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  char path[MAX_PATH];
51ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
52ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek               sizeof(mbi));
53ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
54d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor
55d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  llvm::sys::Path LibClangPath(path);
56d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  LibClangPath.eraseComponent();
57ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#else
58ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  // This silly cast below avoids a C++ warning.
59ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  Dl_info info;
60ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
61ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek    assert(0 && "Call to dladdr() failed");
62d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor
63d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  llvm::sys::Path LibClangPath(info.dli_fname);
64d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor
65ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  // We now have the CIndex directory, locate clang relative to it.
66d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  LibClangPath.eraseComponent();
67ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek#endif
68d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor
69d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  LibClangPath.appendComponent("clang");
70d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  LibClangPath.appendComponent(CLANG_VERSION_STRING);
71ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek
72ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek  // Cache our result.
73d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  ResourcesPath = LibClangPath;
74d1e6fdb4c5325c61fedfa62751f70ee373880a52Douglas Gregor  return LibClangPath.str();
75ab1889321f6f8f200f2b318ac26883ac18e49d03Ted Kremenek}
764db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
77c2a981614e324fea7f0a0533f8f1d103cbd17f6dBenjamin Kramerstatic llvm::sys::Path GetTemporaryPath() {
7874198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  // FIXME: This is lame; sys::Path should provide this function (in particular,
7974198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  // it should know how to find the temporary files dir).
8074198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  std::string Error;
8174198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  const char *TmpDir = ::getenv("TMPDIR");
8274198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  if (!TmpDir)
8374198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    TmpDir = ::getenv("TEMP");
8474198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  if (!TmpDir)
8574198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    TmpDir = ::getenv("TMP");
8674198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  if (!TmpDir)
8774198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    TmpDir = "/tmp";
8874198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  llvm::sys::Path P(TmpDir);
89c2a981614e324fea7f0a0533f8f1d103cbd17f6dBenjamin Kramer  P.appendComponent("remap");
9074198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  if (P.makeUnique(false, &Error))
9174198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    return llvm::sys::Path("");
9274198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar
9374198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  // FIXME: Grumble, makeUnique sometimes leaves the file around!?  PR3837.
9474198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  P.eraseFromDisk(false, 0);
9574198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar
9674198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar  return P;
9774198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar}
9874198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar
994db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorbool clang::RemapFiles(unsigned num_unsaved_files,
1004db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                       struct CXUnsavedFile *unsaved_files,
1014db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                       std::vector<std::string> &RemapArgs,
1024db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                       std::vector<llvm::sys::Path> &TemporaryFiles) {
1034db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  for (unsigned i = 0; i != num_unsaved_files; ++i) {
1044db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    // Write the contents of this unsaved file into the temporary file.
105c2a981614e324fea7f0a0533f8f1d103cbd17f6dBenjamin Kramer    llvm::sys::Path SavedFile(GetTemporaryPath());
10674198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    if (SavedFile.empty())
10774198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar      return true;
10874198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar
1094db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    std::string ErrorInfo;
1104db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
1114db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (!ErrorInfo.empty())
1124db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return true;
1134db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1144db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
1154db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    OS.close();
1164db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (OS.has_error()) {
1174db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      SavedFile.eraseFromDisk();
118ebaf2573ccfcfef179904db1aae965b5b778c72dDan Gohman      OS.clear_error();
1194db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return true;
1204db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    }
1214db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1224db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    // Remap the file.
1234db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    std::string RemapArg = unsaved_files[i].Filename;
1244db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    RemapArg += ';';
12574198af85ea647d6483b643859adae4f2bed330bDaniel Dunbar    RemapArg += SavedFile.str();
1264db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    RemapArgs.push_back("-Xclang");
1274db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    RemapArgs.push_back("-remap-file");
1284db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    RemapArgs.push_back("-Xclang");
1294db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    RemapArgs.push_back(RemapArg);
1304db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    TemporaryFiles.push_back(SavedFile);
1314db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  }
1324db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1334db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  return false;
1344db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
1354db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
136