1 //===- Indexing.cpp - Higher level API functions --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CIndexDiagnostic.h"
10 #include "CIndexer.h"
11 #include "CLog.h"
12 #include "CXCursor.h"
13 #include "CXIndexDataConsumer.h"
14 #include "CXSourceLocation.h"
15 #include "CXString.h"
16 #include "CXTranslationUnit.h"
17 #include "clang/AST/ASTConsumer.h"
18 #include "clang/Frontend/ASTUnit.h"
19 #include "clang/Frontend/CompilerInstance.h"
20 #include "clang/Frontend/CompilerInvocation.h"
21 #include "clang/Frontend/FrontendAction.h"
22 #include "clang/Frontend/Utils.h"
23 #include "clang/Index/IndexingAction.h"
24 #include "clang/Lex/HeaderSearch.h"
25 #include "clang/Lex/PPCallbacks.h"
26 #include "clang/Lex/PPConditionalDirectiveRecord.h"
27 #include "clang/Lex/Preprocessor.h"
28 #include "clang/Lex/PreprocessorOptions.h"
29 #include "llvm/Support/CrashRecoveryContext.h"
30 #include "llvm/Support/MemoryBuffer.h"
31 #include "llvm/Support/Mutex.h"
32 #include "llvm/Support/MutexGuard.h"
33 #include <cstdio>
34 #include <utility>
35 
36 using namespace clang;
37 using namespace clang::index;
38 using namespace cxtu;
39 using namespace cxindex;
40 
41 namespace {
42 
43 //===----------------------------------------------------------------------===//
44 // Skip Parsed Bodies
45 //===----------------------------------------------------------------------===//
46 
47 /// A "region" in source code identified by the file/offset of the
48 /// preprocessor conditional directive that it belongs to.
49 /// Multiple, non-consecutive ranges can be parts of the same region.
50 ///
51 /// As an example of different regions separated by preprocessor directives:
52 ///
53 /// \code
54 ///   #1
55 /// #ifdef BLAH
56 ///   #2
57 /// #ifdef CAKE
58 ///   #3
59 /// #endif
60 ///   #2
61 /// #endif
62 ///   #1
63 /// \endcode
64 ///
65 /// There are 3 regions, with non-consecutive parts:
66 ///   #1 is identified as the beginning of the file
67 ///   #2 is identified as the location of "#ifdef BLAH"
68 ///   #3 is identified as the location of "#ifdef CAKE"
69 ///
70 class PPRegion {
71   llvm::sys::fs::UniqueID UniqueID;
72   time_t ModTime;
73   unsigned Offset;
74 public:
75   PPRegion() : UniqueID(0, 0), ModTime(), Offset() {}
76   PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime)
77       : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {}
78 
79   const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
80   unsigned getOffset() const { return Offset; }
81   time_t getModTime() const { return ModTime; }
82 
83   bool isInvalid() const { return *this == PPRegion(); }
84 
85   friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) {
86     return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset &&
87            lhs.ModTime == rhs.ModTime;
88   }
89 };
90 
91 typedef llvm::DenseSet<PPRegion> PPRegionSetTy;
92 
93 } // end anonymous namespace
94 
95 namespace llvm {
96 
97   template <>
98   struct DenseMapInfo<PPRegion> {
99     static inline PPRegion getEmptyKey() {
100       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
101     }
102     static inline PPRegion getTombstoneKey() {
103       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
104     }
105 
106     static unsigned getHashValue(const PPRegion &S) {
107       llvm::FoldingSetNodeID ID;
108       const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
109       ID.AddInteger(UniqueID.getFile());
110       ID.AddInteger(UniqueID.getDevice());
111       ID.AddInteger(S.getOffset());
112       ID.AddInteger(S.getModTime());
113       return ID.ComputeHash();
114     }
115 
116     static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
117       return LHS == RHS;
118     }
119   };
120 }
121 
122 namespace {
123 
124 class SessionSkipBodyData {
125   llvm::sys::Mutex Mux;
126   PPRegionSetTy ParsedRegions;
127 
128 public:
129   SessionSkipBodyData() : Mux(/*recursive=*/false) {}
130   ~SessionSkipBodyData() {
131     //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n";
132   }
133 
134   void copyTo(PPRegionSetTy &Set) {
135     llvm::MutexGuard MG(Mux);
136     Set = ParsedRegions;
137   }
138 
139   void update(ArrayRef<PPRegion> Regions) {
140     llvm::MutexGuard MG(Mux);
141     ParsedRegions.insert(Regions.begin(), Regions.end());
142   }
143 };
144 
145 class TUSkipBodyControl {
146   SessionSkipBodyData &SessionData;
147   PPConditionalDirectiveRecord &PPRec;
148   Preprocessor &PP;
149 
150   PPRegionSetTy ParsedRegions;
151   SmallVector<PPRegion, 32> NewParsedRegions;
152   PPRegion LastRegion;
153   bool LastIsParsed;
154 
155 public:
156   TUSkipBodyControl(SessionSkipBodyData &sessionData,
157                     PPConditionalDirectiveRecord &ppRec,
158                     Preprocessor &pp)
159     : SessionData(sessionData), PPRec(ppRec), PP(pp) {
160     SessionData.copyTo(ParsedRegions);
161   }
162 
163   bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
164     PPRegion region = getRegion(Loc, FID, FE);
165     if (region.isInvalid())
166       return false;
167 
168     // Check common case, consecutive functions in the same region.
169     if (LastRegion == region)
170       return LastIsParsed;
171 
172     LastRegion = region;
173     LastIsParsed = ParsedRegions.count(region);
174     if (!LastIsParsed)
175       NewParsedRegions.push_back(region);
176     return LastIsParsed;
177   }
178 
179   void finished() {
180     SessionData.update(NewParsedRegions);
181   }
182 
183 private:
184   PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
185     SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
186     if (RegionLoc.isInvalid()) {
187       if (isParsedOnceInclude(FE)) {
188         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
189         return PPRegion(ID, 0, FE->getModificationTime());
190       }
191       return PPRegion();
192     }
193 
194     const SourceManager &SM = PPRec.getSourceManager();
195     assert(RegionLoc.isFileID());
196     FileID RegionFID;
197     unsigned RegionOffset;
198     std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
199 
200     if (RegionFID != FID) {
201       if (isParsedOnceInclude(FE)) {
202         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
203         return PPRegion(ID, 0, FE->getModificationTime());
204       }
205       return PPRegion();
206     }
207 
208     const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
209     return PPRegion(ID, RegionOffset, FE->getModificationTime());
210   }
211 
212   bool isParsedOnceInclude(const FileEntry *FE) {
213     return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
214   }
215 };
216 
217 //===----------------------------------------------------------------------===//
218 // IndexPPCallbacks
219 //===----------------------------------------------------------------------===//
220 
221 class IndexPPCallbacks : public PPCallbacks {
222   Preprocessor &PP;
223   CXIndexDataConsumer &DataConsumer;
224   bool IsMainFileEntered;
225 
226 public:
227   IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
228     : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
229 
230   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
231                  SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
232     if (IsMainFileEntered)
233       return;
234 
235     SourceManager &SM = PP.getSourceManager();
236     SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
237 
238     if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
239       IsMainFileEntered = true;
240       DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
241     }
242   }
243 
244   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
245                           StringRef FileName, bool IsAngled,
246                           CharSourceRange FilenameRange, const FileEntry *File,
247                           StringRef SearchPath, StringRef RelativePath,
248                           const Module *Imported,
249                           SrcMgr::CharacteristicKind FileType) override {
250     bool isImport = (IncludeTok.is(tok::identifier) &&
251             IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
252     DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
253                             Imported);
254   }
255 
256   /// MacroDefined - This hook is called whenever a macro definition is seen.
257   void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
258 
259   /// MacroUndefined - This hook is called whenever a macro #undef is seen.
260   /// MI is released immediately following this callback.
261   void MacroUndefined(const Token &MacroNameTok,
262                       const MacroDefinition &MD,
263                       const MacroDirective *UD) override {}
264 
265   /// MacroExpands - This is called by when a macro invocation is found.
266   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
267                     SourceRange Range, const MacroArgs *Args) override {}
268 
269   /// SourceRangeSkipped - This hook is called when a source range is skipped.
270   /// \param Range The SourceRange that was skipped. The range begins at the
271   /// #if/#else directive and ends after the #endif/#else directive.
272   void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override {
273   }
274 };
275 
276 //===----------------------------------------------------------------------===//
277 // IndexingConsumer
278 //===----------------------------------------------------------------------===//
279 
280 class IndexingConsumer : public ASTConsumer {
281   CXIndexDataConsumer &DataConsumer;
282   TUSkipBodyControl *SKCtrl;
283 
284 public:
285   IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
286     : DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
287 
288   // ASTConsumer Implementation
289 
290   void Initialize(ASTContext &Context) override {
291     DataConsumer.setASTContext(Context);
292     DataConsumer.startedTranslationUnit();
293   }
294 
295   void HandleTranslationUnit(ASTContext &Ctx) override {
296     if (SKCtrl)
297       SKCtrl->finished();
298   }
299 
300   bool HandleTopLevelDecl(DeclGroupRef DG) override {
301     return !DataConsumer.shouldAbort();
302   }
303 
304   bool shouldSkipFunctionBody(Decl *D) override {
305     if (!SKCtrl) {
306       // Always skip bodies.
307       return true;
308     }
309 
310     const SourceManager &SM = DataConsumer.getASTContext().getSourceManager();
311     SourceLocation Loc = D->getLocation();
312     if (Loc.isMacroID())
313       return false;
314     if (SM.isInSystemHeader(Loc))
315       return true; // always skip bodies from system headers.
316 
317     FileID FID;
318     unsigned Offset;
319     std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
320     // Don't skip bodies from main files; this may be revisited.
321     if (SM.getMainFileID() == FID)
322       return false;
323     const FileEntry *FE = SM.getFileEntryForID(FID);
324     if (!FE)
325       return false;
326 
327     return SKCtrl->isParsed(Loc, FID, FE);
328   }
329 };
330 
331 //===----------------------------------------------------------------------===//
332 // CaptureDiagnosticConsumer
333 //===----------------------------------------------------------------------===//
334 
335 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
336   SmallVector<StoredDiagnostic, 4> Errors;
337 public:
338 
339   void HandleDiagnostic(DiagnosticsEngine::Level level,
340                         const Diagnostic &Info) override {
341     if (level >= DiagnosticsEngine::Error)
342       Errors.push_back(StoredDiagnostic(level, Info));
343   }
344 };
345 
346 //===----------------------------------------------------------------------===//
347 // IndexingFrontendAction
348 //===----------------------------------------------------------------------===//
349 
350 class IndexingFrontendAction : public ASTFrontendAction {
351   std::shared_ptr<CXIndexDataConsumer> DataConsumer;
352 
353   SessionSkipBodyData *SKData;
354   std::unique_ptr<TUSkipBodyControl> SKCtrl;
355 
356 public:
357   IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
358                          SessionSkipBodyData *skData)
359       : DataConsumer(std::move(dataConsumer)), SKData(skData) {}
360 
361   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
362                                                  StringRef InFile) override {
363     PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
364 
365     if (!PPOpts.ImplicitPCHInclude.empty()) {
366       DataConsumer->importedPCH(
367                         CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
368     }
369 
370     DataConsumer->setASTContext(CI.getASTContext());
371     Preprocessor &PP = CI.getPreprocessor();
372     PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
373     DataConsumer->setPreprocessor(CI.getPreprocessorPtr());
374 
375     if (SKData) {
376       auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
377       PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
378       SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
379     }
380 
381     return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
382   }
383 
384   TranslationUnitKind getTranslationUnitKind() override {
385     if (DataConsumer->shouldIndexImplicitTemplateInsts())
386       return TU_Complete;
387     else
388       return TU_Prefix;
389   }
390   bool hasCodeCompletionSupport() const override { return false; }
391 };
392 
393 //===----------------------------------------------------------------------===//
394 // clang_indexSourceFileUnit Implementation
395 //===----------------------------------------------------------------------===//
396 
397 static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
398   IndexingOptions IdxOpts;
399   if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
400     IdxOpts.IndexFunctionLocals = true;
401   if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations)
402     IdxOpts.IndexImplicitInstantiation = true;
403   return IdxOpts;
404 }
405 
406 struct IndexSessionData {
407   CXIndex CIdx;
408   std::unique_ptr<SessionSkipBodyData> SkipBodyData;
409 
410   explicit IndexSessionData(CXIndex cIdx)
411     : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
412 };
413 
414 } // anonymous namespace
415 
416 static 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) {
423   if (out_TU)
424     *out_TU = nullptr;
425   bool requestedToGetTU = (out_TU != nullptr);
426 
427   if (!cxIdxAction) {
428     return CXError_InvalidArguments;
429   }
430   if (!client_index_callbacks || index_callbacks_size == 0) {
431     return CXError_InvalidArguments;
432   }
433 
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 
440   IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction);
441   CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx);
442 
443   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
444     setThreadBackgroundPriority();
445 
446   bool CaptureDiagnostics = !Logger::isLoggingEnabled();
447 
448   CaptureDiagnosticConsumer *CaptureDiag = nullptr;
449   if (CaptureDiagnostics)
450     CaptureDiag = new CaptureDiagnosticConsumer();
451 
452   // Configure the diagnostics.
453   IntrusiveRefCntPtr<DiagnosticsEngine>
454     Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
455                                               CaptureDiag,
456                                               /*ShouldOwnClient=*/true));
457 
458   // Recover resources if we crash before exiting this function.
459   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
460     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
461     DiagCleanup(Diags.get());
462 
463   std::unique_ptr<std::vector<const char *>> Args(
464       new std::vector<const char *>());
465 
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);
480 
481   std::shared_ptr<CompilerInvocation> CInvok =
482       createInvocationFromCommandLine(*Args, Diags);
483 
484   if (!CInvok)
485     return CXError_Failure;
486 
487   // Recover resources if we crash before exiting this function.
488   llvm::CrashRecoveryContextCleanupRegistrar<
489       std::shared_ptr<CompilerInvocation>,
490       llvm::CrashRecoveryContextDestructorCleanup<
491           std::shared_ptr<CompilerInvocation>>>
492       CInvokCleanup(&CInvok);
493 
494   if (CInvok->getFrontendOpts().Inputs.empty())
495     return CXError_Failure;
496 
497   typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
498   std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
499 
500   // Recover resources if we crash before exiting this method.
501   llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
502       BufOwner.get());
503 
504   for (auto &UF : unsaved_files) {
505     std::unique_ptr<llvm::MemoryBuffer> MB =
506         llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
507     CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
508     BufOwner->push_back(std::move(MB));
509   }
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.
515   CInvok->getLangOpts()->SpellChecking = false;
516 
517   if (index_options & CXIndexOpt_SuppressWarnings)
518     CInvok->getDiagnosticOpts().IgnoreWarnings = true;
519 
520   // Make sure to use the raw module format.
521   CInvok->getHeaderSearchOpts().ModuleFormat =
522     CXXIdx->getPCHContainerOperations()->getRawReader().getFormat();
523 
524   auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics,
525                               /*UserFilesAreVolatile=*/true);
526   if (!Unit)
527     return CXError_InvalidArguments;
528 
529   auto *UPtr = Unit.get();
530   std::unique_ptr<CXTUOwner> CXTU(
531       new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit))));
532 
533   // Recover resources if we crash before exiting this method.
534   llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
535     CXTUCleanup(CXTU.get());
536 
537   // 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 
544   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;
550   IndexAction = createIndexingAction(DataConsumer,
551                                 getIndexingOptionsFromCXOptions(index_options),
552                                      std::move(InterAction));
553 
554   // Recover resources if we crash before exiting this method.
555   llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
556     IndexActionCleanup(IndexAction.get());
557 
558   bool Persistent = requestedToGetTU;
559   bool OnlyLocalDecls = false;
560   bool PrecompilePreamble = false;
561   bool CreatePreambleOnFirstParse = false;
562   bool CacheCodeCompletionResults = false;
563   PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
564   PPOpts.AllowPCHWithCompilerErrors = true;
565 
566   if (requestedToGetTU) {
567     OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
568     PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
569     CreatePreambleOnFirstParse =
570         TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
571     // FIXME: Add a flag for modules.
572     CacheCodeCompletionResults
573       = TU_options & CXTranslationUnit_CacheCompletionResults;
574   }
575 
576   if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
577     PPOpts.DetailedRecord = true;
578   }
579 
580   if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
581     PPOpts.DetailedRecord = false;
582 
583   // 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;
588   DiagnosticErrorTrap DiagTrap(*Diags);
589   bool Success = ASTUnit::LoadFromCompilerInvocationAction(
590       std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags,
591       IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(),
592       OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
593       CacheCodeCompletionResults,
594       /*IncludeBriefCommentsInCodeCompletion=*/false,
595       /*UserFilesAreVolatile=*/true);
596   if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
597     printDiagsToStderr(UPtr);
598 
599   if (isASTReadError(UPtr))
600     return CXError_ASTReadError;
601 
602   if (!Success)
603     return CXError_Failure;
604 
605   if (out_TU)
606     *out_TU = CXTU->takeTU();
607 
608   return CXError_Success;
609 }
610 
611 //===----------------------------------------------------------------------===//
612 // clang_indexTranslationUnit Implementation
613 //===----------------------------------------------------------------------===//
614 
615 static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
616   Preprocessor &PP = Unit.getPreprocessor();
617   if (!PP.getPreprocessingRecord())
618     return;
619 
620   // FIXME: Only deserialize inclusion directives.
621 
622   bool isModuleFile = Unit.isModuleFile();
623   for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) {
624     if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
625       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());
634     }
635   }
636 }
637 
638 static 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) {
642   // Check arguments.
643   if (isNotUsableTU(TU)) {
644     LOG_BAD_TU(TU);
645     return CXError_InvalidArguments;
646   }
647   if (!client_index_callbacks || index_callbacks_size == 0) {
648     return CXError_InvalidArguments;
649   }
650 
651   CIndexer *CXXIdx = TU->CIdx;
652   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
653     setThreadBackgroundPriority();
654 
655   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 
661   CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU);
662 
663   ASTUnit *Unit = cxtu::getASTUnit(TU);
664   if (!Unit)
665     return CXError_Failure;
666 
667   ASTUnit::ConcurrencyCheck Check(*Unit);
668 
669   if (const FileEntry *PCHFile = Unit->getPCHFile())
670     DataConsumer.importedPCH(PCHFile);
671 
672   FileManager &FileMgr = Unit->getFileManager();
673 
674   if (Unit->getOriginalSourceFileName().empty())
675     DataConsumer.enteredMainFile(nullptr);
676   else
677     DataConsumer.enteredMainFile(
678         FileMgr.getFile(Unit->getOriginalSourceFileName()));
679 
680   DataConsumer.setASTContext(Unit->getASTContext());
681   DataConsumer.startedTranslationUnit();
682 
683   indexPreprocessingRecord(*Unit, DataConsumer);
684   indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
685   DataConsumer.indexDiagnostics();
686 
687   return CXError_Success;
688 }
689 
690 //===----------------------------------------------------------------------===//
691 // libclang public APIs.
692 //===----------------------------------------------------------------------===//
693 
694 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
695   return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
696 }
697 
698 const CXIdxObjCContainerDeclInfo *
699 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
700   if (!DInfo)
701     return nullptr;
702 
703   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
704   if (const ObjCContainerDeclInfo *
705         ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
706     return &ContInfo->ObjCContDeclInfo;
707 
708   return nullptr;
709 }
710 
711 const CXIdxObjCInterfaceDeclInfo *
712 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
713   if (!DInfo)
714     return nullptr;
715 
716   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
717   if (const ObjCInterfaceDeclInfo *
718         InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
719     return &InterInfo->ObjCInterDeclInfo;
720 
721   return nullptr;
722 }
723 
724 const CXIdxObjCCategoryDeclInfo *
725 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
726   if (!DInfo)
727     return nullptr;
728 
729   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
730   if (const ObjCCategoryDeclInfo *
731         CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
732     return &CatInfo->ObjCCatDeclInfo;
733 
734   return nullptr;
735 }
736 
737 const CXIdxObjCProtocolRefListInfo *
738 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
739   if (!DInfo)
740     return nullptr;
741 
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 
752   if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
753     return CatInfo->ObjCCatDeclInfo.protocols;
754 
755   return nullptr;
756 }
757 
758 const CXIdxObjCPropertyDeclInfo *
759 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
760   if (!DInfo)
761     return nullptr;
762 
763   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
764   if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
765     return &PropInfo->ObjCPropDeclInfo;
766 
767   return nullptr;
768 }
769 
770 const CXIdxIBOutletCollectionAttrInfo *
771 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
772   if (!AInfo)
773     return nullptr;
774 
775   const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
776   if (const IBOutletCollectionInfo *
777         IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
778     return &IBInfo->IBCollInfo;
779 
780   return nullptr;
781 }
782 
783 const CXIdxCXXClassDeclInfo *
784 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
785   if (!DInfo)
786     return nullptr;
787 
788   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
789   if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
790     return &ClassInfo->CXXClassInfo;
791 
792   return nullptr;
793 }
794 
795 CXIdxClientContainer
796 clang_index_getClientContainer(const CXIdxContainerInfo *info) {
797   if (!info)
798     return nullptr;
799   const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
800   return Container->IndexCtx->getClientContainerForDC(Container->DC);
801 }
802 
803 void clang_index_setClientContainer(const CXIdxContainerInfo *info,
804                                     CXIdxClientContainer client) {
805   if (!info)
806     return;
807   const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
808   Container->IndexCtx->addContainerInMap(Container->DC, client);
809 }
810 
811 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
812   if (!info)
813     return nullptr;
814   const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
815   return Entity->IndexCtx->getClientEntity(Entity->Dcl);
816 }
817 
818 void clang_index_setClientEntity(const CXIdxEntityInfo *info,
819                                  CXIdxClientEntity client) {
820   if (!info)
821     return;
822   const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
823   Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
824 }
825 
826 CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
827   return new IndexSessionData(CIdx);
828 }
829 
830 void clang_IndexAction_dispose(CXIndexAction idxAction) {
831   if (idxAction)
832     delete static_cast<IndexSessionData *>(idxAction);
833 }
834 
835 int 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) {
847   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 
856 int 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) {
863   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   }
868 
869   if (num_unsaved_files && !unsaved_files)
870     return CXError_InvalidArguments;
871 
872   CXErrorCode result = CXError_Failure;
873   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   };
881 
882   llvm::CrashRecoveryContext CRC;
883 
884   if (!RunSafely(CRC, IndexSourceFileImpl)) {
885     fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
886     fprintf(stderr, "  'source_filename' : '%s'\n", source_filename);
887     fprintf(stderr, "  'command_line_args' : [");
888     for (int i = 0; i != num_command_line_args; ++i) {
889       if (i)
890         fprintf(stderr, ", ");
891       fprintf(stderr, "'%s'", command_line_args[i]);
892     }
893     fprintf(stderr, "],\n");
894     fprintf(stderr, "  'unsaved_files' : [");
895     for (unsigned i = 0; i != num_unsaved_files; ++i) {
896       if (i)
897         fprintf(stderr, ", ");
898       fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
899               unsaved_files[i].Length);
900     }
901     fprintf(stderr, "],\n");
902     fprintf(stderr, "  'options' : %d,\n", TU_options);
903     fprintf(stderr, "}\n");
904 
905     return 1;
906   } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
907     if (out_TU)
908       PrintLibclangResourceUsage(*out_TU);
909   }
910 
911   return result;
912 }
913 
914 int clang_indexTranslationUnit(CXIndexAction idxAction,
915                                CXClientData client_data,
916                                IndexerCallbacks *index_callbacks,
917                                unsigned index_callbacks_size,
918                                unsigned index_options,
919                                CXTranslationUnit TU) {
920   LOG_FUNC_SECTION {
921     *Log << TU;
922   }
923 
924   CXErrorCode result;
925   auto IndexTranslationUnitImpl = [=, &result]() {
926     result = clang_indexTranslationUnit_Impl(
927         idxAction, client_data, index_callbacks, index_callbacks_size,
928         index_options, TU);
929   };
930 
931   llvm::CrashRecoveryContext CRC;
932 
933   if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
934     fprintf(stderr, "libclang: crash detected during indexing TU\n");
935 
936     return 1;
937   }
938 
939   return result;
940 }
941 
942 void clang_indexLoc_getFileLocation(CXIdxLoc location,
943                                     CXIdxClientFile *indexFile,
944                                     CXFile *file,
945                                     unsigned *line,
946                                     unsigned *column,
947                                     unsigned *offset) {
948   if (indexFile) *indexFile = nullptr;
949   if (file)   *file = nullptr;
950   if (line)   *line = 0;
951   if (column) *column = 0;
952   if (offset) *offset = 0;
953 
954   SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
955   if (!location.ptr_data[0] || Loc.isInvalid())
956     return;
957 
958   CXIndexDataConsumer &DataConsumer =
959       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
960   DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
961 }
962 
963 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
964   SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
965   if (!location.ptr_data[0] || Loc.isInvalid())
966     return clang_getNullLocation();
967 
968   CXIndexDataConsumer &DataConsumer =
969       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
970   return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
971 }
972 
973