Indexing.cpp 34 KB

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