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 "IndexingContext.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/AST/DeclVisitor.h"
20#include "clang/Frontend/ASTUnit.h"
21#include "clang/Frontend/CompilerInstance.h"
22#include "clang/Frontend/CompilerInvocation.h"
23#include "clang/Frontend/FrontendAction.h"
24#include "clang/Frontend/Utils.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
36using namespace clang;
37using namespace cxtu;
38using namespace cxindex;
39
40static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx);
41
42namespace {
43
44//===----------------------------------------------------------------------===//
45// Skip Parsed Bodies
46//===----------------------------------------------------------------------===//
47
48#ifdef LLVM_ON_WIN32
49
50// FIXME: On windows it is disabled since current implementation depends on
51// file inodes.
52
53class SessionSkipBodyData { };
54
55class TUSkipBodyControl {
56public:
57  TUSkipBodyControl(SessionSkipBodyData &sessionData,
58                    PPConditionalDirectiveRecord &ppRec,
59                    Preprocessor &pp) { }
60  bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
61    return false;
62  }
63  void finished() { }
64};
65
66#else
67
68/// \brief A "region" in source code identified by the file/offset of the
69/// preprocessor conditional directive that it belongs to.
70/// Multiple, non-consecutive ranges can be parts of the same region.
71///
72/// As an example of different regions separated by preprocessor directives:
73///
74/// \code
75///   #1
76/// #ifdef BLAH
77///   #2
78/// #ifdef CAKE
79///   #3
80/// #endif
81///   #2
82/// #endif
83///   #1
84/// \endcode
85///
86/// There are 3 regions, with non-consecutive parts:
87///   #1 is identified as the beginning of the file
88///   #2 is identified as the location of "#ifdef BLAH"
89///   #3 is identified as the location of "#ifdef CAKE"
90///
91class PPRegion {
92  llvm::sys::fs::UniqueID UniqueID;
93  time_t ModTime;
94  unsigned Offset;
95public:
96  PPRegion() : UniqueID(0, 0), ModTime(), Offset() {}
97  PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime)
98      : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {}
99
100  const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
101  unsigned getOffset() const { return Offset; }
102  time_t getModTime() const { return ModTime; }
103
104  bool isInvalid() const { return *this == PPRegion(); }
105
106  friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) {
107    return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset &&
108           lhs.ModTime == rhs.ModTime;
109  }
110};
111
112typedef llvm::DenseSet<PPRegion> PPRegionSetTy;
113
114} // end anonymous namespace
115
116namespace llvm {
117  template <> struct isPodLike<PPRegion> {
118    static const bool value = true;
119  };
120
121  template <>
122  struct DenseMapInfo<PPRegion> {
123    static inline PPRegion getEmptyKey() {
124      return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
125    }
126    static inline PPRegion getTombstoneKey() {
127      return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
128    }
129
130    static unsigned getHashValue(const PPRegion &S) {
131      llvm::FoldingSetNodeID ID;
132      const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
133      ID.AddInteger(UniqueID.getFile());
134      ID.AddInteger(UniqueID.getDevice());
135      ID.AddInteger(S.getOffset());
136      ID.AddInteger(S.getModTime());
137      return ID.ComputeHash();
138    }
139
140    static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
141      return LHS == RHS;
142    }
143  };
144}
145
146namespace {
147
148class SessionSkipBodyData {
149  llvm::sys::Mutex Mux;
150  PPRegionSetTy ParsedRegions;
151
152public:
153  SessionSkipBodyData() : Mux(/*recursive=*/false) {}
154  ~SessionSkipBodyData() {
155    //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n";
156  }
157
158  void copyTo(PPRegionSetTy &Set) {
159    llvm::MutexGuard MG(Mux);
160    Set = ParsedRegions;
161  }
162
163  void update(ArrayRef<PPRegion> Regions) {
164    llvm::MutexGuard MG(Mux);
165    ParsedRegions.insert(Regions.begin(), Regions.end());
166  }
167};
168
169class TUSkipBodyControl {
170  SessionSkipBodyData &SessionData;
171  PPConditionalDirectiveRecord &PPRec;
172  Preprocessor &PP;
173
174  PPRegionSetTy ParsedRegions;
175  SmallVector<PPRegion, 32> NewParsedRegions;
176  PPRegion LastRegion;
177  bool LastIsParsed;
178
179public:
180  TUSkipBodyControl(SessionSkipBodyData &sessionData,
181                    PPConditionalDirectiveRecord &ppRec,
182                    Preprocessor &pp)
183    : SessionData(sessionData), PPRec(ppRec), PP(pp) {
184    SessionData.copyTo(ParsedRegions);
185  }
186
187  bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
188    PPRegion region = getRegion(Loc, FID, FE);
189    if (region.isInvalid())
190      return false;
191
192    // Check common case, consecutive functions in the same region.
193    if (LastRegion == region)
194      return LastIsParsed;
195
196    LastRegion = region;
197    LastIsParsed = ParsedRegions.count(region);
198    if (!LastIsParsed)
199      NewParsedRegions.push_back(region);
200    return LastIsParsed;
201  }
202
203  void finished() {
204    SessionData.update(NewParsedRegions);
205  }
206
207private:
208  PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
209    SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
210    if (RegionLoc.isInvalid()) {
211      if (isParsedOnceInclude(FE)) {
212        const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
213        return PPRegion(ID, 0, FE->getModificationTime());
214      }
215      return PPRegion();
216    }
217
218    const SourceManager &SM = PPRec.getSourceManager();
219    assert(RegionLoc.isFileID());
220    FileID RegionFID;
221    unsigned RegionOffset;
222    std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
223
224    if (RegionFID != FID) {
225      if (isParsedOnceInclude(FE)) {
226        const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
227        return PPRegion(ID, 0, FE->getModificationTime());
228      }
229      return PPRegion();
230    }
231
232    const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
233    return PPRegion(ID, RegionOffset, FE->getModificationTime());
234  }
235
236  bool isParsedOnceInclude(const FileEntry *FE) {
237    return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
238  }
239};
240
241#endif
242
243//===----------------------------------------------------------------------===//
244// IndexPPCallbacks
245//===----------------------------------------------------------------------===//
246
247class IndexPPCallbacks : public PPCallbacks {
248  Preprocessor &PP;
249  IndexingContext &IndexCtx;
250  bool IsMainFileEntered;
251
252public:
253  IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx)
254    : PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { }
255
256  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
257                 SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
258    if (IsMainFileEntered)
259      return;
260
261    SourceManager &SM = PP.getSourceManager();
262    SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
263
264    if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
265      IsMainFileEntered = true;
266      IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
267    }
268  }
269
270  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
271                          StringRef FileName, bool IsAngled,
272                          CharSourceRange FilenameRange, const FileEntry *File,
273                          StringRef SearchPath, StringRef RelativePath,
274                          const Module *Imported) override {
275    bool isImport = (IncludeTok.is(tok::identifier) &&
276            IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
277    IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
278                            Imported);
279  }
280
281  /// MacroDefined - This hook is called whenever a macro definition is seen.
282  void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
283
284  /// MacroUndefined - This hook is called whenever a macro #undef is seen.
285  /// MI is released immediately following this callback.
286  void MacroUndefined(const Token &MacroNameTok,
287                      const MacroDirective *MD) override {}
288
289  /// MacroExpands - This is called by when a macro invocation is found.
290  void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
291                    SourceRange Range, const MacroArgs *Args) override {}
292
293  /// SourceRangeSkipped - This hook is called when a source range is skipped.
294  /// \param Range The SourceRange that was skipped. The range begins at the
295  /// #if/#else directive and ends after the #endif/#else directive.
296  void SourceRangeSkipped(SourceRange Range) override {}
297};
298
299//===----------------------------------------------------------------------===//
300// IndexingConsumer
301//===----------------------------------------------------------------------===//
302
303class IndexingConsumer : public ASTConsumer {
304  IndexingContext &IndexCtx;
305  TUSkipBodyControl *SKCtrl;
306
307public:
308  IndexingConsumer(IndexingContext &indexCtx, TUSkipBodyControl *skCtrl)
309    : IndexCtx(indexCtx), SKCtrl(skCtrl) { }
310
311  // ASTConsumer Implementation
312
313  void Initialize(ASTContext &Context) override {
314    IndexCtx.setASTContext(Context);
315    IndexCtx.startedTranslationUnit();
316  }
317
318  void HandleTranslationUnit(ASTContext &Ctx) override {
319    if (SKCtrl)
320      SKCtrl->finished();
321  }
322
323  bool HandleTopLevelDecl(DeclGroupRef DG) override {
324    IndexCtx.indexDeclGroupRef(DG);
325    return !IndexCtx.shouldAbort();
326  }
327
328  /// \brief Handle the specified top-level declaration that occurred inside
329  /// and ObjC container.
330  void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
331    // They will be handled after the interface is seen first.
332    IndexCtx.addTUDeclInObjCContainer(D);
333  }
334
335  /// \brief This is called by the AST reader when deserializing things.
336  /// The default implementation forwards to HandleTopLevelDecl but we don't
337  /// care about them when indexing, so have an empty definition.
338  void HandleInterestingDecl(DeclGroupRef D) override {}
339
340  void HandleTagDeclDefinition(TagDecl *D) override {
341    if (!IndexCtx.shouldIndexImplicitTemplateInsts())
342      return;
343
344    if (IndexCtx.isTemplateImplicitInstantiation(D))
345      IndexCtx.indexDecl(D);
346  }
347
348  void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override {
349    if (!IndexCtx.shouldIndexImplicitTemplateInsts())
350      return;
351
352    IndexCtx.indexDecl(D);
353  }
354
355  bool shouldSkipFunctionBody(Decl *D) override {
356    if (!SKCtrl) {
357      // Always skip bodies.
358      return true;
359    }
360
361    const SourceManager &SM = IndexCtx.getASTContext().getSourceManager();
362    SourceLocation Loc = D->getLocation();
363    if (Loc.isMacroID())
364      return false;
365    if (SM.isInSystemHeader(Loc))
366      return true; // always skip bodies from system headers.
367
368    FileID FID;
369    unsigned Offset;
370    std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
371    // Don't skip bodies from main files; this may be revisited.
372    if (SM.getMainFileID() == FID)
373      return false;
374    const FileEntry *FE = SM.getFileEntryForID(FID);
375    if (!FE)
376      return false;
377
378    return SKCtrl->isParsed(Loc, FID, FE);
379  }
380};
381
382//===----------------------------------------------------------------------===//
383// CaptureDiagnosticConsumer
384//===----------------------------------------------------------------------===//
385
386class CaptureDiagnosticConsumer : public DiagnosticConsumer {
387  SmallVector<StoredDiagnostic, 4> Errors;
388public:
389
390  void HandleDiagnostic(DiagnosticsEngine::Level level,
391                        const Diagnostic &Info) override {
392    if (level >= DiagnosticsEngine::Error)
393      Errors.push_back(StoredDiagnostic(level, Info));
394  }
395};
396
397//===----------------------------------------------------------------------===//
398// IndexingFrontendAction
399//===----------------------------------------------------------------------===//
400
401class IndexingFrontendAction : public ASTFrontendAction {
402  IndexingContext IndexCtx;
403  CXTranslationUnit CXTU;
404
405  SessionSkipBodyData *SKData;
406  std::unique_ptr<TUSkipBodyControl> SKCtrl;
407
408public:
409  IndexingFrontendAction(CXClientData clientData,
410                         IndexerCallbacks &indexCallbacks,
411                         unsigned indexOptions,
412                         CXTranslationUnit cxTU,
413                         SessionSkipBodyData *skData)
414    : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU),
415      CXTU(cxTU), SKData(skData) { }
416
417  ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
418                                 StringRef InFile) override {
419    PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
420
421    if (!PPOpts.ImplicitPCHInclude.empty()) {
422      IndexCtx.importedPCH(
423                        CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
424    }
425
426    IndexCtx.setASTContext(CI.getASTContext());
427    Preprocessor &PP = CI.getPreprocessor();
428    PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx));
429    IndexCtx.setPreprocessor(PP);
430
431    if (SKData) {
432      PPConditionalDirectiveRecord *
433        PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
434      PP.addPPCallbacks(PPRec);
435      SKCtrl.reset(new TUSkipBodyControl(*SKData, *PPRec, PP));
436    }
437
438    return new IndexingConsumer(IndexCtx, SKCtrl.get());
439  }
440
441  void EndSourceFileAction() override {
442    indexDiagnostics(CXTU, IndexCtx);
443  }
444
445  TranslationUnitKind getTranslationUnitKind() override {
446    if (IndexCtx.shouldIndexImplicitTemplateInsts())
447      return TU_Complete;
448    else
449      return TU_Prefix;
450  }
451  bool hasCodeCompletionSupport() const override { return false; }
452};
453
454//===----------------------------------------------------------------------===//
455// clang_indexSourceFileUnit Implementation
456//===----------------------------------------------------------------------===//
457
458struct IndexSessionData {
459  CXIndex CIdx;
460  std::unique_ptr<SessionSkipBodyData> SkipBodyData;
461
462  explicit IndexSessionData(CXIndex cIdx)
463    : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
464};
465
466struct IndexSourceFileInfo {
467  CXIndexAction idxAction;
468  CXClientData client_data;
469  IndexerCallbacks *index_callbacks;
470  unsigned index_callbacks_size;
471  unsigned index_options;
472  const char *source_filename;
473  const char *const *command_line_args;
474  int num_command_line_args;
475  ArrayRef<CXUnsavedFile> unsaved_files;
476  CXTranslationUnit *out_TU;
477  unsigned TU_options;
478  CXErrorCode &result;
479};
480
481} // anonymous namespace
482
483static void clang_indexSourceFile_Impl(void *UserData) {
484  const IndexSourceFileInfo *ITUI =
485      static_cast<IndexSourceFileInfo *>(UserData);
486  CXIndexAction cxIdxAction = ITUI->idxAction;
487  CXClientData client_data = ITUI->client_data;
488  IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
489  unsigned index_callbacks_size = ITUI->index_callbacks_size;
490  unsigned index_options = ITUI->index_options;
491  const char *source_filename = ITUI->source_filename;
492  const char * const *command_line_args = ITUI->command_line_args;
493  int num_command_line_args = ITUI->num_command_line_args;
494  CXTranslationUnit *out_TU  = ITUI->out_TU;
495  unsigned TU_options = ITUI->TU_options;
496
497  if (out_TU)
498    *out_TU = nullptr;
499  bool requestedToGetTU = (out_TU != nullptr);
500
501  if (!cxIdxAction) {
502    ITUI->result = CXError_InvalidArguments;
503    return;
504  }
505  if (!client_index_callbacks || index_callbacks_size == 0) {
506    ITUI->result = CXError_InvalidArguments;
507    return;
508  }
509
510  IndexerCallbacks CB;
511  memset(&CB, 0, sizeof(CB));
512  unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
513                                  ? index_callbacks_size : sizeof(CB);
514  memcpy(&CB, client_index_callbacks, ClientCBSize);
515
516  IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction);
517  CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx);
518
519  if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
520    setThreadBackgroundPriority();
521
522  bool CaptureDiagnostics = !Logger::isLoggingEnabled();
523
524  CaptureDiagnosticConsumer *CaptureDiag = nullptr;
525  if (CaptureDiagnostics)
526    CaptureDiag = new CaptureDiagnosticConsumer();
527
528  // Configure the diagnostics.
529  IntrusiveRefCntPtr<DiagnosticsEngine>
530    Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
531                                              CaptureDiag,
532                                              /*ShouldOwnClient=*/true));
533
534  // Recover resources if we crash before exiting this function.
535  llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
536    llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
537    DiagCleanup(Diags.get());
538
539  std::unique_ptr<std::vector<const char *>> Args(
540      new std::vector<const char *>());
541
542  // Recover resources if we crash before exiting this method.
543  llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
544    ArgsCleanup(Args.get());
545
546  Args->insert(Args->end(), command_line_args,
547               command_line_args + num_command_line_args);
548
549  // The 'source_filename' argument is optional.  If the caller does not
550  // specify it then it is assumed that the source file is specified
551  // in the actual argument list.
552  // Put the source file after command_line_args otherwise if '-x' flag is
553  // present it will be unused.
554  if (source_filename)
555    Args->push_back(source_filename);
556
557  IntrusiveRefCntPtr<CompilerInvocation>
558    CInvok(createInvocationFromCommandLine(*Args, Diags));
559
560  if (!CInvok)
561    return;
562
563  // Recover resources if we crash before exiting this function.
564  llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
565    llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> >
566    CInvokCleanup(CInvok.get());
567
568  if (CInvok->getFrontendOpts().Inputs.empty())
569    return;
570
571  typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
572  std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
573
574  // Recover resources if we crash before exiting this method.
575  llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
576      BufOwner.get());
577
578  for (auto &UF : ITUI->unsaved_files) {
579    llvm::MemoryBuffer *MB =
580        llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
581    BufOwner->push_back(std::unique_ptr<llvm::MemoryBuffer>(MB));
582    CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB);
583  }
584
585  // Since libclang is primarily used by batch tools dealing with
586  // (often very broken) source code, where spell-checking can have a
587  // significant negative impact on performance (particularly when
588  // precompiled headers are involved), we disable it.
589  CInvok->getLangOpts()->SpellChecking = false;
590
591  if (index_options & CXIndexOpt_SuppressWarnings)
592    CInvok->getDiagnosticOpts().IgnoreWarnings = true;
593
594  ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags,
595                                  CaptureDiagnostics,
596                                  /*UserFilesAreVolatile=*/true);
597  if (!Unit) {
598    ITUI->result = CXError_InvalidArguments;
599    return;
600  }
601
602  std::unique_ptr<CXTUOwner> CXTU(
603      new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
604
605  // Recover resources if we crash before exiting this method.
606  llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
607    CXTUCleanup(CXTU.get());
608
609  // Enable the skip-parsed-bodies optimization only for C++; this may be
610  // revisited.
611  bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) &&
612      CInvok->getLangOpts()->CPlusPlus;
613  if (SkipBodies)
614    CInvok->getFrontendOpts().SkipFunctionBodies = true;
615
616  std::unique_ptr<IndexingFrontendAction> IndexAction;
617  IndexAction.reset(new IndexingFrontendAction(client_data, CB,
618                                               index_options, CXTU->getTU(),
619                        SkipBodies ? IdxSession->SkipBodyData.get() : nullptr));
620
621  // Recover resources if we crash before exiting this method.
622  llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction>
623    IndexActionCleanup(IndexAction.get());
624
625  bool Persistent = requestedToGetTU;
626  bool OnlyLocalDecls = false;
627  bool PrecompilePreamble = false;
628  bool CacheCodeCompletionResults = false;
629  PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
630  PPOpts.AllowPCHWithCompilerErrors = true;
631
632  if (requestedToGetTU) {
633    OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
634    PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
635    // FIXME: Add a flag for modules.
636    CacheCodeCompletionResults
637      = TU_options & CXTranslationUnit_CacheCompletionResults;
638  }
639
640  if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
641    PPOpts.DetailedRecord = true;
642  }
643
644  if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
645    PPOpts.DetailedRecord = false;
646
647  DiagnosticErrorTrap DiagTrap(*Diags);
648  bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), Diags,
649                                                       IndexAction.get(),
650                                                       Unit,
651                                                       Persistent,
652                                                CXXIdx->getClangResourcesPath(),
653                                                       OnlyLocalDecls,
654                                                       CaptureDiagnostics,
655                                                       PrecompilePreamble,
656                                                    CacheCodeCompletionResults,
657                                 /*IncludeBriefCommentsInCodeCompletion=*/false,
658                                                 /*UserFilesAreVolatile=*/true);
659  if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
660    printDiagsToStderr(Unit);
661
662  if (isASTReadError(Unit)) {
663    ITUI->result = CXError_ASTReadError;
664    return;
665  }
666
667  if (!Success)
668    return;
669
670  if (out_TU)
671    *out_TU = CXTU->takeTU();
672
673  ITUI->result = CXError_Success;
674}
675
676//===----------------------------------------------------------------------===//
677// clang_indexTranslationUnit Implementation
678//===----------------------------------------------------------------------===//
679
680namespace {
681
682struct IndexTranslationUnitInfo {
683  CXIndexAction idxAction;
684  CXClientData client_data;
685  IndexerCallbacks *index_callbacks;
686  unsigned index_callbacks_size;
687  unsigned index_options;
688  CXTranslationUnit TU;
689  int result;
690};
691
692} // anonymous namespace
693
694static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
695  Preprocessor &PP = Unit.getPreprocessor();
696  if (!PP.getPreprocessingRecord())
697    return;
698
699  // FIXME: Only deserialize inclusion directives.
700
701  PreprocessingRecord::iterator I, E;
702  std::tie(I, E) = Unit.getLocalPreprocessingEntities();
703
704  bool isModuleFile = Unit.isModuleFile();
705  for (; I != E; ++I) {
706    PreprocessedEntity *PPE = *I;
707
708    if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
709      SourceLocation Loc = ID->getSourceRange().getBegin();
710      // Modules have synthetic main files as input, give an invalid location
711      // if the location points to such a file.
712      if (isModuleFile && Unit.isInMainFileID(Loc))
713        Loc = SourceLocation();
714      IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
715                            ID->getFile(),
716                            ID->getKind() == InclusionDirective::Import,
717                            !ID->wasInQuotes(), ID->importedModule());
718    }
719  }
720}
721
722static bool topLevelDeclVisitor(void *context, const Decl *D) {
723  IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context);
724  IdxCtx.indexTopLevelDecl(D);
725  if (IdxCtx.shouldAbort())
726    return false;
727  return true;
728}
729
730static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
731  Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor);
732}
733
734static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
735  if (!IdxCtx.hasDiagnosticCallback())
736    return;
737
738  CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU);
739  IdxCtx.handleDiagnosticSet(DiagSet);
740}
741
742static void clang_indexTranslationUnit_Impl(void *UserData) {
743  IndexTranslationUnitInfo *ITUI =
744    static_cast<IndexTranslationUnitInfo*>(UserData);
745  CXTranslationUnit TU = ITUI->TU;
746  CXClientData client_data = ITUI->client_data;
747  IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
748  unsigned index_callbacks_size = ITUI->index_callbacks_size;
749  unsigned index_options = ITUI->index_options;
750
751  // Set up the initial return value.
752  ITUI->result = CXError_Failure;
753
754  // Check arguments.
755  if (isNotUsableTU(TU)) {
756    LOG_BAD_TU(TU);
757    ITUI->result = CXError_InvalidArguments;
758    return;
759  }
760  if (!client_index_callbacks || index_callbacks_size == 0) {
761    ITUI->result = CXError_InvalidArguments;
762    return;
763  }
764
765  CIndexer *CXXIdx = TU->CIdx;
766  if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
767    setThreadBackgroundPriority();
768
769  IndexerCallbacks CB;
770  memset(&CB, 0, sizeof(CB));
771  unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
772                                  ? index_callbacks_size : sizeof(CB);
773  memcpy(&CB, client_index_callbacks, ClientCBSize);
774
775  std::unique_ptr<IndexingContext> IndexCtx;
776  IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU));
777
778  // Recover resources if we crash before exiting this method.
779  llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext>
780    IndexCtxCleanup(IndexCtx.get());
781
782  std::unique_ptr<IndexingConsumer> IndexConsumer;
783  IndexConsumer.reset(new IndexingConsumer(*IndexCtx, nullptr));
784
785  // Recover resources if we crash before exiting this method.
786  llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer>
787    IndexConsumerCleanup(IndexConsumer.get());
788
789  ASTUnit *Unit = cxtu::getASTUnit(TU);
790  if (!Unit)
791    return;
792
793  ASTUnit::ConcurrencyCheck Check(*Unit);
794
795  if (const FileEntry *PCHFile = Unit->getPCHFile())
796    IndexCtx->importedPCH(PCHFile);
797
798  FileManager &FileMgr = Unit->getFileManager();
799
800  if (Unit->getOriginalSourceFileName().empty())
801    IndexCtx->enteredMainFile(nullptr);
802  else
803    IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
804
805  IndexConsumer->Initialize(Unit->getASTContext());
806
807  indexPreprocessingRecord(*Unit, *IndexCtx);
808  indexTranslationUnit(*Unit, *IndexCtx);
809  indexDiagnostics(TU, *IndexCtx);
810
811  ITUI->result = CXError_Success;
812}
813
814//===----------------------------------------------------------------------===//
815// libclang public APIs.
816//===----------------------------------------------------------------------===//
817
818extern "C" {
819
820int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
821  return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
822}
823
824const CXIdxObjCContainerDeclInfo *
825clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
826  if (!DInfo)
827    return nullptr;
828
829  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
830  if (const ObjCContainerDeclInfo *
831        ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
832    return &ContInfo->ObjCContDeclInfo;
833
834  return nullptr;
835}
836
837const CXIdxObjCInterfaceDeclInfo *
838clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
839  if (!DInfo)
840    return nullptr;
841
842  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
843  if (const ObjCInterfaceDeclInfo *
844        InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
845    return &InterInfo->ObjCInterDeclInfo;
846
847  return nullptr;
848}
849
850const CXIdxObjCCategoryDeclInfo *
851clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
852  if (!DInfo)
853    return nullptr;
854
855  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
856  if (const ObjCCategoryDeclInfo *
857        CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
858    return &CatInfo->ObjCCatDeclInfo;
859
860  return nullptr;
861}
862
863const CXIdxObjCProtocolRefListInfo *
864clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
865  if (!DInfo)
866    return nullptr;
867
868  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
869
870  if (const ObjCInterfaceDeclInfo *
871        InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
872    return InterInfo->ObjCInterDeclInfo.protocols;
873
874  if (const ObjCProtocolDeclInfo *
875        ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
876    return &ProtInfo->ObjCProtoRefListInfo;
877
878  if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
879    return CatInfo->ObjCCatDeclInfo.protocols;
880
881  return nullptr;
882}
883
884const CXIdxObjCPropertyDeclInfo *
885clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
886  if (!DInfo)
887    return nullptr;
888
889  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
890  if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
891    return &PropInfo->ObjCPropDeclInfo;
892
893  return nullptr;
894}
895
896const CXIdxIBOutletCollectionAttrInfo *
897clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
898  if (!AInfo)
899    return nullptr;
900
901  const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
902  if (const IBOutletCollectionInfo *
903        IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
904    return &IBInfo->IBCollInfo;
905
906  return nullptr;
907}
908
909const CXIdxCXXClassDeclInfo *
910clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
911  if (!DInfo)
912    return nullptr;
913
914  const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
915  if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
916    return &ClassInfo->CXXClassInfo;
917
918  return nullptr;
919}
920
921CXIdxClientContainer
922clang_index_getClientContainer(const CXIdxContainerInfo *info) {
923  if (!info)
924    return nullptr;
925  const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
926  return Container->IndexCtx->getClientContainerForDC(Container->DC);
927}
928
929void clang_index_setClientContainer(const CXIdxContainerInfo *info,
930                                    CXIdxClientContainer client) {
931  if (!info)
932    return;
933  const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
934  Container->IndexCtx->addContainerInMap(Container->DC, client);
935}
936
937CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
938  if (!info)
939    return nullptr;
940  const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
941  return Entity->IndexCtx->getClientEntity(Entity->Dcl);
942}
943
944void clang_index_setClientEntity(const CXIdxEntityInfo *info,
945                                 CXIdxClientEntity client) {
946  if (!info)
947    return;
948  const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
949  Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
950}
951
952CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
953  return new IndexSessionData(CIdx);
954}
955
956void clang_IndexAction_dispose(CXIndexAction idxAction) {
957  if (idxAction)
958    delete static_cast<IndexSessionData *>(idxAction);
959}
960
961int clang_indexSourceFile(CXIndexAction idxAction,
962                          CXClientData client_data,
963                          IndexerCallbacks *index_callbacks,
964                          unsigned index_callbacks_size,
965                          unsigned index_options,
966                          const char *source_filename,
967                          const char * const *command_line_args,
968                          int num_command_line_args,
969                          struct CXUnsavedFile *unsaved_files,
970                          unsigned num_unsaved_files,
971                          CXTranslationUnit *out_TU,
972                          unsigned TU_options) {
973  LOG_FUNC_SECTION {
974    *Log << source_filename << ": ";
975    for (int i = 0; i != num_command_line_args; ++i)
976      *Log << command_line_args[i] << " ";
977  }
978
979  if (num_unsaved_files && !unsaved_files)
980    return CXError_InvalidArguments;
981
982  CXErrorCode result = CXError_Failure;
983  IndexSourceFileInfo ITUI = {
984      idxAction,
985      client_data,
986      index_callbacks,
987      index_callbacks_size,
988      index_options,
989      source_filename,
990      command_line_args,
991      num_command_line_args,
992      llvm::makeArrayRef(unsaved_files, num_unsaved_files),
993      out_TU,
994      TU_options,
995      result};
996
997  if (getenv("LIBCLANG_NOTHREADS")) {
998    clang_indexSourceFile_Impl(&ITUI);
999    return result;
1000  }
1001
1002  llvm::CrashRecoveryContext CRC;
1003
1004  if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) {
1005    fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
1006    fprintf(stderr, "  'source_filename' : '%s'\n", source_filename);
1007    fprintf(stderr, "  'command_line_args' : [");
1008    for (int i = 0; i != num_command_line_args; ++i) {
1009      if (i)
1010        fprintf(stderr, ", ");
1011      fprintf(stderr, "'%s'", command_line_args[i]);
1012    }
1013    fprintf(stderr, "],\n");
1014    fprintf(stderr, "  'unsaved_files' : [");
1015    for (unsigned i = 0; i != num_unsaved_files; ++i) {
1016      if (i)
1017        fprintf(stderr, ", ");
1018      fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
1019              unsaved_files[i].Length);
1020    }
1021    fprintf(stderr, "],\n");
1022    fprintf(stderr, "  'options' : %d,\n", TU_options);
1023    fprintf(stderr, "}\n");
1024
1025    return 1;
1026  } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
1027    if (out_TU)
1028      PrintLibclangResourceUsage(*out_TU);
1029  }
1030
1031  return result;
1032}
1033
1034int clang_indexTranslationUnit(CXIndexAction idxAction,
1035                               CXClientData client_data,
1036                               IndexerCallbacks *index_callbacks,
1037                               unsigned index_callbacks_size,
1038                               unsigned index_options,
1039                               CXTranslationUnit TU) {
1040  LOG_FUNC_SECTION {
1041    *Log << TU;
1042  }
1043
1044  IndexTranslationUnitInfo ITUI = { idxAction, client_data, index_callbacks,
1045                                    index_callbacks_size, index_options, TU,
1046                                    0 };
1047
1048  if (getenv("LIBCLANG_NOTHREADS")) {
1049    clang_indexTranslationUnit_Impl(&ITUI);
1050    return ITUI.result;
1051  }
1052
1053  llvm::CrashRecoveryContext CRC;
1054
1055  if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) {
1056    fprintf(stderr, "libclang: crash detected during indexing TU\n");
1057
1058    return 1;
1059  }
1060
1061  return ITUI.result;
1062}
1063
1064void clang_indexLoc_getFileLocation(CXIdxLoc location,
1065                                    CXIdxClientFile *indexFile,
1066                                    CXFile *file,
1067                                    unsigned *line,
1068                                    unsigned *column,
1069                                    unsigned *offset) {
1070  if (indexFile) *indexFile = nullptr;
1071  if (file)   *file = nullptr;
1072  if (line)   *line = 0;
1073  if (column) *column = 0;
1074  if (offset) *offset = 0;
1075
1076  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
1077  if (!location.ptr_data[0] || Loc.isInvalid())
1078    return;
1079
1080  IndexingContext &IndexCtx =
1081      *static_cast<IndexingContext*>(location.ptr_data[0]);
1082  IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset);
1083}
1084
1085CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
1086  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
1087  if (!location.ptr_data[0] || Loc.isInvalid())
1088    return clang_getNullLocation();
1089
1090  IndexingContext &IndexCtx =
1091      *static_cast<IndexingContext*>(location.ptr_data[0]);
1092  return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc);
1093}
1094
1095} // end: extern "C"
1096
1097