Indexing.cpp 33 KB

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