IndexingContext.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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) ||
  230. isa<EnumConstantDecl>(D) ||
  231. isa<FieldDecl>(D) ||
  232. isa<MSPropertyDecl>(D) ||
  233. isa<ObjCImplDecl>(D) ||
  234. isa<ObjCPropertyImplDecl>(D))
  235. return true;
  236. return false;
  237. }
  238. /// Whether the given NamedDecl should be skipped because it has no name.
  239. static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
  240. return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
  241. !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
  242. }
  243. static const Decl *adjustParent(const Decl *Parent) {
  244. if (!Parent)
  245. return nullptr;
  246. for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
  247. if (isa<TranslationUnitDecl>(Parent))
  248. return nullptr;
  249. if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
  250. continue;
  251. if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
  252. if (NS->isAnonymousNamespace())
  253. continue;
  254. } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
  255. if (RD->isAnonymousStructOrUnion())
  256. continue;
  257. } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
  258. if (shouldSkipNamelessDecl(ND))
  259. continue;
  260. }
  261. return Parent;
  262. }
  263. }
  264. static const Decl *getCanonicalDecl(const Decl *D) {
  265. D = D->getCanonicalDecl();
  266. if (auto TD = dyn_cast<TemplateDecl>(D)) {
  267. if (auto TTD = TD->getTemplatedDecl()) {
  268. D = TTD;
  269. assert(D->isCanonicalDecl());
  270. }
  271. }
  272. return D;
  273. }
  274. static bool shouldReportOccurrenceForSystemDeclOnlyMode(
  275. bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
  276. if (!IsRef)
  277. return true;
  278. auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
  279. bool accept = false;
  280. applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
  281. switch (r) {
  282. case SymbolRole::RelationChildOf:
  283. case SymbolRole::RelationBaseOf:
  284. case SymbolRole::RelationOverrideOf:
  285. case SymbolRole::RelationExtendedBy:
  286. case SymbolRole::RelationAccessorOf:
  287. case SymbolRole::RelationIBTypeOf:
  288. accept = true;
  289. return false;
  290. case SymbolRole::Declaration:
  291. case SymbolRole::Definition:
  292. case SymbolRole::Reference:
  293. case SymbolRole::Read:
  294. case SymbolRole::Write:
  295. case SymbolRole::Call:
  296. case SymbolRole::Dynamic:
  297. case SymbolRole::AddressOf:
  298. case SymbolRole::Implicit:
  299. case SymbolRole::Undefinition:
  300. case SymbolRole::RelationReceivedBy:
  301. case SymbolRole::RelationCalledBy:
  302. case SymbolRole::RelationContainedBy:
  303. case SymbolRole::RelationSpecializationOf:
  304. case SymbolRole::NameReference:
  305. return true;
  306. }
  307. llvm_unreachable("Unsupported SymbolRole value!");
  308. });
  309. return accept;
  310. };
  311. for (auto &Rel : Relations) {
  312. if (acceptForRelation(Rel.Roles))
  313. return true;
  314. }
  315. return false;
  316. }
  317. bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
  318. bool IsRef, const Decl *Parent,
  319. SymbolRoleSet Roles,
  320. ArrayRef<SymbolRelation> Relations,
  321. const Expr *OrigE,
  322. const Decl *OrigD,
  323. const DeclContext *ContainerDC) {
  324. if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
  325. return true;
  326. if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
  327. return true;
  328. SourceManager &SM = Ctx->getSourceManager();
  329. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  330. if (FID.isInvalid())
  331. return true;
  332. bool Invalid = false;
  333. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  334. if (Invalid || !SEntry.isFile())
  335. return true;
  336. if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
  337. switch (IndexOpts.SystemSymbolFilter) {
  338. case IndexingOptions::SystemSymbolFilterKind::None:
  339. return true;
  340. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  341. if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
  342. return true;
  343. break;
  344. case IndexingOptions::SystemSymbolFilterKind::All:
  345. break;
  346. }
  347. }
  348. if (!OrigD)
  349. OrigD = D;
  350. if (isTemplateImplicitInstantiation(D)) {
  351. if (!IsRef)
  352. return true;
  353. D = adjustTemplateImplicitInstantiation(D);
  354. if (!D)
  355. return true;
  356. assert(!isTemplateImplicitInstantiation(D));
  357. }
  358. if (IsRef)
  359. Roles |= (unsigned)SymbolRole::Reference;
  360. else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
  361. Roles |= (unsigned)SymbolRole::Definition;
  362. else
  363. Roles |= (unsigned)SymbolRole::Declaration;
  364. D = getCanonicalDecl(D);
  365. Parent = adjustParent(Parent);
  366. if (Parent)
  367. Parent = getCanonicalDecl(Parent);
  368. SmallVector<SymbolRelation, 6> FinalRelations;
  369. FinalRelations.reserve(Relations.size()+1);
  370. auto addRelation = [&](SymbolRelation Rel) {
  371. auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
  372. return Elem.RelatedSymbol == Rel.RelatedSymbol;
  373. });
  374. if (It != FinalRelations.end()) {
  375. It->Roles |= Rel.Roles;
  376. } else {
  377. FinalRelations.push_back(Rel);
  378. }
  379. Roles |= Rel.Roles;
  380. };
  381. if (Parent) {
  382. if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
  383. addRelation(SymbolRelation{
  384. (unsigned)SymbolRole::RelationContainedBy,
  385. Parent
  386. });
  387. } else {
  388. addRelation(SymbolRelation{
  389. (unsigned)SymbolRole::RelationChildOf,
  390. Parent
  391. });
  392. }
  393. }
  394. for (auto &Rel : Relations) {
  395. addRelation(SymbolRelation(Rel.Roles,
  396. Rel.RelatedSymbol->getCanonicalDecl()));
  397. }
  398. IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
  399. return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
  400. }
  401. void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
  402. SourceLocation Loc,
  403. const MacroInfo &MI) {
  404. if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
  405. return;
  406. SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
  407. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  408. }
  409. void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
  410. SourceLocation Loc,
  411. const MacroInfo &MI) {
  412. if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
  413. return;
  414. SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
  415. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  416. }
  417. void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
  418. SourceLocation Loc,
  419. const MacroInfo &MI) {
  420. if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
  421. return;
  422. SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
  423. DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
  424. }
  425. bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
  426. SourceLocation Loc) {
  427. if (!IndexOpts.IndexMacros)
  428. return false;
  429. switch (IndexOpts.SystemSymbolFilter) {
  430. case IndexingOptions::SystemSymbolFilterKind::None:
  431. break;
  432. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  433. if (!IsRef)
  434. return true;
  435. break;
  436. case IndexingOptions::SystemSymbolFilterKind::All:
  437. return true;
  438. }
  439. SourceManager &SM = Ctx->getSourceManager();
  440. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  441. if (FID.isInvalid())
  442. return false;
  443. bool Invalid = false;
  444. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  445. if (Invalid || !SEntry.isFile())
  446. return false;
  447. return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
  448. }