IndexingContext.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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/Basic/SourceLocation.h"
  10. #include "clang/Index/IndexDataConsumer.h"
  11. #include "clang/AST/ASTContext.h"
  12. #include "clang/AST/DeclTemplate.h"
  13. #include "clang/AST/DeclObjC.h"
  14. #include "clang/Basic/SourceManager.h"
  15. using namespace clang;
  16. using namespace index;
  17. static bool isGeneratedDecl(const Decl *D) {
  18. if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
  19. return attr->getGeneratedDeclaration();
  20. }
  21. return false;
  22. }
  23. bool IndexingContext::shouldIndex(const Decl *D) {
  24. return !isGeneratedDecl(D);
  25. }
  26. const LangOptions &IndexingContext::getLangOpts() const {
  27. return Ctx->getLangOpts();
  28. }
  29. bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
  30. return IndexOpts.IndexFunctionLocals;
  31. }
  32. bool IndexingContext::shouldIndexImplicitInstantiation() const {
  33. return IndexOpts.IndexImplicitInstantiation;
  34. }
  35. bool IndexingContext::shouldIndexParametersInDeclarations() const {
  36. return IndexOpts.IndexParametersInDeclarations;
  37. }
  38. bool IndexingContext::shouldIndexTemplateParameters() const {
  39. return IndexOpts.IndexTemplateParameters;
  40. }
  41. bool IndexingContext::handleDecl(const Decl *D,
  42. SymbolRoleSet Roles,
  43. ArrayRef<SymbolRelation> Relations) {
  44. return handleDecl(D, D->getLocation(), Roles, Relations);
  45. }
  46. bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
  47. SymbolRoleSet Roles,
  48. ArrayRef<SymbolRelation> Relations,
  49. const DeclContext *DC) {
  50. if (!DC)
  51. DC = D->getDeclContext();
  52. const Decl *OrigD = D;
  53. if (isa<ObjCPropertyImplDecl>(D)) {
  54. D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
  55. }
  56. return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
  57. Roles, Relations,
  58. nullptr, OrigD, DC);
  59. }
  60. bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
  61. const NamedDecl *Parent,
  62. const DeclContext *DC,
  63. SymbolRoleSet Roles,
  64. ArrayRef<SymbolRelation> Relations,
  65. const Expr *RefE,
  66. const Decl *RefD) {
  67. if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
  68. return true;
  69. if (!shouldIndexTemplateParameters() &&
  70. (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
  71. isa<TemplateTemplateParmDecl>(D))) {
  72. return true;
  73. }
  74. return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
  75. RefE, RefD, DC);
  76. }
  77. static void reportModuleReferences(const Module *Mod,
  78. ArrayRef<SourceLocation> IdLocs,
  79. const ImportDecl *ImportD,
  80. IndexDataConsumer &DataConsumer) {
  81. if (!Mod)
  82. return;
  83. reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
  84. DataConsumer);
  85. DataConsumer.handleModuleOccurence(ImportD, Mod,
  86. (SymbolRoleSet)SymbolRole::Reference,
  87. 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.handleModuleOccurence(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. case TSK_ExplicitSpecialization:
  148. return false;
  149. case TSK_ImplicitInstantiation:
  150. case TSK_ExplicitInstantiationDeclaration:
  151. case TSK_ExplicitInstantiationDefinition:
  152. return true;
  153. }
  154. llvm_unreachable("invalid TemplateSpecializationKind");
  155. }
  156. bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
  157. if (isa<ObjCInterfaceDecl>(D))
  158. return false;
  159. if (isa<ObjCCategoryDecl>(D))
  160. return false;
  161. if (isa<ObjCIvarDecl>(D))
  162. return false;
  163. if (isa<ObjCMethodDecl>(D))
  164. return false;
  165. if (isa<ImportDecl>(D))
  166. return false;
  167. return true;
  168. }
  169. static const CXXRecordDecl *
  170. getDeclContextForTemplateInstationPattern(const Decl *D) {
  171. if (const auto *CTSD =
  172. dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
  173. return CTSD->getTemplateInstantiationPattern();
  174. else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
  175. return RD->getInstantiatedFromMemberClass();
  176. return nullptr;
  177. }
  178. static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
  179. if (const ClassTemplateSpecializationDecl *
  180. SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
  181. return SD->getTemplateInstantiationPattern();
  182. } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  183. return FD->getTemplateInstantiationPattern();
  184. } else if (auto *VD = dyn_cast<VarDecl>(D)) {
  185. return VD->getTemplateInstantiationPattern();
  186. } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
  187. return RD->getInstantiatedFromMemberClass();
  188. } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
  189. return ED->getInstantiatedFromMemberEnum();
  190. } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
  191. const auto *ND = cast<NamedDecl>(D);
  192. if (const CXXRecordDecl *Pattern =
  193. getDeclContextForTemplateInstationPattern(ND)) {
  194. for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
  195. if (BaseND->isImplicit())
  196. continue;
  197. if (BaseND->getKind() == ND->getKind())
  198. return BaseND;
  199. }
  200. }
  201. } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
  202. if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
  203. if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
  204. for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
  205. return BaseECD;
  206. }
  207. }
  208. }
  209. return nullptr;
  210. }
  211. static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
  212. if (auto VD = dyn_cast<VarDecl>(D))
  213. return VD->isThisDeclarationADefinition(Ctx);
  214. if (auto FD = dyn_cast<FunctionDecl>(D))
  215. return FD->isThisDeclarationADefinition();
  216. if (auto TD = dyn_cast<TagDecl>(D))
  217. return TD->isThisDeclarationADefinition();
  218. if (auto MD = dyn_cast<ObjCMethodDecl>(D))
  219. return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
  220. if (isa<TypedefNameDecl>(D) ||
  221. isa<EnumConstantDecl>(D) ||
  222. isa<FieldDecl>(D) ||
  223. isa<MSPropertyDecl>(D) ||
  224. isa<ObjCImplDecl>(D) ||
  225. isa<ObjCPropertyImplDecl>(D))
  226. return true;
  227. return false;
  228. }
  229. /// Whether the given NamedDecl should be skipped because it has no name.
  230. static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
  231. return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
  232. !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
  233. }
  234. static const Decl *adjustParent(const Decl *Parent) {
  235. if (!Parent)
  236. return nullptr;
  237. for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
  238. if (isa<TranslationUnitDecl>(Parent))
  239. return nullptr;
  240. if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
  241. continue;
  242. if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
  243. if (NS->isAnonymousNamespace())
  244. continue;
  245. } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
  246. if (RD->isAnonymousStructOrUnion())
  247. continue;
  248. } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
  249. if (shouldSkipNamelessDecl(ND))
  250. continue;
  251. }
  252. return Parent;
  253. }
  254. }
  255. static const Decl *getCanonicalDecl(const Decl *D) {
  256. D = D->getCanonicalDecl();
  257. if (auto TD = dyn_cast<TemplateDecl>(D)) {
  258. if (auto TTD = TD->getTemplatedDecl()) {
  259. D = TTD;
  260. assert(D->isCanonicalDecl());
  261. }
  262. }
  263. return D;
  264. }
  265. static bool shouldReportOccurrenceForSystemDeclOnlyMode(
  266. bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
  267. if (!IsRef)
  268. return true;
  269. auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
  270. bool accept = false;
  271. applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
  272. switch (r) {
  273. case SymbolRole::RelationChildOf:
  274. case SymbolRole::RelationBaseOf:
  275. case SymbolRole::RelationOverrideOf:
  276. case SymbolRole::RelationExtendedBy:
  277. case SymbolRole::RelationAccessorOf:
  278. case SymbolRole::RelationIBTypeOf:
  279. accept = true;
  280. return false;
  281. case SymbolRole::Declaration:
  282. case SymbolRole::Definition:
  283. case SymbolRole::Reference:
  284. case SymbolRole::Read:
  285. case SymbolRole::Write:
  286. case SymbolRole::Call:
  287. case SymbolRole::Dynamic:
  288. case SymbolRole::AddressOf:
  289. case SymbolRole::Implicit:
  290. case SymbolRole::Undefinition:
  291. case SymbolRole::RelationReceivedBy:
  292. case SymbolRole::RelationCalledBy:
  293. case SymbolRole::RelationContainedBy:
  294. case SymbolRole::RelationSpecializationOf:
  295. case SymbolRole::NameReference:
  296. return true;
  297. }
  298. llvm_unreachable("Unsupported SymbolRole value!");
  299. });
  300. return accept;
  301. };
  302. for (auto &Rel : Relations) {
  303. if (acceptForRelation(Rel.Roles))
  304. return true;
  305. }
  306. return false;
  307. }
  308. bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
  309. bool IsRef, const Decl *Parent,
  310. SymbolRoleSet Roles,
  311. ArrayRef<SymbolRelation> Relations,
  312. const Expr *OrigE,
  313. const Decl *OrigD,
  314. const DeclContext *ContainerDC) {
  315. if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
  316. return true;
  317. if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
  318. return true;
  319. SourceManager &SM = Ctx->getSourceManager();
  320. FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  321. if (FID.isInvalid())
  322. return true;
  323. bool Invalid = false;
  324. const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  325. if (Invalid || !SEntry.isFile())
  326. return true;
  327. if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
  328. switch (IndexOpts.SystemSymbolFilter) {
  329. case IndexingOptions::SystemSymbolFilterKind::None:
  330. return true;
  331. case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
  332. if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
  333. return true;
  334. break;
  335. case IndexingOptions::SystemSymbolFilterKind::All:
  336. break;
  337. }
  338. }
  339. if (!OrigD)
  340. OrigD = D;
  341. if (isTemplateImplicitInstantiation(D)) {
  342. if (!IsRef)
  343. return true;
  344. D = adjustTemplateImplicitInstantiation(D);
  345. if (!D)
  346. return true;
  347. assert(!isTemplateImplicitInstantiation(D));
  348. }
  349. if (IsRef)
  350. Roles |= (unsigned)SymbolRole::Reference;
  351. else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
  352. Roles |= (unsigned)SymbolRole::Definition;
  353. else
  354. Roles |= (unsigned)SymbolRole::Declaration;
  355. D = getCanonicalDecl(D);
  356. Parent = adjustParent(Parent);
  357. if (Parent)
  358. Parent = getCanonicalDecl(Parent);
  359. SmallVector<SymbolRelation, 6> FinalRelations;
  360. FinalRelations.reserve(Relations.size()+1);
  361. auto addRelation = [&](SymbolRelation Rel) {
  362. auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
  363. return Elem.RelatedSymbol == Rel.RelatedSymbol;
  364. });
  365. if (It != FinalRelations.end()) {
  366. It->Roles |= Rel.Roles;
  367. } else {
  368. FinalRelations.push_back(Rel);
  369. }
  370. Roles |= Rel.Roles;
  371. };
  372. if (Parent) {
  373. if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
  374. addRelation(SymbolRelation{
  375. (unsigned)SymbolRole::RelationContainedBy,
  376. Parent
  377. });
  378. } else {
  379. addRelation(SymbolRelation{
  380. (unsigned)SymbolRole::RelationChildOf,
  381. Parent
  382. });
  383. }
  384. }
  385. for (auto &Rel : Relations) {
  386. addRelation(SymbolRelation(Rel.Roles,
  387. Rel.RelatedSymbol->getCanonicalDecl()));
  388. }
  389. IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
  390. return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node);
  391. }
  392. void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
  393. SourceLocation Loc,
  394. const MacroInfo &MI) {
  395. SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
  396. DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
  397. }
  398. void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
  399. SourceLocation Loc,
  400. const MacroInfo &MI) {
  401. SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
  402. DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
  403. }
  404. void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
  405. SourceLocation Loc,
  406. const MacroInfo &MI) {
  407. SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
  408. DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
  409. }