Indexing.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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,
  226. OptionalFileEntryRef File, StringRef SearchPath,
  227. StringRef RelativePath, 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. CreateInvocationOptions CIOpts;
  427. CIOpts.Diags = Diags;
  428. CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?
  429. std::shared_ptr<CompilerInvocation> CInvok =
  430. createInvocation(*Args, std::move(CIOpts));
  431. if (!CInvok)
  432. return CXError_Failure;
  433. // Recover resources if we crash before exiting this function.
  434. llvm::CrashRecoveryContextCleanupRegistrar<
  435. std::shared_ptr<CompilerInvocation>,
  436. llvm::CrashRecoveryContextDestructorCleanup<
  437. std::shared_ptr<CompilerInvocation>>>
  438. CInvokCleanup(&CInvok);
  439. if (CInvok->getFrontendOpts().Inputs.empty())
  440. return CXError_Failure;
  441. typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
  442. std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
  443. // Recover resources if we crash before exiting this method.
  444. llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
  445. BufOwner.get());
  446. for (auto &UF : unsaved_files) {
  447. std::unique_ptr<llvm::MemoryBuffer> MB =
  448. llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
  449. CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
  450. BufOwner->push_back(std::move(MB));
  451. }
  452. // Since libclang is primarily used by batch tools dealing with
  453. // (often very broken) source code, where spell-checking can have a
  454. // significant negative impact on performance (particularly when
  455. // precompiled headers are involved), we disable it.
  456. CInvok->getLangOpts()->SpellChecking = false;
  457. if (index_options & CXIndexOpt_SuppressWarnings)
  458. CInvok->getDiagnosticOpts().IgnoreWarnings = true;
  459. // Make sure to use the raw module format.
  460. CInvok->getHeaderSearchOpts().ModuleFormat = std::string(
  461. CXXIdx->getPCHContainerOperations()->getRawReader().getFormat());
  462. auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics,
  463. /*UserFilesAreVolatile=*/true);
  464. if (!Unit)
  465. return CXError_InvalidArguments;
  466. auto *UPtr = Unit.get();
  467. std::unique_ptr<CXTUOwner> CXTU(
  468. new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit))));
  469. // Recover resources if we crash before exiting this method.
  470. llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
  471. CXTUCleanup(CXTU.get());
  472. // Enable the skip-parsed-bodies optimization only for C++; this may be
  473. // revisited.
  474. bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) &&
  475. CInvok->getLangOpts()->CPlusPlus;
  476. if (SkipBodies)
  477. CInvok->getFrontendOpts().SkipFunctionBodies = true;
  478. auto DataConsumer =
  479. std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
  480. CXTU->getTU());
  481. auto IndexAction = std::make_unique<IndexingFrontendAction>(
  482. DataConsumer, getIndexingOptionsFromCXOptions(index_options),
  483. SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
  484. // Recover resources if we crash before exiting this method.
  485. llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
  486. IndexActionCleanup(IndexAction.get());
  487. bool Persistent = requestedToGetTU;
  488. bool OnlyLocalDecls = false;
  489. bool PrecompilePreamble = false;
  490. bool CreatePreambleOnFirstParse = false;
  491. bool CacheCodeCompletionResults = false;
  492. PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
  493. PPOpts.AllowPCHWithCompilerErrors = true;
  494. if (requestedToGetTU) {
  495. OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
  496. PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
  497. CreatePreambleOnFirstParse =
  498. TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
  499. // FIXME: Add a flag for modules.
  500. CacheCodeCompletionResults
  501. = TU_options & CXTranslationUnit_CacheCompletionResults;
  502. }
  503. if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
  504. PPOpts.DetailedRecord = true;
  505. }
  506. if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
  507. PPOpts.DetailedRecord = false;
  508. // Unless the user specified that they want the preamble on the first parse
  509. // set it up to be created on the first reparse. This makes the first parse
  510. // faster, trading for a slower (first) reparse.
  511. unsigned PrecompilePreambleAfterNParses =
  512. !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
  513. DiagnosticErrorTrap DiagTrap(*Diags);
  514. bool Success = ASTUnit::LoadFromCompilerInvocationAction(
  515. std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags,
  516. IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(),
  517. OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
  518. CacheCodeCompletionResults, /*UserFilesAreVolatile=*/true);
  519. if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
  520. printDiagsToStderr(UPtr);
  521. if (isASTReadError(UPtr))
  522. return CXError_ASTReadError;
  523. if (!Success)
  524. return CXError_Failure;
  525. if (out_TU)
  526. *out_TU = CXTU->takeTU();
  527. return CXError_Success;
  528. }
  529. //===----------------------------------------------------------------------===//
  530. // clang_indexTranslationUnit Implementation
  531. //===----------------------------------------------------------------------===//
  532. static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
  533. Preprocessor &PP = Unit.getPreprocessor();
  534. if (!PP.getPreprocessingRecord())
  535. return;
  536. // FIXME: Only deserialize inclusion directives.
  537. bool isModuleFile = Unit.isModuleFile();
  538. for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) {
  539. if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
  540. SourceLocation Loc = ID->getSourceRange().getBegin();
  541. // Modules have synthetic main files as input, give an invalid location
  542. // if the location points to such a file.
  543. if (isModuleFile && Unit.isInMainFileID(Loc))
  544. Loc = SourceLocation();
  545. IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
  546. ID->getFile(),
  547. ID->getKind() == InclusionDirective::Import,
  548. !ID->wasInQuotes(), ID->importedModule());
  549. }
  550. }
  551. }
  552. static CXErrorCode clang_indexTranslationUnit_Impl(
  553. CXIndexAction idxAction, CXClientData client_data,
  554. IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
  555. unsigned index_options, CXTranslationUnit TU) {
  556. // Check arguments.
  557. if (isNotUsableTU(TU)) {
  558. LOG_BAD_TU(TU);
  559. return CXError_InvalidArguments;
  560. }
  561. if (!client_index_callbacks || index_callbacks_size == 0) {
  562. return CXError_InvalidArguments;
  563. }
  564. CIndexer *CXXIdx = TU->CIdx;
  565. if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
  566. setThreadBackgroundPriority();
  567. IndexerCallbacks CB;
  568. memset(&CB, 0, sizeof(CB));
  569. unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
  570. ? index_callbacks_size : sizeof(CB);
  571. memcpy(&CB, client_index_callbacks, ClientCBSize);
  572. CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU);
  573. ASTUnit *Unit = cxtu::getASTUnit(TU);
  574. if (!Unit)
  575. return CXError_Failure;
  576. ASTUnit::ConcurrencyCheck Check(*Unit);
  577. if (const FileEntry *PCHFile = Unit->getPCHFile())
  578. DataConsumer.importedPCH(PCHFile);
  579. FileManager &FileMgr = Unit->getFileManager();
  580. if (Unit->getOriginalSourceFileName().empty())
  581. DataConsumer.enteredMainFile(nullptr);
  582. else if (auto MainFile = FileMgr.getFile(Unit->getOriginalSourceFileName()))
  583. DataConsumer.enteredMainFile(*MainFile);
  584. else
  585. DataConsumer.enteredMainFile(nullptr);
  586. DataConsumer.setASTContext(Unit->getASTContext());
  587. DataConsumer.startedTranslationUnit();
  588. indexPreprocessingRecord(*Unit, DataConsumer);
  589. indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
  590. DataConsumer.indexDiagnostics();
  591. return CXError_Success;
  592. }
  593. //===----------------------------------------------------------------------===//
  594. // libclang public APIs.
  595. //===----------------------------------------------------------------------===//
  596. int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
  597. return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
  598. }
  599. const CXIdxObjCContainerDeclInfo *
  600. clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
  601. if (!DInfo)
  602. return nullptr;
  603. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  604. if (const ObjCContainerDeclInfo *
  605. ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
  606. return &ContInfo->ObjCContDeclInfo;
  607. return nullptr;
  608. }
  609. const CXIdxObjCInterfaceDeclInfo *
  610. clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
  611. if (!DInfo)
  612. return nullptr;
  613. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  614. if (const ObjCInterfaceDeclInfo *
  615. InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
  616. return &InterInfo->ObjCInterDeclInfo;
  617. return nullptr;
  618. }
  619. const CXIdxObjCCategoryDeclInfo *
  620. clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
  621. if (!DInfo)
  622. return nullptr;
  623. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  624. if (const ObjCCategoryDeclInfo *
  625. CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
  626. return &CatInfo->ObjCCatDeclInfo;
  627. return nullptr;
  628. }
  629. const CXIdxObjCProtocolRefListInfo *
  630. clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
  631. if (!DInfo)
  632. return nullptr;
  633. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  634. if (const ObjCInterfaceDeclInfo *
  635. InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
  636. return InterInfo->ObjCInterDeclInfo.protocols;
  637. if (const ObjCProtocolDeclInfo *
  638. ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
  639. return &ProtInfo->ObjCProtoRefListInfo;
  640. if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
  641. return CatInfo->ObjCCatDeclInfo.protocols;
  642. return nullptr;
  643. }
  644. const CXIdxObjCPropertyDeclInfo *
  645. clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
  646. if (!DInfo)
  647. return nullptr;
  648. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  649. if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
  650. return &PropInfo->ObjCPropDeclInfo;
  651. return nullptr;
  652. }
  653. const CXIdxIBOutletCollectionAttrInfo *
  654. clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
  655. if (!AInfo)
  656. return nullptr;
  657. const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
  658. if (const IBOutletCollectionInfo *
  659. IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
  660. return &IBInfo->IBCollInfo;
  661. return nullptr;
  662. }
  663. const CXIdxCXXClassDeclInfo *
  664. clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
  665. if (!DInfo)
  666. return nullptr;
  667. const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
  668. if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
  669. return &ClassInfo->CXXClassInfo;
  670. return nullptr;
  671. }
  672. CXIdxClientContainer
  673. clang_index_getClientContainer(const CXIdxContainerInfo *info) {
  674. if (!info)
  675. return nullptr;
  676. const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
  677. return Container->IndexCtx->getClientContainerForDC(Container->DC);
  678. }
  679. void clang_index_setClientContainer(const CXIdxContainerInfo *info,
  680. CXIdxClientContainer client) {
  681. if (!info)
  682. return;
  683. const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
  684. Container->IndexCtx->addContainerInMap(Container->DC, client);
  685. }
  686. CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
  687. if (!info)
  688. return nullptr;
  689. const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
  690. return Entity->IndexCtx->getClientEntity(Entity->Dcl);
  691. }
  692. void clang_index_setClientEntity(const CXIdxEntityInfo *info,
  693. CXIdxClientEntity client) {
  694. if (!info)
  695. return;
  696. const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
  697. Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
  698. }
  699. CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
  700. return new IndexSessionData(CIdx);
  701. }
  702. void clang_IndexAction_dispose(CXIndexAction idxAction) {
  703. if (idxAction)
  704. delete static_cast<IndexSessionData *>(idxAction);
  705. }
  706. int clang_indexSourceFile(CXIndexAction idxAction,
  707. CXClientData client_data,
  708. IndexerCallbacks *index_callbacks,
  709. unsigned index_callbacks_size,
  710. unsigned index_options,
  711. const char *source_filename,
  712. const char * const *command_line_args,
  713. int num_command_line_args,
  714. struct CXUnsavedFile *unsaved_files,
  715. unsigned num_unsaved_files,
  716. CXTranslationUnit *out_TU,
  717. unsigned TU_options) {
  718. SmallVector<const char *, 4> Args;
  719. Args.push_back("clang");
  720. Args.append(command_line_args, command_line_args + num_command_line_args);
  721. return clang_indexSourceFileFullArgv(
  722. idxAction, client_data, index_callbacks, index_callbacks_size,
  723. index_options, source_filename, Args.data(), Args.size(), unsaved_files,
  724. num_unsaved_files, out_TU, TU_options);
  725. }
  726. int clang_indexSourceFileFullArgv(
  727. CXIndexAction idxAction, CXClientData client_data,
  728. IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
  729. unsigned index_options, const char *source_filename,
  730. const char *const *command_line_args, int num_command_line_args,
  731. struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
  732. CXTranslationUnit *out_TU, unsigned TU_options) {
  733. LOG_FUNC_SECTION {
  734. *Log << source_filename << ": ";
  735. for (int i = 0; i != num_command_line_args; ++i)
  736. *Log << command_line_args[i] << " ";
  737. }
  738. if (num_unsaved_files && !unsaved_files)
  739. return CXError_InvalidArguments;
  740. CXErrorCode result = CXError_Failure;
  741. auto IndexSourceFileImpl = [=, &result]() {
  742. result = clang_indexSourceFile_Impl(
  743. idxAction, client_data, index_callbacks, index_callbacks_size,
  744. index_options, source_filename, command_line_args,
  745. num_command_line_args, llvm::ArrayRef(unsaved_files, num_unsaved_files),
  746. out_TU, TU_options);
  747. };
  748. llvm::CrashRecoveryContext CRC;
  749. if (!RunSafely(CRC, IndexSourceFileImpl)) {
  750. fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
  751. fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
  752. fprintf(stderr, " 'command_line_args' : [");
  753. for (int i = 0; i != num_command_line_args; ++i) {
  754. if (i)
  755. fprintf(stderr, ", ");
  756. fprintf(stderr, "'%s'", command_line_args[i]);
  757. }
  758. fprintf(stderr, "],\n");
  759. fprintf(stderr, " 'unsaved_files' : [");
  760. for (unsigned i = 0; i != num_unsaved_files; ++i) {
  761. if (i)
  762. fprintf(stderr, ", ");
  763. fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
  764. unsaved_files[i].Length);
  765. }
  766. fprintf(stderr, "],\n");
  767. fprintf(stderr, " 'options' : %d,\n", TU_options);
  768. fprintf(stderr, "}\n");
  769. return 1;
  770. } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
  771. if (out_TU)
  772. PrintLibclangResourceUsage(*out_TU);
  773. }
  774. return result;
  775. }
  776. int clang_indexTranslationUnit(CXIndexAction idxAction,
  777. CXClientData client_data,
  778. IndexerCallbacks *index_callbacks,
  779. unsigned index_callbacks_size,
  780. unsigned index_options,
  781. CXTranslationUnit TU) {
  782. LOG_FUNC_SECTION {
  783. *Log << TU;
  784. }
  785. CXErrorCode result;
  786. auto IndexTranslationUnitImpl = [=, &result]() {
  787. result = clang_indexTranslationUnit_Impl(
  788. idxAction, client_data, index_callbacks, index_callbacks_size,
  789. index_options, TU);
  790. };
  791. llvm::CrashRecoveryContext CRC;
  792. if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
  793. fprintf(stderr, "libclang: crash detected during indexing TU\n");
  794. return 1;
  795. }
  796. return result;
  797. }
  798. void clang_indexLoc_getFileLocation(CXIdxLoc location,
  799. CXIdxClientFile *indexFile,
  800. CXFile *file,
  801. unsigned *line,
  802. unsigned *column,
  803. unsigned *offset) {
  804. if (indexFile) *indexFile = nullptr;
  805. if (file) *file = nullptr;
  806. if (line) *line = 0;
  807. if (column) *column = 0;
  808. if (offset) *offset = 0;
  809. SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
  810. if (!location.ptr_data[0] || Loc.isInvalid())
  811. return;
  812. CXIndexDataConsumer &DataConsumer =
  813. *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
  814. DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
  815. }
  816. CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
  817. SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
  818. if (!location.ptr_data[0] || Loc.isInvalid())
  819. return clang_getNullLocation();
  820. CXIndexDataConsumer &DataConsumer =
  821. *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
  822. return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
  823. }