blob: 5312b7c0169c82ef070bc3a2fb926dea486e6213 [file] [log] [blame]
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +00001//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
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
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +000010#include "CIndexDiagnostic.h"
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000011#include "CIndexer.h"
Chandler Carruth4b417452013-01-19 08:09:44 +000012#include "CLog.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000013#include "CXCursor.h"
Benjamin Kramercfeacf52016-05-27 14:27:13 +000014#include "CXIndexDataConsumer.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000015#include "CXSourceLocation.h"
16#include "CXString.h"
17#include "CXTranslationUnit.h"
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000018#include "clang/AST/ASTConsumer.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000019#include "clang/Frontend/ASTUnit.h"
20#include "clang/Frontend/CompilerInstance.h"
21#include "clang/Frontend/CompilerInvocation.h"
22#include "clang/Frontend/FrontendAction.h"
23#include "clang/Frontend/Utils.h"
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000024#include "clang/Index/IndexingAction.h"
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000025#include "clang/Lex/HeaderSearch.h"
Chandler Carruth44eb4f62013-01-02 10:28:36 +000026#include "clang/Lex/PPCallbacks.h"
27#include "clang/Lex/PPConditionalDirectiveRecord.h"
28#include "clang/Lex/Preprocessor.h"
Mehdi Amini9670f842016-07-18 19:02:11 +000029#include "clang/Lex/PreprocessorOptions.h"
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000030#include "llvm/Support/CrashRecoveryContext.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000031#include "llvm/Support/MemoryBuffer.h"
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000032#include "llvm/Support/Mutex.h"
33#include "llvm/Support/MutexGuard.h"
Dmitri Gribenkoab458a12013-08-19 16:14:33 +000034#include <cstdio>
Benjamin Kramercfeacf52016-05-27 14:27:13 +000035#include <utility>
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000036
37using namespace clang;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000038using namespace clang::index;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +000039using namespace cxtu;
40using namespace cxindex;
41
42namespace {
43
44//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000045// Skip Parsed Bodies
46//===----------------------------------------------------------------------===//
47
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000048/// \brief A "region" in source code identified by the file/offset of the
49/// preprocessor conditional directive that it belongs to.
50/// Multiple, non-consecutive ranges can be parts of the same region.
51///
52/// As an example of different regions separated by preprocessor directives:
53///
54/// \code
55/// #1
56/// #ifdef BLAH
57/// #2
58/// #ifdef CAKE
59/// #3
60/// #endif
61/// #2
62/// #endif
63/// #1
64/// \endcode
65///
66/// There are 3 regions, with non-consecutive parts:
67/// #1 is identified as the beginning of the file
68/// #2 is identified as the location of "#ifdef BLAH"
69/// #3 is identified as the location of "#ifdef CAKE"
70///
71class PPRegion {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +000072 llvm::sys::fs::UniqueID UniqueID;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000073 time_t ModTime;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000074 unsigned Offset;
75public:
Alexey Samsonovc04b5cd2013-08-02 09:06:39 +000076 PPRegion() : UniqueID(0, 0), ModTime(), Offset() {}
Rafael Espindolaf8f91b82013-08-01 21:42:11 +000077 PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime)
78 : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {}
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000079
Rafael Espindolaf8f91b82013-08-01 21:42:11 +000080 const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000081 unsigned getOffset() const { return Offset; }
82 time_t getModTime() const { return ModTime; }
83
84 bool isInvalid() const { return *this == PPRegion(); }
85
86 friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +000087 return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset &&
88 lhs.ModTime == rhs.ModTime;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +000089 }
90};
91
92typedef llvm::DenseSet<PPRegion> PPRegionSetTy;
93
94} // end anonymous namespace
95
96namespace llvm {
97 template <> struct isPodLike<PPRegion> {
98 static const bool value = true;
99 };
100
101 template <>
102 struct DenseMapInfo<PPRegion> {
103 static inline PPRegion getEmptyKey() {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000104 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000105 }
106 static inline PPRegion getTombstoneKey() {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000107 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000108 }
109
110 static unsigned getHashValue(const PPRegion &S) {
111 llvm::FoldingSetNodeID ID;
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000112 const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
113 ID.AddInteger(UniqueID.getFile());
114 ID.AddInteger(UniqueID.getDevice());
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000115 ID.AddInteger(S.getOffset());
116 ID.AddInteger(S.getModTime());
117 return ID.ComputeHash();
118 }
119
120 static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
121 return LHS == RHS;
122 }
123 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000124}
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000125
126namespace {
127
128class SessionSkipBodyData {
129 llvm::sys::Mutex Mux;
130 PPRegionSetTy ParsedRegions;
131
132public:
133 SessionSkipBodyData() : Mux(/*recursive=*/false) {}
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +0000134 ~SessionSkipBodyData() {
135 //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n";
136 }
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000137
138 void copyTo(PPRegionSetTy &Set) {
139 llvm::MutexGuard MG(Mux);
140 Set = ParsedRegions;
141 }
142
143 void update(ArrayRef<PPRegion> Regions) {
144 llvm::MutexGuard MG(Mux);
145 ParsedRegions.insert(Regions.begin(), Regions.end());
146 }
147};
148
149class TUSkipBodyControl {
150 SessionSkipBodyData &SessionData;
151 PPConditionalDirectiveRecord &PPRec;
152 Preprocessor &PP;
153
154 PPRegionSetTy ParsedRegions;
155 SmallVector<PPRegion, 32> NewParsedRegions;
156 PPRegion LastRegion;
157 bool LastIsParsed;
158
159public:
160 TUSkipBodyControl(SessionSkipBodyData &sessionData,
161 PPConditionalDirectiveRecord &ppRec,
162 Preprocessor &pp)
163 : SessionData(sessionData), PPRec(ppRec), PP(pp) {
164 SessionData.copyTo(ParsedRegions);
165 }
166
167 bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
168 PPRegion region = getRegion(Loc, FID, FE);
169 if (region.isInvalid())
170 return false;
171
172 // Check common case, consecutive functions in the same region.
173 if (LastRegion == region)
174 return LastIsParsed;
175
176 LastRegion = region;
177 LastIsParsed = ParsedRegions.count(region);
178 if (!LastIsParsed)
179 NewParsedRegions.push_back(region);
180 return LastIsParsed;
181 }
182
183 void finished() {
184 SessionData.update(NewParsedRegions);
185 }
186
187private:
188 PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
189 SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
190 if (RegionLoc.isInvalid()) {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000191 if (isParsedOnceInclude(FE)) {
192 const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
193 return PPRegion(ID, 0, FE->getModificationTime());
194 }
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000195 return PPRegion();
196 }
197
198 const SourceManager &SM = PPRec.getSourceManager();
199 assert(RegionLoc.isFileID());
200 FileID RegionFID;
201 unsigned RegionOffset;
Benjamin Kramer867ea1d2014-03-02 13:01:17 +0000202 std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000203
204 if (RegionFID != FID) {
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000205 if (isParsedOnceInclude(FE)) {
206 const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
207 return PPRegion(ID, 0, FE->getModificationTime());
208 }
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000209 return PPRegion();
210 }
211
Rafael Espindolaf8f91b82013-08-01 21:42:11 +0000212 const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
213 return PPRegion(ID, RegionOffset, FE->getModificationTime());
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000214 }
215
216 bool isParsedOnceInclude(const FileEntry *FE) {
217 return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
218 }
219};
220
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000221//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000222// IndexPPCallbacks
223//===----------------------------------------------------------------------===//
224
225class IndexPPCallbacks : public PPCallbacks {
226 Preprocessor &PP;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000227 CXIndexDataConsumer &DataConsumer;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000228 bool IsMainFileEntered;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000229
230public:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000231 IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
232 : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000233
Craig Topper36835562014-03-15 07:47:46 +0000234 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
235 SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000236 if (IsMainFileEntered)
237 return;
238
239 SourceManager &SM = PP.getSourceManager();
240 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
241
242 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
243 IsMainFileEntered = true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000244 DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000245 }
246 }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000247
Craig Topper36835562014-03-15 07:47:46 +0000248 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
249 StringRef FileName, bool IsAngled,
250 CharSourceRange FilenameRange, const FileEntry *File,
251 StringRef SearchPath, StringRef RelativePath,
252 const Module *Imported) override {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000253 bool isImport = (IncludeTok.is(tok::identifier) &&
254 IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000255 DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
Argyrios Kyrtzidis5e2ec482012-10-18 00:17:05 +0000256 Imported);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000257 }
258
259 /// MacroDefined - This hook is called whenever a macro definition is seen.
Craig Topper36835562014-03-15 07:47:46 +0000260 void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000261
262 /// MacroUndefined - This hook is called whenever a macro #undef is seen.
263 /// MI is released immediately following this callback.
Craig Topper36835562014-03-15 07:47:46 +0000264 void MacroUndefined(const Token &MacroNameTok,
Vedant Kumar349a6242017-04-26 21:05:44 +0000265 const MacroDefinition &MD,
266 const MacroDirective *UD) override {}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000267
268 /// MacroExpands - This is called by when a macro invocation is found.
Richard Smith36bd40d2015-05-04 03:15:40 +0000269 void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
Craig Topper36835562014-03-15 07:47:46 +0000270 SourceRange Range, const MacroArgs *Args) override {}
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000271
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000272 /// SourceRangeSkipped - This hook is called when a source range is skipped.
273 /// \param Range The SourceRange that was skipped. The range begins at the
274 /// #if/#else directive and ends after the #endif/#else directive.
Craig Topper36835562014-03-15 07:47:46 +0000275 void SourceRangeSkipped(SourceRange Range) override {}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000276};
277
278//===----------------------------------------------------------------------===//
279// IndexingConsumer
280//===----------------------------------------------------------------------===//
281
282class IndexingConsumer : public ASTConsumer {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000283 CXIndexDataConsumer &DataConsumer;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000284 TUSkipBodyControl *SKCtrl;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000285
286public:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000287 IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
288 : DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000289
290 // ASTConsumer Implementation
291
Craig Topper36835562014-03-15 07:47:46 +0000292 void Initialize(ASTContext &Context) override {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000293 DataConsumer.setASTContext(Context);
294 DataConsumer.startedTranslationUnit();
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000295 }
296
Craig Topper36835562014-03-15 07:47:46 +0000297 void HandleTranslationUnit(ASTContext &Ctx) override {
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000298 if (SKCtrl)
299 SKCtrl->finished();
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000300 }
301
Craig Topper36835562014-03-15 07:47:46 +0000302 bool HandleTopLevelDecl(DeclGroupRef DG) override {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000303 return !DataConsumer.shouldAbort();
Argyrios Kyrtzidise5dc5b32012-02-10 20:10:44 +0000304 }
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000305
Craig Topper36835562014-03-15 07:47:46 +0000306 bool shouldSkipFunctionBody(Decl *D) override {
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000307 if (!SKCtrl) {
308 // Always skip bodies.
309 return true;
310 }
311
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000312 const SourceManager &SM = DataConsumer.getASTContext().getSourceManager();
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000313 SourceLocation Loc = D->getLocation();
314 if (Loc.isMacroID())
315 return false;
316 if (SM.isInSystemHeader(Loc))
317 return true; // always skip bodies from system headers.
318
319 FileID FID;
320 unsigned Offset;
Benjamin Kramer867ea1d2014-03-02 13:01:17 +0000321 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000322 // Don't skip bodies from main files; this may be revisited.
323 if (SM.getMainFileID() == FID)
324 return false;
325 const FileEntry *FE = SM.getFileEntryForID(FID);
326 if (!FE)
327 return false;
328
329 return SKCtrl->isParsed(Loc, FID, FE);
330 }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000331};
332
333//===----------------------------------------------------------------------===//
Argyrios Kyrtzidiseffdbf52011-11-18 00:26:51 +0000334// CaptureDiagnosticConsumer
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000335//===----------------------------------------------------------------------===//
336
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000337class CaptureDiagnosticConsumer : public DiagnosticConsumer {
338 SmallVector<StoredDiagnostic, 4> Errors;
339public:
340
Craig Topper36835562014-03-15 07:47:46 +0000341 void HandleDiagnostic(DiagnosticsEngine::Level level,
342 const Diagnostic &Info) override {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000343 if (level >= DiagnosticsEngine::Error)
344 Errors.push_back(StoredDiagnostic(level, Info));
345 }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000346};
347
348//===----------------------------------------------------------------------===//
349// IndexingFrontendAction
350//===----------------------------------------------------------------------===//
351
352class IndexingFrontendAction : public ASTFrontendAction {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000353 std::shared_ptr<CXIndexDataConsumer> DataConsumer;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000354
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000355 SessionSkipBodyData *SKData;
Ahmed Charlesb8984322014-03-07 20:03:18 +0000356 std::unique_ptr<TUSkipBodyControl> SKCtrl;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000357
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000358public:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000359 IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000360 SessionSkipBodyData *skData)
Benjamin Kramercfeacf52016-05-27 14:27:13 +0000361 : DataConsumer(std::move(dataConsumer)), SKData(skData) {}
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000362
David Blaikie6beb6aa2014-08-10 19:56:51 +0000363 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
364 StringRef InFile) override {
Argyrios Kyrtzidisf484b132012-10-03 21:05:51 +0000365 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
366
Argyrios Kyrtzidisf484b132012-10-03 21:05:51 +0000367 if (!PPOpts.ImplicitPCHInclude.empty()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000368 DataConsumer->importedPCH(
Argyrios Kyrtzidisf484b132012-10-03 21:05:51 +0000369 CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
370 }
Argyrios Kyrtzidisb36ee5c2012-10-02 16:10:41 +0000371
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000372 DataConsumer->setASTContext(CI.getASTContext());
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000373 Preprocessor &PP = CI.getPreprocessor();
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000374 PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
David Blaikie41565462017-01-05 19:48:07 +0000375 DataConsumer->setPreprocessor(CI.getPreprocessorPtr());
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000376
377 if (SKData) {
David Blaikie6beb6aa2014-08-10 19:56:51 +0000378 auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
Craig Topperb8a70532014-09-10 04:53:53 +0000379 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
David Blaikie6beb6aa2014-08-10 19:56:51 +0000380 SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000381 }
382
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000383 return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +0000384 }
385
Craig Topper36835562014-03-15 07:47:46 +0000386 TranslationUnitKind getTranslationUnitKind() override {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000387 if (DataConsumer->shouldIndexImplicitTemplateInsts())
Argyrios Kyrtzidis7e747952012-02-14 22:23:11 +0000388 return TU_Complete;
389 else
390 return TU_Prefix;
391 }
Craig Topper36835562014-03-15 07:47:46 +0000392 bool hasCodeCompletionSupport() const override { return false; }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000393};
394
395//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000396// clang_indexSourceFileUnit Implementation
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000397//===----------------------------------------------------------------------===//
398
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000399static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
400 IndexingOptions IdxOpts;
401 if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
402 IdxOpts.IndexFunctionLocals = true;
403 return IdxOpts;
404}
405
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000406struct IndexSessionData {
407 CXIndex CIdx;
Ahmed Charlesb8984322014-03-07 20:03:18 +0000408 std::unique_ptr<SessionSkipBodyData> SkipBodyData;
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000409
410 explicit IndexSessionData(CXIndex cIdx)
411 : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
412};
413
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000414} // anonymous namespace
415
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000416static CXErrorCode clang_indexSourceFile_Impl(
417 CXIndexAction cxIdxAction, CXClientData client_data,
418 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
419 unsigned index_options, const char *source_filename,
420 const char *const *command_line_args, int num_command_line_args,
421 ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU,
422 unsigned TU_options) {
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000423 if (out_TU)
Craig Topper69186e72014-06-08 08:38:04 +0000424 *out_TU = nullptr;
425 bool requestedToGetTU = (out_TU != nullptr);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000426
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000427 if (!cxIdxAction) {
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000428 return CXError_InvalidArguments;
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000429 }
430 if (!client_index_callbacks || index_callbacks_size == 0) {
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000431 return CXError_InvalidArguments;
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000432 }
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000433
434 IndexerCallbacks CB;
435 memset(&CB, 0, sizeof(CB));
436 unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
437 ? index_callbacks_size : sizeof(CB);
438 memcpy(&CB, client_index_callbacks, ClientCBSize);
439
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000440 IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction);
441 CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000442
Argyrios Kyrtzidis7317a5c2012-03-28 02:18:05 +0000443 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
Argyrios Kyrtzidis58d5f3f2012-03-28 02:49:54 +0000444 setThreadBackgroundPriority();
Argyrios Kyrtzidis7317a5c2012-03-28 02:18:05 +0000445
Argyrios Kyrtzidis828f4d42013-03-29 21:51:44 +0000446 bool CaptureDiagnostics = !Logger::isLoggingEnabled();
447
Craig Topper69186e72014-06-08 08:38:04 +0000448 CaptureDiagnosticConsumer *CaptureDiag = nullptr;
Argyrios Kyrtzidis828f4d42013-03-29 21:51:44 +0000449 if (CaptureDiagnostics)
450 CaptureDiag = new CaptureDiagnosticConsumer();
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000451
452 // Configure the diagnostics.
Dylan Noblesmithc95d8192012-02-20 14:00:23 +0000453 IntrusiveRefCntPtr<DiagnosticsEngine>
Douglas Gregor811db4e2012-10-23 22:26:28 +0000454 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
Douglas Gregor811db4e2012-10-23 22:26:28 +0000455 CaptureDiag,
Douglas Gregor30071cea2013-05-03 23:07:45 +0000456 /*ShouldOwnClient=*/true));
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000457
458 // Recover resources if we crash before exiting this function.
459 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
460 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
Alp Tokerf994cef2014-07-05 03:08:06 +0000461 DiagCleanup(Diags.get());
Ahmed Charlesb8984322014-03-07 20:03:18 +0000462
463 std::unique_ptr<std::vector<const char *>> Args(
464 new std::vector<const char *>());
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000465
466 // Recover resources if we crash before exiting this method.
467 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
468 ArgsCleanup(Args.get());
469
470 Args->insert(Args->end(), command_line_args,
471 command_line_args + num_command_line_args);
472
473 // The 'source_filename' argument is optional. If the caller does not
474 // specify it then it is assumed that the source file is specified
475 // in the actual argument list.
476 // Put the source file after command_line_args otherwise if '-x' flag is
477 // present it will be unused.
478 if (source_filename)
479 Args->push_back(source_filename);
David Blaikieea4395e2017-01-06 19:49:01 +0000480
481 std::shared_ptr<CompilerInvocation> CInvok =
482 createInvocationFromCommandLine(*Args, Diags);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000483
484 if (!CInvok)
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000485 return CXError_Failure;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000486
487 // Recover resources if we crash before exiting this function.
David Blaikieea4395e2017-01-06 19:49:01 +0000488 llvm::CrashRecoveryContextCleanupRegistrar<
489 std::shared_ptr<CompilerInvocation>,
490 llvm::CrashRecoveryContextDestructorCleanup<
491 std::shared_ptr<CompilerInvocation>>>
492 CInvokCleanup(&CInvok);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000493
494 if (CInvok->getFrontendOpts().Inputs.empty())
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000495 return CXError_Failure;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000496
Alp Toker9d85b182014-07-07 01:23:14 +0000497 typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
498 std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000499
500 // Recover resources if we crash before exiting this method.
Alp Toker9d85b182014-07-07 01:23:14 +0000501 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
502 BufOwner.get());
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000503
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000504 for (auto &UF : unsaved_files) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000505 std::unique_ptr<llvm::MemoryBuffer> MB =
Alp Toker9d85b182014-07-07 01:23:14 +0000506 llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000507 CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
508 BufOwner->push_back(std::move(MB));
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000509 }
510
511 // Since libclang is primarily used by batch tools dealing with
512 // (often very broken) source code, where spell-checking can have a
513 // significant negative impact on performance (particularly when
514 // precompiled headers are involved), we disable it.
Ted Kremenek8cf47df2011-11-17 23:01:24 +0000515 CInvok->getLangOpts()->SpellChecking = false;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000516
Argyrios Kyrtzidis6c9ed7d2012-03-27 21:38:03 +0000517 if (index_options & CXIndexOpt_SuppressWarnings)
518 CInvok->getDiagnosticOpts().IgnoreWarnings = true;
519
Argyrios Kyrtzidisa3e2ff12015-11-20 03:36:21 +0000520 // Make sure to use the raw module format.
521 CInvok->getHeaderSearchOpts().ModuleFormat =
522 CXXIdx->getPCHContainerOperations()->getRawReader().getFormat();
523
David Blaikieea4395e2017-01-06 19:49:01 +0000524 auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics,
525 /*UserFilesAreVolatile=*/true);
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000526 if (!Unit)
527 return CXError_InvalidArguments;
Ben Langmuir8832c062014-04-15 18:16:25 +0000528
David Blaikieea4395e2017-01-06 19:49:01 +0000529 auto *UPtr = Unit.get();
Ahmed Charlesb8984322014-03-07 20:03:18 +0000530 std::unique_ptr<CXTUOwner> CXTU(
David Blaikieea4395e2017-01-06 19:49:01 +0000531 new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit))));
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000532
533 // Recover resources if we crash before exiting this method.
534 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
535 CXTUCleanup(CXTU.get());
536
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000537 // Enable the skip-parsed-bodies optimization only for C++; this may be
538 // revisited.
539 bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) &&
540 CInvok->getLangOpts()->CPlusPlus;
541 if (SkipBodies)
542 CInvok->getFrontendOpts().SkipFunctionBodies = true;
543
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000544 auto DataConsumer =
545 std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
546 CXTU->getTU());
547 auto InterAction = llvm::make_unique<IndexingFrontendAction>(DataConsumer,
548 SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
549 std::unique_ptr<FrontendAction> IndexAction;
Argyrios Kyrtzidis469c1362016-02-14 06:39:03 +0000550 IndexAction = createIndexingAction(DataConsumer,
551 getIndexingOptionsFromCXOptions(index_options),
552 std::move(InterAction));
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000553
554 // Recover resources if we crash before exiting this method.
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000555 llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000556 IndexActionCleanup(IndexAction.get());
557
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000558 bool Persistent = requestedToGetTU;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000559 bool OnlyLocalDecls = false;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000560 bool PrecompilePreamble = false;
Benjamin Kramer5c248d82015-12-15 09:30:31 +0000561 bool CreatePreambleOnFirstParse = false;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000562 bool CacheCodeCompletionResults = false;
563 PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
Argyrios Kyrtzidis4a280ff2012-03-07 01:51:17 +0000564 PPOpts.AllowPCHWithCompilerErrors = true;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000565
566 if (requestedToGetTU) {
567 OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
568 PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
Benjamin Kramer5c248d82015-12-15 09:30:31 +0000569 CreatePreambleOnFirstParse =
570 TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000571 // FIXME: Add a flag for modules.
572 CacheCodeCompletionResults
573 = TU_options & CXTranslationUnit_CacheCompletionResults;
Argyrios Kyrtzidisb11f5a42011-11-28 04:56:00 +0000574 }
575
Argyrios Kyrtzidis6a80e752012-10-06 01:18:35 +0000576 if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
577 PPOpts.DetailedRecord = true;
578 }
Argyrios Kyrtzidisb36ee5c2012-10-02 16:10:41 +0000579
Argyrios Kyrtzidis15f6b8e2012-10-10 02:12:50 +0000580 if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
581 PPOpts.DetailedRecord = false;
582
Benjamin Kramer5c248d82015-12-15 09:30:31 +0000583 // Unless the user specified that they want the preamble on the first parse
584 // set it up to be created on the first reparse. This makes the first parse
585 // faster, trading for a slower (first) reparse.
586 unsigned PrecompilePreambleAfterNParses =
587 !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
Argyrios Kyrtzidisac1cc932012-04-11 02:11:16 +0000588 DiagnosticErrorTrap DiagTrap(*Diags);
Adrian Prantlbb165fb2015-06-20 18:53:08 +0000589 bool Success = ASTUnit::LoadFromCompilerInvocationAction(
David Blaikieea4395e2017-01-06 19:49:01 +0000590 std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags,
591 IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(),
Benjamin Kramer5c248d82015-12-15 09:30:31 +0000592 OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
Adrian Prantlbb165fb2015-06-20 18:53:08 +0000593 CacheCodeCompletionResults,
594 /*IncludeBriefCommentsInCodeCompletion=*/false,
595 /*UserFilesAreVolatile=*/true);
Argyrios Kyrtzidisac1cc932012-04-11 02:11:16 +0000596 if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
David Blaikieea4395e2017-01-06 19:49:01 +0000597 printDiagsToStderr(UPtr);
Argyrios Kyrtzidisac1cc932012-04-11 02:11:16 +0000598
David Blaikieea4395e2017-01-06 19:49:01 +0000599 if (isASTReadError(UPtr))
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000600 return CXError_ASTReadError;
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000601
Argyrios Kyrtzidisac1cc932012-04-11 02:11:16 +0000602 if (!Success)
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000603 return CXError_Failure;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000604
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000605 if (out_TU)
606 *out_TU = CXTU->takeTU();
607
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000608 return CXError_Success;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000609}
610
611//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000612// clang_indexTranslationUnit Implementation
613//===----------------------------------------------------------------------===//
614
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000615static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000616 Preprocessor &PP = Unit.getPreprocessor();
617 if (!PP.getPreprocessingRecord())
618 return;
619
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000620 // FIXME: Only deserialize inclusion directives.
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000621
Argyrios Kyrtzidise445c722012-10-10 02:12:47 +0000622 bool isModuleFile = Unit.isModuleFile();
Benjamin Kramerb4ef6682015-02-06 17:25:10 +0000623 for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) {
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000624 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
Argyrios Kyrtzidis5e2ec482012-10-18 00:17:05 +0000625 SourceLocation Loc = ID->getSourceRange().getBegin();
626 // Modules have synthetic main files as input, give an invalid location
627 // if the location points to such a file.
628 if (isModuleFile && Unit.isInMainFileID(Loc))
629 Loc = SourceLocation();
630 IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
631 ID->getFile(),
632 ID->getKind() == InclusionDirective::Import,
633 !ID->wasInQuotes(), ID->importedModule());
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000634 }
635 }
636}
637
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000638static CXErrorCode clang_indexTranslationUnit_Impl(
639 CXIndexAction idxAction, CXClientData client_data,
640 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
641 unsigned index_options, CXTranslationUnit TU) {
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000642 // Check arguments.
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000643 if (isNotUsableTU(TU)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000644 LOG_BAD_TU(TU);
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000645 return CXError_InvalidArguments;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000646 }
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000647 if (!client_index_callbacks || index_callbacks_size == 0) {
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000648 return CXError_InvalidArguments;
Dmitri Gribenkoea4d1c32014-02-12 19:12:37 +0000649 }
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000650
Dmitri Gribenko183436e2013-01-26 21:49:50 +0000651 CIndexer *CXXIdx = TU->CIdx;
Argyrios Kyrtzidis7317a5c2012-03-28 02:18:05 +0000652 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
Argyrios Kyrtzidis58d5f3f2012-03-28 02:49:54 +0000653 setThreadBackgroundPriority();
Argyrios Kyrtzidis7317a5c2012-03-28 02:18:05 +0000654
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000655 IndexerCallbacks CB;
656 memset(&CB, 0, sizeof(CB));
657 unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
658 ? index_callbacks_size : sizeof(CB);
659 memcpy(&CB, client_index_callbacks, ClientCBSize);
660
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000661 auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
662 index_options, TU);
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000663
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000664 ASTUnit *Unit = cxtu::getASTUnit(TU);
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000665 if (!Unit)
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000666 return CXError_Failure;
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000667
Argyrios Kyrtzidis341de092012-09-25 19:29:50 +0000668 ASTUnit::ConcurrencyCheck Check(*Unit);
669
Argyrios Kyrtzidisf484b132012-10-03 21:05:51 +0000670 if (const FileEntry *PCHFile = Unit->getPCHFile())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000671 DataConsumer->importedPCH(PCHFile);
Argyrios Kyrtzidisf484b132012-10-03 21:05:51 +0000672
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000673 FileManager &FileMgr = Unit->getFileManager();
674
675 if (Unit->getOriginalSourceFileName().empty())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000676 DataConsumer->enteredMainFile(nullptr);
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000677 else
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000678 DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000679
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000680 DataConsumer->setASTContext(Unit->getASTContext());
681 DataConsumer->startedTranslationUnit();
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000682
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000683 indexPreprocessingRecord(*Unit, *DataConsumer);
684 indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
685 DataConsumer->indexDiagnostics();
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000686
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000687 return CXError_Success;
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000688}
689
690//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000691// libclang public APIs.
692//===----------------------------------------------------------------------===//
693
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000694int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
695 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
696}
697
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000698const CXIdxObjCContainerDeclInfo *
699clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
700 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000701 return nullptr;
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000702
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000703 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
704 if (const ObjCContainerDeclInfo *
705 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
706 return &ContInfo->ObjCContDeclInfo;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000707
Craig Topper69186e72014-06-08 08:38:04 +0000708 return nullptr;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000709}
710
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000711const CXIdxObjCInterfaceDeclInfo *
712clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000713 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000714 return nullptr;
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000715
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000716 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
717 if (const ObjCInterfaceDeclInfo *
718 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
719 return &InterInfo->ObjCInterDeclInfo;
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000720
Craig Topper69186e72014-06-08 08:38:04 +0000721 return nullptr;
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000722}
723
724const CXIdxObjCCategoryDeclInfo *
725clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000726 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000727 return nullptr;
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000728
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000729 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
730 if (const ObjCCategoryDeclInfo *
731 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
732 return &CatInfo->ObjCCatDeclInfo;
733
Craig Topper69186e72014-06-08 08:38:04 +0000734 return nullptr;
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000735}
736
737const CXIdxObjCProtocolRefListInfo *
738clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
739 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000740 return nullptr;
Argyrios Kyrtzidis86acd722011-11-14 22:39:19 +0000741
742 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
743
744 if (const ObjCInterfaceDeclInfo *
745 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
746 return InterInfo->ObjCInterDeclInfo.protocols;
747
748 if (const ObjCProtocolDeclInfo *
749 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
750 return &ProtInfo->ObjCProtoRefListInfo;
751
Argyrios Kyrtzidis9b9f7a92011-12-13 18:47:45 +0000752 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
753 return CatInfo->ObjCCatDeclInfo.protocols;
754
Craig Topper69186e72014-06-08 08:38:04 +0000755 return nullptr;
Argyrios Kyrtzidis3e429e72011-11-12 02:16:30 +0000756}
757
Argyrios Kyrtzidis93db2922012-02-28 17:50:33 +0000758const CXIdxObjCPropertyDeclInfo *
759clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
760 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000761 return nullptr;
Argyrios Kyrtzidis93db2922012-02-28 17:50:33 +0000762
763 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
764 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
765 return &PropInfo->ObjCPropDeclInfo;
766
Craig Topper69186e72014-06-08 08:38:04 +0000767 return nullptr;
Argyrios Kyrtzidis93db2922012-02-28 17:50:33 +0000768}
769
Argyrios Kyrtzidiseffdbf52011-11-18 00:26:51 +0000770const CXIdxIBOutletCollectionAttrInfo *
771clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
772 if (!AInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000773 return nullptr;
Argyrios Kyrtzidiseffdbf52011-11-18 00:26:51 +0000774
775 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
776 if (const IBOutletCollectionInfo *
777 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
778 return &IBInfo->IBCollInfo;
779
Craig Topper69186e72014-06-08 08:38:04 +0000780 return nullptr;
Argyrios Kyrtzidiseffdbf52011-11-18 00:26:51 +0000781}
782
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000783const CXIdxCXXClassDeclInfo *
784clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
785 if (!DInfo)
Craig Topper69186e72014-06-08 08:38:04 +0000786 return nullptr;
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000787
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000788 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
789 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
790 return &ClassInfo->CXXClassInfo;
791
Craig Topper69186e72014-06-08 08:38:04 +0000792 return nullptr;
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000793}
794
795CXIdxClientContainer
796clang_index_getClientContainer(const CXIdxContainerInfo *info) {
797 if (!info)
Craig Topper69186e72014-06-08 08:38:04 +0000798 return nullptr;
Benjamin Kramer7f107ee2011-11-29 12:31:20 +0000799 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000800 return Container->IndexCtx->getClientContainerForDC(Container->DC);
801}
802
803void clang_index_setClientContainer(const CXIdxContainerInfo *info,
804 CXIdxClientContainer client) {
805 if (!info)
806 return;
Benjamin Kramer7f107ee2011-11-29 12:31:20 +0000807 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000808 Container->IndexCtx->addContainerInMap(Container->DC, client);
809}
810
811CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
812 if (!info)
Craig Topper69186e72014-06-08 08:38:04 +0000813 return nullptr;
Benjamin Kramer7f107ee2011-11-29 12:31:20 +0000814 const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000815 return Entity->IndexCtx->getClientEntity(Entity->Dcl);
816}
817
818void clang_index_setClientEntity(const CXIdxEntityInfo *info,
819 CXIdxClientEntity client) {
820 if (!info)
821 return;
Benjamin Kramer7f107ee2011-11-29 12:31:20 +0000822 const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000823 Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
824}
825
826CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000827 return new IndexSessionData(CIdx);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000828}
829
830void clang_IndexAction_dispose(CXIndexAction idxAction) {
Argyrios Kyrtzidis8b71bc72012-12-06 19:41:16 +0000831 if (idxAction)
832 delete static_cast<IndexSessionData *>(idxAction);
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000833}
834
835int clang_indexSourceFile(CXIndexAction idxAction,
836 CXClientData client_data,
837 IndexerCallbacks *index_callbacks,
838 unsigned index_callbacks_size,
839 unsigned index_options,
840 const char *source_filename,
841 const char * const *command_line_args,
842 int num_command_line_args,
843 struct CXUnsavedFile *unsaved_files,
844 unsigned num_unsaved_files,
845 CXTranslationUnit *out_TU,
846 unsigned TU_options) {
Benjamin Kramerc02670e2015-11-18 16:14:27 +0000847 SmallVector<const char *, 4> Args;
848 Args.push_back("clang");
849 Args.append(command_line_args, command_line_args + num_command_line_args);
850 return clang_indexSourceFileFullArgv(
851 idxAction, client_data, index_callbacks, index_callbacks_size,
852 index_options, source_filename, Args.data(), Args.size(), unsaved_files,
853 num_unsaved_files, out_TU, TU_options);
854}
855
856int clang_indexSourceFileFullArgv(
857 CXIndexAction idxAction, CXClientData client_data,
858 IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
859 unsigned index_options, const char *source_filename,
860 const char *const *command_line_args, int num_command_line_args,
861 struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
862 CXTranslationUnit *out_TU, unsigned TU_options) {
Argyrios Kyrtzidisea474352013-01-10 18:54:52 +0000863 LOG_FUNC_SECTION {
864 *Log << source_filename << ": ";
865 for (int i = 0; i != num_command_line_args; ++i)
866 *Log << command_line_args[i] << " ";
867 }
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000868
Alp Toker9d85b182014-07-07 01:23:14 +0000869 if (num_unsaved_files && !unsaved_files)
870 return CXError_InvalidArguments;
871
Alp Toker5c532982014-07-07 22:42:03 +0000872 CXErrorCode result = CXError_Failure;
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000873 auto IndexSourceFileImpl = [=, &result]() {
874 result = clang_indexSourceFile_Impl(
875 idxAction, client_data, index_callbacks, index_callbacks_size,
876 index_options, source_filename, command_line_args,
877 num_command_line_args,
878 llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU,
879 TU_options);
880 };
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000881
Argyrios Kyrtzidis97805532011-10-29 19:32:39 +0000882 if (getenv("LIBCLANG_NOTHREADS")) {
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000883 IndexSourceFileImpl();
Alp Toker5c532982014-07-07 22:42:03 +0000884 return result;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000885 }
886
887 llvm::CrashRecoveryContext CRC;
888
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000889 if (!RunSafely(CRC, IndexSourceFileImpl)) {
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000890 fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000891 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
892 fprintf(stderr, " 'command_line_args' : [");
893 for (int i = 0; i != num_command_line_args; ++i) {
894 if (i)
895 fprintf(stderr, ", ");
896 fprintf(stderr, "'%s'", command_line_args[i]);
897 }
898 fprintf(stderr, "],\n");
899 fprintf(stderr, " 'unsaved_files' : [");
900 for (unsigned i = 0; i != num_unsaved_files; ++i) {
901 if (i)
902 fprintf(stderr, ", ");
903 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
904 unsaved_files[i].Length);
905 }
906 fprintf(stderr, "],\n");
907 fprintf(stderr, " 'options' : %d,\n", TU_options);
908 fprintf(stderr, "}\n");
909
910 return 1;
911 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
912 if (out_TU)
913 PrintLibclangResourceUsage(*out_TU);
914 }
Alp Toker5c532982014-07-07 22:42:03 +0000915
916 return result;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000917}
918
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000919int clang_indexTranslationUnit(CXIndexAction idxAction,
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000920 CXClientData client_data,
921 IndexerCallbacks *index_callbacks,
922 unsigned index_callbacks_size,
Argyrios Kyrtzidis4c910b12011-11-22 07:24:51 +0000923 unsigned index_options,
924 CXTranslationUnit TU) {
Argyrios Kyrtzidisea474352013-01-10 18:54:52 +0000925 LOG_FUNC_SECTION {
926 *Log << TU;
927 }
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000928
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000929 CXErrorCode result;
930 auto IndexTranslationUnitImpl = [=, &result]() {
931 result = clang_indexTranslationUnit_Impl(
932 idxAction, client_data, index_callbacks, index_callbacks_size,
933 index_options, TU);
934 };
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000935
936 if (getenv("LIBCLANG_NOTHREADS")) {
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000937 IndexTranslationUnitImpl();
938 return result;
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000939 }
940
941 llvm::CrashRecoveryContext CRC;
942
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000943 if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000944 fprintf(stderr, "libclang: crash detected during indexing TU\n");
945
946 return 1;
947 }
948
Benjamin Kramer11a9cd92015-07-25 20:55:44 +0000949 return result;
Argyrios Kyrtzidisd992e142011-11-15 06:20:16 +0000950}
951
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000952void clang_indexLoc_getFileLocation(CXIdxLoc location,
Argyrios Kyrtzidis7519c5e2011-11-11 00:23:36 +0000953 CXIdxClientFile *indexFile,
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000954 CXFile *file,
955 unsigned *line,
956 unsigned *column,
957 unsigned *offset) {
Craig Topper69186e72014-06-08 08:38:04 +0000958 if (indexFile) *indexFile = nullptr;
959 if (file) *file = nullptr;
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000960 if (line) *line = 0;
961 if (column) *column = 0;
962 if (offset) *offset = 0;
963
964 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
965 if (!location.ptr_data[0] || Loc.isInvalid())
966 return;
967
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000968 CXIndexDataConsumer &DataConsumer =
969 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
970 DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000971}
972
973CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
974 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
975 if (!location.ptr_data[0] || Loc.isInvalid())
976 return clang_getNullLocation();
977
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000978 CXIndexDataConsumer &DataConsumer =
979 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
980 return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
Argyrios Kyrtzidisdc199a32011-10-17 19:48:19 +0000981}
982