]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file implements the Clang-C Source Indexing library. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "CIndexer.h" | |
15 | ||
16 | #include "clang/AST/Decl.h" | |
17 | #include "clang/AST/DeclVisitor.h" | |
18 | #include "clang/AST/StmtVisitor.h" | |
19 | #include "clang/Basic/FileManager.h" | |
20 | #include "clang/Basic/SourceManager.h" | |
21 | #include "clang/Basic/Version.h" | |
22 | #include "clang/Sema/CodeCompleteConsumer.h" | |
23 | #include "llvm/ADT/StringExtras.h" | |
24 | #include "llvm/Config/llvm-config.h" | |
25 | #include "llvm/Support/Compiler.h" | |
26 | #include "llvm/Support/MemoryBuffer.h" | |
27 | #include "llvm/Support/raw_ostream.h" | |
28 | #include "llvm/Support/Program.h" | |
29 | ||
30 | #include <cstdio> | |
31 | #include <vector> | |
32 | #include <sstream> | |
33 | ||
34 | #ifdef __CYGWIN__ | |
35 | #include <cygwin/version.h> | |
36 | #include <sys/cygwin.h> | |
37 | #define LLVM_ON_WIN32 1 | |
38 | #endif | |
39 | ||
40 | #ifdef LLVM_ON_WIN32 | |
41 | #include <windows.h> | |
42 | #else | |
43 | #include <dlfcn.h> | |
44 | #endif | |
45 | ||
46 | using namespace clang; | |
47 | ||
48 | std::string CIndexer::getClangResourcesPath() { | |
49 | // Did we already compute the path? | |
50 | if (!ResourcesPath.empty()) | |
51 | return ResourcesPath.str(); | |
52 | ||
53 | // Find the location where this library lives (libclang.dylib). | |
54 | #ifdef LLVM_ON_WIN32 | |
55 | MEMORY_BASIC_INFORMATION mbi; | |
56 | char path[MAX_PATH]; | |
57 | VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi, | |
58 | sizeof(mbi)); | |
59 | GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH); | |
60 | ||
61 | #ifdef __CYGWIN__ | |
62 | char w32path[MAX_PATH]; | |
63 | strcpy(w32path, path); | |
64 | #if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181 | |
65 | cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH); | |
66 | #else | |
67 | cygwin_conv_to_full_posix_path(w32path, path); | |
68 | #endif | |
69 | #endif | |
70 | ||
71 | llvm::sys::Path LibClangPath(path); | |
72 | LibClangPath.eraseComponent(); | |
73 | #else | |
74 | // This silly cast below avoids a C++ warning. | |
75 | Dl_info info; | |
76 | if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0) | |
77 | llvm_unreachable("Call to dladdr() failed"); | |
78 | ||
79 | llvm::sys::Path LibClangPath(info.dli_fname); | |
80 | ||
81 | // We now have the CIndex directory, locate clang relative to it. | |
82 | LibClangPath.eraseComponent(); | |
83 | #endif | |
84 | ||
85 | LibClangPath.appendComponent("clang"); | |
86 | LibClangPath.appendComponent(CLANG_VERSION_STRING); | |
87 | ||
88 | // Cache our result. | |
89 | ResourcesPath = LibClangPath; | |
90 | return LibClangPath.str(); | |
91 | } | |
92 | ||
93 | static llvm::sys::Path GetTemporaryPath() { | |
94 | // FIXME: This is lame; sys::Path should provide this function (in particular, | |
95 | // it should know how to find the temporary files dir). | |
96 | std::string Error; | |
97 | const char *TmpDir = ::getenv("TMPDIR"); | |
98 | if (!TmpDir) | |
99 | TmpDir = ::getenv("TEMP"); | |
100 | if (!TmpDir) | |
101 | TmpDir = ::getenv("TMP"); | |
102 | if (!TmpDir) | |
103 | TmpDir = "/tmp"; | |
104 | llvm::sys::Path P(TmpDir); | |
105 | P.appendComponent("remap"); | |
106 | if (P.makeUnique(false, &Error)) | |
107 | return llvm::sys::Path(""); | |
108 | ||
109 | // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837. | |
110 | P.eraseFromDisk(false, 0); | |
111 | ||
112 | return P; | |
113 | } | |
114 | ||
115 | bool clang::RemapFiles(unsigned num_unsaved_files, | |
116 | struct CXUnsavedFile *unsaved_files, | |
117 | std::vector<std::string> &RemapArgs, | |
118 | std::vector<llvm::sys::Path> &TemporaryFiles) { | |
119 | for (unsigned i = 0; i != num_unsaved_files; ++i) { | |
120 | // Write the contents of this unsaved file into the temporary file. | |
121 | llvm::sys::Path SavedFile(GetTemporaryPath()); | |
122 | if (SavedFile.empty()) | |
123 | return true; | |
124 | ||
125 | std::string ErrorInfo; | |
126 | llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo, | |
127 | llvm::raw_fd_ostream::F_Binary); | |
128 | if (!ErrorInfo.empty()) | |
129 | return true; | |
130 | ||
131 | OS.write(unsaved_files[i].Contents, unsaved_files[i].Length); | |
132 | OS.close(); | |
133 | if (OS.has_error()) { | |
134 | SavedFile.eraseFromDisk(); | |
135 | OS.clear_error(); | |
136 | return true; | |
137 | } | |
138 | ||
139 | // Remap the file. | |
140 | std::string RemapArg = unsaved_files[i].Filename; | |
141 | RemapArg += ';'; | |
142 | RemapArg += SavedFile.str(); | |
143 | RemapArgs.push_back("-Xclang"); | |
144 | RemapArgs.push_back("-remap-file"); | |
145 | RemapArgs.push_back("-Xclang"); | |
146 | RemapArgs.push_back(RemapArg); | |
147 | TemporaryFiles.push_back(SavedFile); | |
148 | } | |
149 | ||
150 | return false; | |
151 | } | |
152 |