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 "CXIndexDataConsumer.h"
11 #include "CIndexDiagnostic.h"
12 #include "CIndexer.h"
13 #include "CLog.h"
14 #include "CXCursor.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/Sema/SemaConsumer.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 
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 /// \brief 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   template <> struct isPodLike<PPRegion> {
97     static const bool value = true;
98   };
99 
100   template <>
101   struct DenseMapInfo<PPRegion> {
102     static inline PPRegion getEmptyKey() {
103       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
104     }
105     static inline PPRegion getTombstoneKey() {
106       return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
107     }
108 
109     static unsigned getHashValue(const PPRegion &S) {
110       llvm::FoldingSetNodeID ID;
111       const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
112       ID.AddInteger(UniqueID.getFile());
113       ID.AddInteger(UniqueID.getDevice());
114       ID.AddInteger(S.getOffset());
115       ID.AddInteger(S.getModTime());
116       return ID.ComputeHash();
117     }
118 
119     static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
120       return LHS == RHS;
121     }
122   };
123 }
124 
125 namespace {
126 
127 class SessionSkipBodyData {
128   llvm::sys::Mutex Mux;
129   PPRegionSetTy ParsedRegions;
130 
131 public:
132   SessionSkipBodyData() : Mux(/*recursive=*/false) {}
133   ~SessionSkipBodyData() {
134     //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n";
135   }
136 
137   void copyTo(PPRegionSetTy &Set) {
138     llvm::MutexGuard MG(Mux);
139     Set = ParsedRegions;
140   }
141 
142   void update(ArrayRef<PPRegion> Regions) {
143     llvm::MutexGuard MG(Mux);
144     ParsedRegions.insert(Regions.begin(), Regions.end());
145   }
146 };
147 
148 class TUSkipBodyControl {
149   SessionSkipBodyData &SessionData;
150   PPConditionalDirectiveRecord &PPRec;
151   Preprocessor &PP;
152 
153   PPRegionSetTy ParsedRegions;
154   SmallVector<PPRegion, 32> NewParsedRegions;
155   PPRegion LastRegion;
156   bool LastIsParsed;
157 
158 public:
159   TUSkipBodyControl(SessionSkipBodyData &sessionData,
160                     PPConditionalDirectiveRecord &ppRec,
161                     Preprocessor &pp)
162     : SessionData(sessionData), PPRec(ppRec), PP(pp) {
163     SessionData.copyTo(ParsedRegions);
164   }
165 
166   bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
167     PPRegion region = getRegion(Loc, FID, FE);
168     if (region.isInvalid())
169       return false;
170 
171     // Check common case, consecutive functions in the same region.
172     if (LastRegion == region)
173       return LastIsParsed;
174 
175     LastRegion = region;
176     LastIsParsed = ParsedRegions.count(region);
177     if (!LastIsParsed)
178       NewParsedRegions.push_back(region);
179     return LastIsParsed;
180   }
181 
182   void finished() {
183     SessionData.update(NewParsedRegions);
184   }
185 
186 private:
187   PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
188     SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
189     if (RegionLoc.isInvalid()) {
190       if (isParsedOnceInclude(FE)) {
191         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
192         return PPRegion(ID, 0, FE->getModificationTime());
193       }
194       return PPRegion();
195     }
196 
197     const SourceManager &SM = PPRec.getSourceManager();
198     assert(RegionLoc.isFileID());
199     FileID RegionFID;
200     unsigned RegionOffset;
201     std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
202 
203     if (RegionFID != FID) {
204       if (isParsedOnceInclude(FE)) {
205         const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
206         return PPRegion(ID, 0, FE->getModificationTime());
207       }
208       return PPRegion();
209     }
210 
211     const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
212     return PPRegion(ID, RegionOffset, FE->getModificationTime());
213   }
214 
215   bool isParsedOnceInclude(const FileEntry *FE) {
216     return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
217   }
218 };
219 
220 //===----------------------------------------------------------------------===//
221 // IndexPPCallbacks
222 //===----------------------------------------------------------------------===//
223 
224 class IndexPPCallbacks : public PPCallbacks {
225   Preprocessor &PP;
226   CXIndexDataConsumer &DataConsumer;
227   bool IsMainFileEntered;
228 
229 public:
230   IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
231     : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
232 
233   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
234                  SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
235     if (IsMainFileEntered)
236       return;
237 
238     SourceManager &SM = PP.getSourceManager();
239     SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
240 
241     if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
242       IsMainFileEntered = true;
243       DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
244     }
245   }
246 
247   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
248                           StringRef FileName, bool IsAngled,
249                           CharSourceRange FilenameRange, const FileEntry *File,
250                           StringRef SearchPath, StringRef RelativePath,
251                           const Module *Imported) override {
252     bool isImport = (IncludeTok.is(tok::identifier) &&
253             IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
254     DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
255                             Imported);
256   }
257 
258   /// MacroDefined - This hook is called whenever a macro definition is seen.
259   void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
260 
261   /// MacroUndefined - This hook is called whenever a macro #undef is seen.
262   /// MI is released immediately following this callback.
263   void MacroUndefined(const Token &MacroNameTok,
264                       const MacroDefinition &MD) override {}
265 
266   /// MacroExpands - This is called by when a macro invocation is found.
267   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
268                     SourceRange Range, const MacroArgs *Args) override {}
269 
270   /// SourceRangeSkipped - This hook is called when a source range is skipped.
271   /// \param Range The SourceRange that was skipped. The range begins at the
272   /// #if/#else directive and ends after the #endif/#else directive.
273   void SourceRangeSkipped(SourceRange Range) override {}
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(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(PP);
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   return IdxOpts;
402 }
403 
404 struct IndexSessionData {
405   CXIndex CIdx;
406   std::unique_ptr<SessionSkipBodyData> SkipBodyData;
407 
408   explicit IndexSessionData(CXIndex cIdx)
409     : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
410 };
411 
412 } // anonymous namespace
413 
414 static CXErrorCode clang_indexSourceFile_Impl(
415     CXIndexAction cxIdxAction, CXClientData client_data,
416     IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
417     unsigned index_options, const char *source_filename,
418     const char *const *command_line_args, int num_command_line_args,
419     ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU,
420     unsigned TU_options) {
421   if (out_TU)
422     *out_TU = nullptr;
423   bool requestedToGetTU = (out_TU != nullptr);
424 
425   if (!cxIdxAction) {
426     return CXError_InvalidArguments;
427   }
428   if (!client_index_callbacks || index_callbacks_size == 0) {
429     return CXError_InvalidArguments;
430   }
431 
432   IndexerCallbacks CB;
433   memset(&CB, 0, sizeof(CB));
434   unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
435                                   ? index_callbacks_size : sizeof(CB);
436   memcpy(&CB, client_index_callbacks, ClientCBSize);
437 
438   IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction);
439   CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx);
440 
441   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
442     setThreadBackgroundPriority();
443 
444   bool CaptureDiagnostics = !Logger::isLoggingEnabled();
445 
446   CaptureDiagnosticConsumer *CaptureDiag = nullptr;
447   if (CaptureDiagnostics)
448     CaptureDiag = new CaptureDiagnosticConsumer();
449 
450   // Configure the diagnostics.
451   IntrusiveRefCntPtr<DiagnosticsEngine>
452     Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
453                                               CaptureDiag,
454                                               /*ShouldOwnClient=*/true));
455 
456   // Recover resources if we crash before exiting this function.
457   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
458     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
459     DiagCleanup(Diags.get());
460 
461   std::unique_ptr<std::vector<const char *>> Args(
462       new std::vector<const char *>());
463 
464   // Recover resources if we crash before exiting this method.
465   llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
466     ArgsCleanup(Args.get());
467 
468   Args->insert(Args->end(), command_line_args,
469                command_line_args + num_command_line_args);
470 
471   // The 'source_filename' argument is optional.  If the caller does not
472   // specify it then it is assumed that the source file is specified
473   // in the actual argument list.
474   // Put the source file after command_line_args otherwise if '-x' flag is
475   // present it will be unused.
476   if (source_filename)
477     Args->push_back(source_filename);
478 
479   IntrusiveRefCntPtr<CompilerInvocation>
480     CInvok(createInvocationFromCommandLine(*Args, Diags));
481 
482   if (!CInvok)
483     return CXError_Failure;
484 
485   // Recover resources if we crash before exiting this function.
486   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
487     llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> >
488     CInvokCleanup(CInvok.get());
489 
490   if (CInvok->getFrontendOpts().Inputs.empty())
491     return CXError_Failure;
492 
493   typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
494   std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
495 
496   // Recover resources if we crash before exiting this method.
497   llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
498       BufOwner.get());
499 
500   for (auto &UF : unsaved_files) {
501     std::unique_ptr<llvm::MemoryBuffer> MB =
502         llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
503     CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
504     BufOwner->push_back(std::move(MB));
505   }
506 
507   // Since libclang is primarily used by batch tools dealing with
508   // (often very broken) source code, where spell-checking can have a
509   // significant negative impact on performance (particularly when
510   // precompiled headers are involved), we disable it.
511   CInvok->getLangOpts()->SpellChecking = false;
512 
513   if (index_options & CXIndexOpt_SuppressWarnings)
514     CInvok->getDiagnosticOpts().IgnoreWarnings = true;
515 
516   // Make sure to use the raw module format.
517   CInvok->getHeaderSearchOpts().ModuleFormat =
518     CXXIdx->getPCHContainerOperations()->getRawReader().getFormat();
519 
520   ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags, CaptureDiagnostics,
521                                   /*UserFilesAreVolatile=*/true);
522   if (!Unit)
523     return CXError_InvalidArguments;
524 
525   std::unique_ptr<CXTUOwner> CXTU(
526       new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
527 
528   // Recover resources if we crash before exiting this method.
529   llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
530     CXTUCleanup(CXTU.get());
531 
532   // Enable the skip-parsed-bodies optimization only for C++; this may be
533   // revisited.
534   bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) &&
535       CInvok->getLangOpts()->CPlusPlus;
536   if (SkipBodies)
537     CInvok->getFrontendOpts().SkipFunctionBodies = true;
538 
539   auto DataConsumer =
540     std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
541                                           CXTU->getTU());
542   auto InterAction = llvm::make_unique<IndexingFrontendAction>(DataConsumer,
543                          SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
544   std::unique_ptr<FrontendAction> IndexAction;
545   IndexAction = createIndexingAction(DataConsumer,
546                                 getIndexingOptionsFromCXOptions(index_options),
547                                      std::move(InterAction));
548 
549   // Recover resources if we crash before exiting this method.
550   llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
551     IndexActionCleanup(IndexAction.get());
552 
553   bool Persistent = requestedToGetTU;
554   bool OnlyLocalDecls = false;
555   bool PrecompilePreamble = false;
556   bool CreatePreambleOnFirstParse = false;
557   bool CacheCodeCompletionResults = false;
558   PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
559   PPOpts.AllowPCHWithCompilerErrors = true;
560 
561   if (requestedToGetTU) {
562     OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
563     PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
564     CreatePreambleOnFirstParse =
565         TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
566     // FIXME: Add a flag for modules.
567     CacheCodeCompletionResults
568       = TU_options & CXTranslationUnit_CacheCompletionResults;
569   }
570 
571   if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
572     PPOpts.DetailedRecord = true;
573   }
574 
575   if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
576     PPOpts.DetailedRecord = false;
577 
578   // Unless the user specified that they want the preamble on the first parse
579   // set it up to be created on the first reparse. This makes the first parse
580   // faster, trading for a slower (first) reparse.
581   unsigned PrecompilePreambleAfterNParses =
582       !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
583   DiagnosticErrorTrap DiagTrap(*Diags);
584   bool Success = ASTUnit::LoadFromCompilerInvocationAction(
585       CInvok.get(), CXXIdx->getPCHContainerOperations(), Diags,
586       IndexAction.get(), Unit, Persistent, CXXIdx->getClangResourcesPath(),
587       OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
588       CacheCodeCompletionResults,
589       /*IncludeBriefCommentsInCodeCompletion=*/false,
590       /*UserFilesAreVolatile=*/true);
591   if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
592     printDiagsToStderr(Unit);
593 
594   if (isASTReadError(Unit))
595     return CXError_ASTReadError;
596 
597   if (!Success)
598     return CXError_Failure;
599 
600   if (out_TU)
601     *out_TU = CXTU->takeTU();
602 
603   return CXError_Success;
604 }
605 
606 //===----------------------------------------------------------------------===//
607 // clang_indexTranslationUnit Implementation
608 //===----------------------------------------------------------------------===//
609 
610 static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
611   Preprocessor &PP = Unit.getPreprocessor();
612   if (!PP.getPreprocessingRecord())
613     return;
614 
615   // FIXME: Only deserialize inclusion directives.
616 
617   bool isModuleFile = Unit.isModuleFile();
618   for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) {
619     if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
620       SourceLocation Loc = ID->getSourceRange().getBegin();
621       // Modules have synthetic main files as input, give an invalid location
622       // if the location points to such a file.
623       if (isModuleFile && Unit.isInMainFileID(Loc))
624         Loc = SourceLocation();
625       IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
626                             ID->getFile(),
627                             ID->getKind() == InclusionDirective::Import,
628                             !ID->wasInQuotes(), ID->importedModule());
629     }
630   }
631 }
632 
633 static CXErrorCode clang_indexTranslationUnit_Impl(
634     CXIndexAction idxAction, CXClientData client_data,
635     IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
636     unsigned index_options, CXTranslationUnit TU) {
637   // Check arguments.
638   if (isNotUsableTU(TU)) {
639     LOG_BAD_TU(TU);
640     return CXError_InvalidArguments;
641   }
642   if (!client_index_callbacks || index_callbacks_size == 0) {
643     return CXError_InvalidArguments;
644   }
645 
646   CIndexer *CXXIdx = TU->CIdx;
647   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
648     setThreadBackgroundPriority();
649 
650   IndexerCallbacks CB;
651   memset(&CB, 0, sizeof(CB));
652   unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
653                                   ? index_callbacks_size : sizeof(CB);
654   memcpy(&CB, client_index_callbacks, ClientCBSize);
655 
656   auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
657                                                             index_options, TU);
658 
659   ASTUnit *Unit = cxtu::getASTUnit(TU);
660   if (!Unit)
661     return CXError_Failure;
662 
663   ASTUnit::ConcurrencyCheck Check(*Unit);
664 
665   if (const FileEntry *PCHFile = Unit->getPCHFile())
666     DataConsumer->importedPCH(PCHFile);
667 
668   FileManager &FileMgr = Unit->getFileManager();
669 
670   if (Unit->getOriginalSourceFileName().empty())
671     DataConsumer->enteredMainFile(nullptr);
672   else
673     DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
674 
675   DataConsumer->setASTContext(Unit->getASTContext());
676   DataConsumer->startedTranslationUnit();
677 
678   indexPreprocessingRecord(*Unit, *DataConsumer);
679   indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
680   DataConsumer->indexDiagnostics();
681 
682   return CXError_Success;
683 }
684 
685 //===----------------------------------------------------------------------===//
686 // libclang public APIs.
687 //===----------------------------------------------------------------------===//
688 
689 extern "C" {
690 
691 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
692   return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
693 }
694 
695 const CXIdxObjCContainerDeclInfo *
696 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
697   if (!DInfo)
698     return nullptr;
699 
700   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
701   if (const ObjCContainerDeclInfo *
702         ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
703     return &ContInfo->ObjCContDeclInfo;
704 
705   return nullptr;
706 }
707 
708 const CXIdxObjCInterfaceDeclInfo *
709 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
710   if (!DInfo)
711     return nullptr;
712 
713   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
714   if (const ObjCInterfaceDeclInfo *
715         InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
716     return &InterInfo->ObjCInterDeclInfo;
717 
718   return nullptr;
719 }
720 
721 const CXIdxObjCCategoryDeclInfo *
722 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
723   if (!DInfo)
724     return nullptr;
725 
726   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
727   if (const ObjCCategoryDeclInfo *
728         CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
729     return &CatInfo->ObjCCatDeclInfo;
730 
731   return nullptr;
732 }
733 
734 const CXIdxObjCProtocolRefListInfo *
735 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
736   if (!DInfo)
737     return nullptr;
738 
739   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
740 
741   if (const ObjCInterfaceDeclInfo *
742         InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
743     return InterInfo->ObjCInterDeclInfo.protocols;
744 
745   if (const ObjCProtocolDeclInfo *
746         ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
747     return &ProtInfo->ObjCProtoRefListInfo;
748 
749   if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
750     return CatInfo->ObjCCatDeclInfo.protocols;
751 
752   return nullptr;
753 }
754 
755 const CXIdxObjCPropertyDeclInfo *
756 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
757   if (!DInfo)
758     return nullptr;
759 
760   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
761   if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
762     return &PropInfo->ObjCPropDeclInfo;
763 
764   return nullptr;
765 }
766 
767 const CXIdxIBOutletCollectionAttrInfo *
768 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
769   if (!AInfo)
770     return nullptr;
771 
772   const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
773   if (const IBOutletCollectionInfo *
774         IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
775     return &IBInfo->IBCollInfo;
776 
777   return nullptr;
778 }
779 
780 const CXIdxCXXClassDeclInfo *
781 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
782   if (!DInfo)
783     return nullptr;
784 
785   const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
786   if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
787     return &ClassInfo->CXXClassInfo;
788 
789   return nullptr;
790 }
791 
792 CXIdxClientContainer
793 clang_index_getClientContainer(const CXIdxContainerInfo *info) {
794   if (!info)
795     return nullptr;
796   const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
797   return Container->IndexCtx->getClientContainerForDC(Container->DC);
798 }
799 
800 void clang_index_setClientContainer(const CXIdxContainerInfo *info,
801                                     CXIdxClientContainer client) {
802   if (!info)
803     return;
804   const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
805   Container->IndexCtx->addContainerInMap(Container->DC, client);
806 }
807 
808 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
809   if (!info)
810     return nullptr;
811   const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
812   return Entity->IndexCtx->getClientEntity(Entity->Dcl);
813 }
814 
815 void clang_index_setClientEntity(const CXIdxEntityInfo *info,
816                                  CXIdxClientEntity client) {
817   if (!info)
818     return;
819   const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
820   Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
821 }
822 
823 CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
824   return new IndexSessionData(CIdx);
825 }
826 
827 void clang_IndexAction_dispose(CXIndexAction idxAction) {
828   if (idxAction)
829     delete static_cast<IndexSessionData *>(idxAction);
830 }
831 
832 int clang_indexSourceFile(CXIndexAction idxAction,
833                           CXClientData client_data,
834                           IndexerCallbacks *index_callbacks,
835                           unsigned index_callbacks_size,
836                           unsigned index_options,
837                           const char *source_filename,
838                           const char * const *command_line_args,
839                           int num_command_line_args,
840                           struct CXUnsavedFile *unsaved_files,
841                           unsigned num_unsaved_files,
842                           CXTranslationUnit *out_TU,
843                           unsigned TU_options) {
844   SmallVector<const char *, 4> Args;
845   Args.push_back("clang");
846   Args.append(command_line_args, command_line_args + num_command_line_args);
847   return clang_indexSourceFileFullArgv(
848       idxAction, client_data, index_callbacks, index_callbacks_size,
849       index_options, source_filename, Args.data(), Args.size(), unsaved_files,
850       num_unsaved_files, out_TU, TU_options);
851 }
852 
853 int clang_indexSourceFileFullArgv(
854     CXIndexAction idxAction, CXClientData client_data,
855     IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
856     unsigned index_options, const char *source_filename,
857     const char *const *command_line_args, int num_command_line_args,
858     struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
859     CXTranslationUnit *out_TU, unsigned TU_options) {
860   LOG_FUNC_SECTION {
861     *Log << source_filename << ": ";
862     for (int i = 0; i != num_command_line_args; ++i)
863       *Log << command_line_args[i] << " ";
864   }
865 
866   if (num_unsaved_files && !unsaved_files)
867     return CXError_InvalidArguments;
868 
869   CXErrorCode result = CXError_Failure;
870   auto IndexSourceFileImpl = [=, &result]() {
871     result = clang_indexSourceFile_Impl(
872         idxAction, client_data, index_callbacks, index_callbacks_size,
873         index_options, source_filename, command_line_args,
874         num_command_line_args,
875         llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU,
876         TU_options);
877   };
878 
879   if (getenv("LIBCLANG_NOTHREADS")) {
880     IndexSourceFileImpl();
881     return result;
882   }
883 
884   llvm::CrashRecoveryContext CRC;
885 
886   if (!RunSafely(CRC, IndexSourceFileImpl)) {
887     fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
888     fprintf(stderr, "  'source_filename' : '%s'\n", source_filename);
889     fprintf(stderr, "  'command_line_args' : [");
890     for (int i = 0; i != num_command_line_args; ++i) {
891       if (i)
892         fprintf(stderr, ", ");
893       fprintf(stderr, "'%s'", command_line_args[i]);
894     }
895     fprintf(stderr, "],\n");
896     fprintf(stderr, "  'unsaved_files' : [");
897     for (unsigned i = 0; i != num_unsaved_files; ++i) {
898       if (i)
899         fprintf(stderr, ", ");
900       fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
901               unsaved_files[i].Length);
902     }
903     fprintf(stderr, "],\n");
904     fprintf(stderr, "  'options' : %d,\n", TU_options);
905     fprintf(stderr, "}\n");
906 
907     return 1;
908   } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
909     if (out_TU)
910       PrintLibclangResourceUsage(*out_TU);
911   }
912 
913   return result;
914 }
915 
916 int clang_indexTranslationUnit(CXIndexAction idxAction,
917                                CXClientData client_data,
918                                IndexerCallbacks *index_callbacks,
919                                unsigned index_callbacks_size,
920                                unsigned index_options,
921                                CXTranslationUnit TU) {
922   LOG_FUNC_SECTION {
923     *Log << TU;
924   }
925 
926   CXErrorCode result;
927   auto IndexTranslationUnitImpl = [=, &result]() {
928     result = clang_indexTranslationUnit_Impl(
929         idxAction, client_data, index_callbacks, index_callbacks_size,
930         index_options, TU);
931   };
932 
933   if (getenv("LIBCLANG_NOTHREADS")) {
934     IndexTranslationUnitImpl();
935     return result;
936   }
937 
938   llvm::CrashRecoveryContext CRC;
939 
940   if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
941     fprintf(stderr, "libclang: crash detected during indexing TU\n");
942 
943     return 1;
944   }
945 
946   return result;
947 }
948 
949 void clang_indexLoc_getFileLocation(CXIdxLoc location,
950                                     CXIdxClientFile *indexFile,
951                                     CXFile *file,
952                                     unsigned *line,
953                                     unsigned *column,
954                                     unsigned *offset) {
955   if (indexFile) *indexFile = nullptr;
956   if (file)   *file = nullptr;
957   if (line)   *line = 0;
958   if (column) *column = 0;
959   if (offset) *offset = 0;
960 
961   SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
962   if (!location.ptr_data[0] || Loc.isInvalid())
963     return;
964 
965   CXIndexDataConsumer &DataConsumer =
966       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
967   DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
968 }
969 
970 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
971   SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
972   if (!location.ptr_data[0] || Loc.isInvalid())
973     return clang_getNullLocation();
974 
975   CXIndexDataConsumer &DataConsumer =
976       *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
977   return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
978 }
979 
980 } // end: extern "C"
981 
982