IndexingContext.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. //===- IndexingContext.cpp - Indexing context data ------------------------===//
  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 "IndexingContext.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/AST/Attr.h"
  11. #include "clang/AST/DeclObjC.h"
  12. #include "clang/AST/DeclTemplate.h"
  13. #include "clang/Basic/SourceLocation.h"
  14. #include "clang/Basic/SourceManager.h"
  15. #include "clang/Index/IndexDataConsumer.h"
  16. using namespace clang;
  17. using namespace index;
  18. static bool isGeneratedDecl(const Decl *D) {
  19. if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
  20. return attr->getGeneratedDeclaration();
  21. }
  22. return false;
  23. }
  24. bool IndexingContext::shouldIndex(const Decl *D) {
  25. return !isGeneratedDecl(D);
  26. }
  27. const LangOptions &IndexingContext::getLangOpts() const {
  28. return Ctx->getLangOpts();
  29. }
  30. bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
  31. return IndexOpts.IndexFunctionLocals;
  32. }
  33. bool IndexingContext::shouldIndexImplicitInstantiation() const {
  34. return IndexOpts.IndexImplicitInstantiation;
  35. }
  36. bool IndexingContext::shouldIndexParametersInDeclarations() const {
  37. return IndexOpts.IndexParametersInDeclarations;
  38. }
  39. bool IndexingContext::shouldIndexTemplateParameters() const {
  40. return IndexOpts.IndexTemplateParameters;
  41. }
  42. bool IndexingContext::handleDecl(const Decl *D,
  43. SymbolRoleSet Roles,
  44. ArrayRef<SymbolRelation> Relations) {
  45. return handleDecl(D, D->getLocation(), Roles, Relations);
  46. }
  47. bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
  48. SymbolRoleSet Roles,
  49. ArrayRef<SymbolRelation> Relations,
  50. const DeclContext *DC) {
  51. if (!DC)
  52. DC = D->getDeclContext();
  53. const Decl *OrigD = D;
  54. if (isa<ObjCPropertyImplDecl>(D)) {
  55. D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
  56. }
  57. return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
  58. Roles, Relations,
  59. nullptr, OrigD, DC);
  60. }
  61. bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
  62. const NamedDecl *Parent,
  63. const DeclContext *DC,
  64. SymbolRoleSet Roles,
  65. ArrayRef<SymbolRelation> Relations,
  66. const Expr *RefE,
  67. const Decl *RefD) {
  68. if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
  69. return true;
  70. if (!shouldIndexTemplateParameters() &&
  71. (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
  72. isa<TemplateTemplateParmDecl>(D))) {
  73. return true;
  74. }
  75. return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
  76. RefE, RefD, DC);
  77. }
  78. static void reportModuleReferences(const Module *Mod,
  79. ArrayRef<SourceLocation> IdLocs,
  80. const ImportDecl *ImportD,
  81. IndexDataConsumer &DataConsumer) {
  82. if (!Mod)
  83. return;
  84. reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
  85. DataConsumer);
  86. DataConsumer.handleModuleOccurrence(
  87. ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
  88. }
  89. bool IndexingContext::importedModule(const ImportDecl *ImportD) {
  90. if (ImportD->isInvalidDecl())
  91. return true;
  92. SourceLocation Loc;
  93. auto IdLocs = ImportD->getIdentifierLocs();
  94. if (!IdLocs.empty())
  95. Loc = IdLocs.back();
  96. else
  97. Loc = ImportD->getLocation();
  98. SourceManager &SM = Ctx->getSourceManager();
  99. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  100. if (FID.isInvalid())
  101. return true;
  102. bool Invalid = false;
  103. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  104. if (Invalid || !SEntry.isFile())
  105. return true;
  106. if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
  107. switch (IndexOpts.SystemSymbolFilter) {
  108. case IndexingOptions::SystemSymbolFilterKind::None:
  109. return true;
  110. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  111. case IndexingOptions::SystemSymbolFilterKind::All:
  112. break;
  113. }
  114. }
  115. const Module *Mod = ImportD->getImportedModule();
  116. if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
  117. reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
  118. DataConsumer);
  119. }
  120. SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
  121. if (ImportD->isImplicit())
  122. Roles |= (unsigned)SymbolRole::Implicit;
  123. return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
  124. }
  125. bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
  126. TemplateSpecializationKind TKind = TSK_Undeclared;
  127. if (const ClassTemplateSpecializationDecl *
  128. SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
  129. TKind = SD->getSpecializationKind();
  130. } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  131. TKind = FD->getTemplateSpecializationKind();
  132. } else if (auto *VD = dyn_cast<VarDecl>(D)) {
  133. TKind = VD->getTemplateSpecializationKind();
  134. } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
  135. if (RD->getInstantiatedFromMemberClass())
  136. TKind = RD->getTemplateSpecializationKind();
  137. } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
  138. if (ED->getInstantiatedFromMemberEnum())
  139. TKind = ED->getTemplateSpecializationKind();
  140. } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
  141. isa<EnumConstantDecl>(D)) {
  142. if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
  143. return isTemplateImplicitInstantiation(Parent);
  144. }
  145. switch (TKind) {
  146. case TSK_Undeclared:
  147. // Instantiation maybe not happen yet when we see a SpecializationDecl,
  148. // e.g. when the type doesn't need to be complete, we still treat it as an
  149. // instantiation as we'd like to keep the canonicalized result consistent.
  150. return isa<ClassTemplateSpecializationDecl>(D);
  151. case TSK_ExplicitSpecialization:
  152. return false;
  153. case TSK_ImplicitInstantiation:
  154. case TSK_ExplicitInstantiationDeclaration:
  155. case TSK_ExplicitInstantiationDefinition:
  156. return true;
  157. }
  158. llvm_unreachable("invalid TemplateSpecializationKind");
  159. }
  160. bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
  161. if (isa<ObjCInterfaceDecl>(D))
  162. return false;
  163. if (isa<ObjCCategoryDecl>(D))
  164. return false;
  165. if (isa<ObjCIvarDecl>(D))
  166. return false;
  167. if (isa<ObjCMethodDecl>(D))
  168. return false;
  169. if (isa<ImportDecl>(D))
  170. return false;
  171. return true;
  172. }
  173. static const CXXRecordDecl *
  174. getDeclContextForTemplateInstationPattern(const Decl *D) {
  175. if (const auto *CTSD =
  176. dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
  177. return CTSD->getTemplateInstantiationPattern();
  178. else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
  179. return RD->getInstantiatedFromMemberClass();
  180. return nullptr;
  181. }
  182. static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
  183. if (const ClassTemplateSpecializationDecl *
  184. SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
  185. const auto *Template = SD->getTemplateInstantiationPattern();
  186. if (Template)
  187. return Template;
  188. // Fallback to primary template if no instantiation is available yet (e.g.
  189. // the type doesn't need to be complete).
  190. return SD->getSpecializedTemplate()->getTemplatedDecl();
  191. } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  192. return FD->getTemplateInstantiationPattern();
  193. } else if (auto *VD = dyn_cast<VarDecl>(D)) {
  194. return VD->getTemplateInstantiationPattern();
  195. } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
  196. return RD->getInstantiatedFromMemberClass();
  197. } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
  198. return ED->getInstantiatedFromMemberEnum();
  199. } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
  200. const auto *ND = cast<NamedDecl>(D);
  201. if (const CXXRecordDecl *Pattern =
  202. getDeclContextForTemplateInstationPattern(ND)) {
  203. for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
  204. if (BaseND->isImplicit())
  205. continue;
  206. if (BaseND->getKind() == ND->getKind())
  207. return BaseND;
  208. }
  209. }
  210. } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
  211. if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
  212. if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
  213. for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
  214. return BaseECD;
  215. }
  216. }
  217. }
  218. return nullptr;
  219. }
  220. static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
  221. if (auto VD = dyn_cast<VarDecl>(D))
  222. return VD->isThisDeclarationADefinition(Ctx);
  223. if (auto FD = dyn_cast<FunctionDecl>(D))
  224. return FD->isThisDeclarationADefinition();
  225. if (auto TD = dyn_cast<TagDecl>(D))
  226. return TD->isThisDeclarationADefinition();
  227. if (auto MD = dyn_cast<ObjCMethodDecl>(D))
  228. return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
  229. if (isa<TypedefNameDecl>(D) || isa<EnumConstantDecl>(D) ||
  230. isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || isa<ObjCImplDecl>(D) ||
  231. isa<ObjCPropertyImplDecl>(D) || isa<ConceptDecl>(D))
  232. return true;
  233. return false;
  234. }
  235. /// Whether the given NamedDecl should be skipped because it has no name.
  236. static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
  237. return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
  238. !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
  239. }
  240. static const Decl *adjustParent(const Decl *Parent) {
  241. if (!Parent)
  242. return nullptr;
  243. for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
  244. if (isa<TranslationUnitDecl>(Parent))
  245. return nullptr;
  246. if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
  247. continue;
  248. if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
  249. if (NS->isAnonymousNamespace())
  250. continue;
  251. } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
  252. if (RD->isAnonymousStructOrUnion())
  253. continue;
  254. } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
  255. if (shouldSkipNamelessDecl(ND))
  256. continue;
  257. }
  258. return Parent;
  259. }
  260. }
  261. static const Decl *getCanonicalDecl(const Decl *D) {
  262. D = D->getCanonicalDecl();
  263. if (auto TD = dyn_cast<TemplateDecl>(D)) {
  264. if (auto TTD = TD->getTemplatedDecl()) {
  265. D = TTD;
  266. assert(D->isCanonicalDecl());
  267. }
  268. }
  269. return D;
  270. }
  271. static bool shouldReportOccurrenceForSystemDeclOnlyMode(
  272. bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
  273. if (!IsRef)
  274. return true;
  275. auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
  276. bool accept = false;
  277. applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
  278. switch (r) {
  279. case SymbolRole::RelationChildOf:
  280. case SymbolRole::RelationBaseOf:
  281. case SymbolRole::RelationOverrideOf:
  282. case SymbolRole::RelationExtendedBy:
  283. case SymbolRole::RelationAccessorOf:
  284. case SymbolRole::RelationIBTypeOf:
  285. accept = true;
  286. return false;
  287. case SymbolRole::Declaration:
  288. case SymbolRole::Definition:
  289. case SymbolRole::Reference:
  290. case SymbolRole::Read:
  291. case SymbolRole::Write:
  292. case SymbolRole::Call:
  293. case SymbolRole::Dynamic:
  294. case SymbolRole::AddressOf:
  295. case SymbolRole::Implicit:
  296. case SymbolRole::Undefinition:
  297. case SymbolRole::RelationReceivedBy:
  298. case SymbolRole::RelationCalledBy:
  299. case SymbolRole::RelationContainedBy:
  300. case SymbolRole::RelationSpecializationOf:
  301. case SymbolRole::NameReference:
  302. return true;
  303. }
  304. llvm_unreachable("Unsupported SymbolRole value!");
  305. });
  306. return accept;
  307. };
  308. for (auto &Rel : Relations) {
  309. if (acceptForRelation(Rel.Roles))
  310. return true;
  311. }
  312. return false;
  313. }
  314. bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
  315. bool IsRef, const Decl *Parent,
  316. SymbolRoleSet Roles,
  317. ArrayRef<SymbolRelation> Relations,
  318. const Expr *OrigE,
  319. const Decl *OrigD,
  320. const DeclContext *ContainerDC) {
  321. if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
  322. return true;
  323. if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
  324. return true;
  325. SourceManager &SM = Ctx->getSourceManager();
  326. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  327. if (FID.isInvalid())
  328. return true;
  329. bool Invalid = false;
  330. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  331. if (Invalid || !SEntry.isFile())
  332. return true;
  333. if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
  334. switch (IndexOpts.SystemSymbolFilter) {
  335. case IndexingOptions::SystemSymbolFilterKind::None:
  336. return true;
  337. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  338. if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
  339. return true;
  340. break;
  341. case IndexingOptions::SystemSymbolFilterKind::All:
  342. break;
  343. }
  344. }
  345. if (!OrigD)
  346. OrigD = D;
  347. if (isTemplateImplicitInstantiation(D)) {
  348. if (!IsRef)
  349. return true;
  350. D = adjustTemplateImplicitInstantiation(D);
  351. if (!D)
  352. return true;
  353. assert(!isTemplateImplicitInstantiation(D));
  354. }
  355. if (IsRef)
  356. Roles |= (unsigned)SymbolRole::Reference;
  357. else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
  358. Roles |= (unsigned)SymbolRole::Definition;
  359. else
  360. Roles |= (unsigned)SymbolRole::Declaration;
  361. D = getCanonicalDecl(D);
  362. Parent = adjustParent(Parent);
  363. if (Parent)
  364. Parent = getCanonicalDecl(Parent);
  365. SmallVector<SymbolRelation, 6> FinalRelations;
  366. FinalRelations.reserve(Relations.size()+1);
  367. auto addRelation = [&](SymbolRelation Rel) {
  368. auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
  369. return Elem.RelatedSymbol == Rel.RelatedSymbol;
  370. });
  371. if (It != FinalRelations.end()) {
  372. It->Roles |= Rel.Roles;
  373. } else {
  374. FinalRelations.push_back(Rel);
  375. }
  376. Roles |= Rel.Roles;
  377. };
  378. if (Parent) {
  379. if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
  380. addRelation(SymbolRelation{
  381. (unsigned)SymbolRole::RelationContainedBy,
  382. Parent
  383. });
  384. } else {
  385. addRelation(SymbolRelation{
  386. (unsigned)SymbolRole::RelationChildOf,
  387. Parent
  388. });
  389. }
  390. }
  391. for (auto &Rel : Relations) {
  392. addRelation(SymbolRelation(Rel.Roles,
  393. Rel.RelatedSymbol->getCanonicalDecl()));
  394. }
  395. IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
  396. return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
  397. }
  398. void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
  399. SourceLocation Loc,
  400. const MacroInfo &MI) {
  401. if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
  402. return;
  403. SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
  404. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  405. }
  406. void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
  407. SourceLocation Loc,
  408. const MacroInfo &MI) {
  409. if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
  410. return;
  411. SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
  412. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  413. }
  414. void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
  415. SourceLocation Loc,
  416. const MacroInfo &MI) {
  417. if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
  418. return;
  419. SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
  420. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  421. }
  422. bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
  423. SourceLocation Loc) {
  424. if (!IndexOpts.IndexMacros)
  425. return false;
  426. switch (IndexOpts.SystemSymbolFilter) {
  427. case IndexingOptions::SystemSymbolFilterKind::None:
  428. break;
  429. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  430. if (!IsRef)
  431. return true;
  432. break;
  433. case IndexingOptions::SystemSymbolFilterKind::All:
  434. return true;
  435. }
  436. SourceManager &SM = Ctx->getSourceManager();
  437. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  438. if (FID.isInvalid())
  439. return false;
  440. bool Invalid = false;
  441. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  442. if (Invalid || !SEntry.isFile())
  443. return false;
  444. return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
  445. }