1 //===- 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 
10 #include "CIndexDiagnostic.h"
11 #include "CIndexer.h"
12 #include "CLog.h"
13 #include "CXCursor.h"
14 #include "CXIndexDataConsumer.h"
15 #include "CXSourceLocation.h"
16 #include "CXString.h"
17 #include "CXTranslationUnit.h"
18 #include "clang/AST/ASTConsumer.h"
19 #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"
24 #include "clang/Index/IndexingAction.h"
25 #include "clang/Lex/HeaderSearch.h"
26 #include "clang/Lex/PPCallbacks.h"
27 #include "clang/Lex/PPConditionalDirectiveRecord.h"
28 #include "clang/Lex/Preprocessor.h"
29 #include "clang/Lex/PreprocessorOptions.h"
30 #include "llvm/Support/CrashRecoveryContext.h"
31 #include "llvm/Support/MemoryBuffer.h"
32 #include "llvm/Support/Mutex.h"
33 #include "llvm/Support/MutexGuard.h"
34 #include <cstdio>
35 #include <utility>
36 
37 using namespace clang;
38 using namespace clang::index;
39 using namespace cxtu;
40 using namespace cxindex;
41 
42 namespace {
43 
44 //===----------------------------------------------------------------------===//
45 // Skip Parsed Bodies
46 //===----------------------------------------------------------------------===//
47 
48 /// \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 ///
71 class PPRegion {
72   llvm::sys::fs::UniqueID UniqueID;
73   time_t ModTime;
74   unsigned Offset;
75 public:
76   PPRegion() : UniqueID(0, 0), ModTime(), Offset() {}
77   PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime)
78       : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {}
79 
80   const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
81   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) {
87     return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset &&
88            lhs.ModTime == rhs.ModTime;
89   }
90 };
91 
92 typedef llvm::DenseSet<PPRegion> PPRegionSetTy;
93 
94 } // end anonymous namespace
95 
96 namespace 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() {
104       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
105     }
106     static inline PPRegion getTombstoneKey() {
107       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
108     }
109 
110     static unsigned getHashValue(const PPRegion &S) {
111       llvm::FoldingSetNodeID ID;
112       const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
113       ID.AddInteger(UniqueID.getFile());
114       ID.AddInteger(UniqueID.getDevice());
115       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   };
124 }
125 
126 namespace {
127 
128 class SessionSkipBodyData {
129   llvm::sys::Mutex Mux;
130   PPRegionSetTy ParsedRegions;
131 
132 public:
133   SessionSkipBodyData() : Mux(/*recursive=*/false) {}
134   ~SessionSkipBodyData() {
135     //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n";
136   }
137 
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 
149 class 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 
159 public:
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 
187 private:
188   PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
189     SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
190     if (RegionLoc.isInvalid()) {
191       if (isParsedOnceInclude(FE)) {
192         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
193         return PPRegion(ID, 0, FE->getModificationTime());
194       }
195       return PPRegion();
196     }
197 
198     const SourceManager &SM = PPRec.getSourceManager();
199     assert(RegionLoc.isFileID());
200     FileID RegionFID;
201     unsigned RegionOffset;
202     std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
203 
204     if (RegionFID != FID) {
205       if (isParsedOnceInclude(FE)) {
206         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
207         return PPRegion(ID, 0, FE->getModificationTime());
208       }
209       return PPRegion();
210     }
211 
212     const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
213     return PPRegion(ID, RegionOffset, FE->getModificationTime());
214   }
215 
216   bool isParsedOnceInclude(const FileEntry *FE) {
217     return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
218   }
219 };
220 
221 //===----------------------------------------------------------------------===//
222 // IndexPPCallbacks
223 //===----------------------------------------------------------------------===//
224 
225 class IndexPPCallbacks : public PPCallbacks {
226   Preprocessor &PP;
227   CXIndexDataConsumer &DataConsumer;
228   bool IsMainFileEntered;
229 
230 public:
231   IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
232     : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
233 
234   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
235                  SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
236     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;
244       DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
245     }
246   }
247 
248   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 {
253     bool isImport = (IncludeTok.is(tok::identifier) &&
254             IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
255     DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
256                             Imported);
257   }
258 
259   /// MacroDefined - This hook is called whenever a macro definition is seen.
260   void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
261 
262   /// MacroUndefined - This hook is called whenever a macro #undef is seen.
263   /// MI is released immediately following this callback.
264   void MacroUndefined(const Token &MacroNameTok,
265                       const MacroDefinition &MD,
266                       const MacroDirective *UD) override {}
267 
268   /// MacroExpands - This is called by when a macro invocation is found.
269   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
270                     SourceRange Range, const MacroArgs *Args) override {}
271 
272   /// 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.
275   void SourceRangeSkipped(SourceRange Range) override {}
276 };
277 
278 //===----------------------------------------------------------------------===//
279 // IndexingConsumer
280 //===----------------------------------------------------------------------===//
281 
282 class IndexingConsumer : public ASTConsumer {
283   CXIndexDataConsumer &DataConsumer;
284   TUSkipBodyControl *SKCtrl;
285 
286 public:
287   IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
288     : DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
289 
290   // ASTConsumer Implementation
291 
292   void Initialize(ASTContext &Context) override {
293     DataConsumer.setASTContext(Context);
294     DataConsumer.startedTranslationUnit();
295   }
296 
297   void HandleTranslationUnit(ASTContext &Ctx) override {
298     if (SKCtrl)
299       SKCtrl->finished();
300   }
301 
302   bool HandleTopLevelDecl(DeclGroupRef DG) override {
303     return !DataConsumer.shouldAbort();
304   }
305 
306   bool shouldSkipFunctionBody(Decl *D) override {
307     if (!SKCtrl) {
308       // Always skip bodies.
309       return true;
310     }
311 
312     const SourceManager &SM = DataConsumer.getASTContext().getSourceManager();
313     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;
321     std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
322     // 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   }
331 };
332 
333 //===----------------------------------------------------------------------===//
334 // CaptureDiagnosticConsumer
335 //===----------------------------------------------------------------------===//
336 
337 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
338   SmallVector<StoredDiagnostic, 4> Errors;
339 public:
340 
341   void HandleDiagnostic(DiagnosticsEngine::Level level,
342                         const Diagnostic &Info) override {
343     if (level >= DiagnosticsEngine::Error)
344       Errors.push_back(StoredDiagnostic(level, Info));
345   }
346 };
347 
348 //===----------------------------------------------------------------------===//
349 // IndexingFrontendAction
350 //===----------------------------------------------------------------------===//
351 
352 class IndexingFrontendAction : public ASTFrontendAction {
353   std::shared_ptr<CXIndexDataConsumer> DataConsumer;
354 
355   SessionSkipBodyData *SKData;
356   std::unique_ptr<TUSkipBodyControl> SKCtrl;
357 
358 public:
359   IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
360                          SessionSkipBodyData *skData)
361       : DataConsumer(std::move(dataConsumer)), SKData(skData) {}
362 
363   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
364                                                  StringRef InFile) override {
365     PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
366 
367     if (!PPOpts.ImplicitPCHInclude.empty()) {
368       DataConsumer->importedPCH(
369                         CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
370     }
371 
372     DataConsumer->setASTContext(CI.getASTContext());
373     Preprocessor &PP = CI.getPreprocessor();
374     PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
375     DataConsumer->setPreprocessor(CI.getPreprocessorPtr());
376 
377     if (SKData) {
378       auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
379       PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
380       SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
381     }
382 
383     return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
384   }
385 
386   TranslationUnitKind getTranslationUnitKind() override {
387     if (DataConsumer->shouldIndexImplicitTemplateInsts())
388       return TU_Complete;
389     else
390       return TU_Prefix;
391   }
392   bool hasCodeCompletionSupport() const override { return false; }
393 };
394 
395 //===----------------------------------------------------------------------===//
396 // clang_indexSourceFileUnit Implementation
397 //===----------------------------------------------------------------------===//
398 
399 static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
400   IndexingOptions IdxOpts;
401   if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
402     IdxOpts.IndexFunctionLocals = 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   auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
662                                                             index_options, TU);
663 
664   ASTUnit *Unit = cxtu::getASTUnit(TU);
665   if (!Unit)
666     return CXError_Failure;
667 
668   ASTUnit::ConcurrencyCheck Check(*Unit);
669 
670   if (const FileEntry *PCHFile = Unit->getPCHFile())
671     DataConsumer->importedPCH(PCHFile);
672 
673   FileManager &FileMgr = Unit->getFileManager();
674 
675   if (Unit->getOriginalSourceFileName().empty())
676     DataConsumer->enteredMainFile(nullptr);
677   else
678     DataConsumer->enteredMainFile(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   if (getenv("LIBCLANG_NOTHREADS")) {
883     IndexSourceFileImpl();
884     return result;
885   }
886 
887   llvm::CrashRecoveryContext CRC;
888 
889   if (!RunSafely(CRC, IndexSourceFileImpl)) {
890     fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
891     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   }
915 
916   return result;
917 }
918 
919 int clang_indexTranslationUnit(CXIndexAction idxAction,
920                                CXClientData client_data,
921                                IndexerCallbacks *index_callbacks,
922                                unsigned index_callbacks_size,
923                                unsigned index_options,
924                                CXTranslationUnit TU) {
925   LOG_FUNC_SECTION {
926     *Log << TU;
927   }
928 
929   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   };
935 
936   if (getenv("LIBCLANG_NOTHREADS")) {
937     IndexTranslationUnitImpl();
938     return result;
939   }
940 
941   llvm::CrashRecoveryContext CRC;
942 
943   if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
944     fprintf(stderr, "libclang: crash detected during indexing TU\n");
945 
946     return 1;
947   }
948 
949   return result;
950 }
951 
952 void clang_indexLoc_getFileLocation(CXIdxLoc location,
953                                     CXIdxClientFile *indexFile,
954                                     CXFile *file,
955                                     unsigned *line,
956                                     unsigned *column,
957                                     unsigned *offset) {
958   if (indexFile) *indexFile = nullptr;
959   if (file)   *file = nullptr;
960   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 
968   CXIndexDataConsumer &DataConsumer =
969       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
970   DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
971 }
972 
973 CXSourceLocation 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 
978   CXIndexDataConsumer &DataConsumer =
979       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
980   return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
981 }
982 
983