IndexTypeSourceInfo.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
  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/RecursiveASTVisitor.h"
  10. using namespace clang;
  11. using namespace index;
  12. namespace {
  13. class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
  14. IndexingContext &IndexCtx;
  15. const NamedDecl *Parent;
  16. const DeclContext *ParentDC;
  17. bool IsBase;
  18. SmallVector<SymbolRelation, 3> Relations;
  19. typedef RecursiveASTVisitor<TypeIndexer> base;
  20. public:
  21. TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
  22. const DeclContext *DC, bool isBase, bool isIBType)
  23. : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
  24. if (IsBase) {
  25. assert(Parent);
  26. Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
  27. }
  28. if (isIBType) {
  29. assert(Parent);
  30. Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
  31. }
  32. }
  33. bool shouldWalkTypesOfTypeLocs() const { return false; }
  34. #define TRY_TO(CALL_EXPR) \
  35. do { \
  36. if (!CALL_EXPR) \
  37. return false; \
  38. } while (0)
  39. bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
  40. SourceLocation Loc = TTPL.getNameLoc();
  41. TemplateTypeParmDecl *TTPD = TTPL.getDecl();
  42. return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
  43. SymbolRoleSet());
  44. }
  45. bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
  46. SourceLocation Loc = TL.getNameLoc();
  47. TypedefNameDecl *ND = TL.getTypedefNameDecl();
  48. if (ND->isTransparentTag()) {
  49. TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
  50. return IndexCtx.handleReference(Underlying, Loc, Parent,
  51. ParentDC, SymbolRoleSet(), Relations);
  52. }
  53. if (IsBase) {
  54. TRY_TO(IndexCtx.handleReference(ND, Loc,
  55. Parent, ParentDC, SymbolRoleSet()));
  56. if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
  57. TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
  58. (unsigned)SymbolRole::Implicit,
  59. Relations));
  60. }
  61. } else {
  62. TRY_TO(IndexCtx.handleReference(ND, Loc,
  63. Parent, ParentDC, SymbolRoleSet(),
  64. Relations));
  65. }
  66. return true;
  67. }
  68. bool traverseParamVarHelper(ParmVarDecl *D) {
  69. TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
  70. if (D->getTypeSourceInfo())
  71. TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
  72. return true;
  73. }
  74. bool TraverseParmVarDecl(ParmVarDecl *D) {
  75. // Avoid visiting default arguments from the definition that were already
  76. // visited in the declaration.
  77. // FIXME: A free function definition can have default arguments.
  78. // Avoiding double visitaiton of default arguments should be handled by the
  79. // visitor probably with a bit in the AST to indicate if the attached
  80. // default argument was 'inherited' or written in source.
  81. if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
  82. if (FD->isThisDeclarationADefinition()) {
  83. return traverseParamVarHelper(D);
  84. }
  85. }
  86. return base::TraverseParmVarDecl(D);
  87. }
  88. bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
  89. IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
  90. return true;
  91. }
  92. bool VisitTagTypeLoc(TagTypeLoc TL) {
  93. TagDecl *D = TL.getDecl();
  94. if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
  95. D->getParentFunctionOrMethod())
  96. return true;
  97. if (TL.isDefinition()) {
  98. IndexCtx.indexTagDecl(D);
  99. return true;
  100. }
  101. return IndexCtx.handleReference(D, TL.getNameLoc(),
  102. Parent, ParentDC, SymbolRoleSet(),
  103. Relations);
  104. }
  105. bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
  106. return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
  107. Parent, ParentDC, SymbolRoleSet(), Relations);
  108. }
  109. bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
  110. for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
  111. IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
  112. Parent, ParentDC, SymbolRoleSet(), Relations);
  113. }
  114. return true;
  115. }
  116. template<typename TypeLocType>
  117. bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
  118. if (const auto *T = TL.getTypePtr()) {
  119. if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
  120. if (!RD->isImplicit() || IndexCtx.shouldIndexImplicitInstantiation()) {
  121. IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), Parent,
  122. ParentDC, SymbolRoleSet(), Relations);
  123. return true;
  124. }
  125. }
  126. if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
  127. IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC,
  128. SymbolRoleSet(), Relations);
  129. }
  130. return true;
  131. }
  132. bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
  133. return HandleTemplateSpecializationTypeLoc(TL);
  134. }
  135. bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
  136. return HandleTemplateSpecializationTypeLoc(TL);
  137. }
  138. bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
  139. const DependentNameType *DNT = TL.getTypePtr();
  140. const NestedNameSpecifier *NNS = DNT->getQualifier();
  141. const Type *T = NNS->getAsType();
  142. if (!T)
  143. return true;
  144. const TemplateSpecializationType *TST =
  145. T->getAs<TemplateSpecializationType>();
  146. if (!TST)
  147. return true;
  148. TemplateName TN = TST->getTemplateName();
  149. const ClassTemplateDecl *TD =
  150. dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
  151. if (!TD)
  152. return true;
  153. CXXRecordDecl *RD = TD->getTemplatedDecl();
  154. if (!RD->hasDefinition())
  155. return true;
  156. RD = RD->getDefinition();
  157. DeclarationName Name(DNT->getIdentifier());
  158. std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
  159. Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
  160. if (Symbols.size() != 1)
  161. return true;
  162. return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
  163. ParentDC, SymbolRoleSet(), Relations);
  164. }
  165. bool TraverseStmt(Stmt *S) {
  166. IndexCtx.indexBody(S, Parent, ParentDC);
  167. return true;
  168. }
  169. };
  170. } // anonymous namespace
  171. void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
  172. const NamedDecl *Parent,
  173. const DeclContext *DC,
  174. bool isBase,
  175. bool isIBType) {
  176. if (!TInfo || TInfo->getTypeLoc().isNull())
  177. return;
  178. indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
  179. }
  180. void IndexingContext::indexTypeLoc(TypeLoc TL,
  181. const NamedDecl *Parent,
  182. const DeclContext *DC,
  183. bool isBase,
  184. bool isIBType) {
  185. if (TL.isNull())
  186. return;
  187. if (!DC)
  188. DC = Parent->getLexicalDeclContext();
  189. TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
  190. }
  191. void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
  192. const NamedDecl *Parent,
  193. const DeclContext *DC) {
  194. if (!NNS)
  195. return;
  196. if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
  197. indexNestedNameSpecifierLoc(Prefix, Parent, DC);
  198. if (!DC)
  199. DC = Parent->getLexicalDeclContext();
  200. SourceLocation Loc = NNS.getLocalBeginLoc();
  201. switch (NNS.getNestedNameSpecifier()->getKind()) {
  202. case NestedNameSpecifier::Identifier:
  203. case NestedNameSpecifier::Global:
  204. case NestedNameSpecifier::Super:
  205. break;
  206. case NestedNameSpecifier::Namespace:
  207. handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
  208. Loc, Parent, DC, SymbolRoleSet());
  209. break;
  210. case NestedNameSpecifier::NamespaceAlias:
  211. handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
  212. Loc, Parent, DC, SymbolRoleSet());
  213. break;
  214. case NestedNameSpecifier::TypeSpec:
  215. case NestedNameSpecifier::TypeSpecWithTemplate:
  216. indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
  217. break;
  218. }
  219. }
  220. void IndexingContext::indexTagDecl(const TagDecl *D,
  221. ArrayRef<SymbolRelation> Relations) {
  222. if (!shouldIndex(D))
  223. return;
  224. if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
  225. return;
  226. if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
  227. if (D->isThisDeclarationADefinition()) {
  228. indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
  229. if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
  230. for (const auto &I : CXXRD->bases()) {
  231. indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
  232. }
  233. }
  234. indexDeclContext(D);
  235. }
  236. }
  237. }