1 //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "IndexingContext.h"
11 #include "clang/AST/RecursiveASTVisitor.h"
13 using namespace clang;
14 using namespace index;
18 class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
19 IndexingContext &IndexCtx;
20 const NamedDecl *Parent;
21 const DeclContext *ParentDC;
23 SmallVector<SymbolRelation, 3> Relations;
25 typedef RecursiveASTVisitor<TypeIndexer> base;
28 TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
29 const DeclContext *DC, bool isBase, bool isIBType)
30 : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
33 Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
37 Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
41 bool shouldWalkTypesOfTypeLocs() const { return false; }
43 bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
44 return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
45 Parent, ParentDC, SymbolRoleSet(),
49 #define TRY_TO(CALL_EXPR) \
55 bool traverseParamVarHelper(ParmVarDecl *D) {
56 TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
57 if (D->getTypeSourceInfo())
58 TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
62 bool TraverseParmVarDecl(ParmVarDecl *D) {
63 // Avoid visiting default arguments from the definition that were already
64 // visited in the declaration.
65 // FIXME: A free function definition can have default arguments.
66 // Avoiding double visitaiton of default arguments should be handled by the
67 // visitor probably with a bit in the AST to indicate if the attached
68 // default argument was 'inherited' or written in source.
69 if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
70 if (FD->isThisDeclarationADefinition()) {
71 return traverseParamVarHelper(D);
75 return base::TraverseParmVarDecl(D);
78 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
79 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
83 bool VisitTagTypeLoc(TagTypeLoc TL) {
84 TagDecl *D = TL.getDecl();
85 if (D->getParentFunctionOrMethod())
88 if (TL.isDefinition()) {
89 IndexCtx.indexTagDecl(D);
93 return IndexCtx.handleReference(D, TL.getNameLoc(),
94 Parent, ParentDC, SymbolRoleSet(),
98 bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
99 return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
100 Parent, ParentDC, SymbolRoleSet(), Relations);
103 bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
104 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
105 IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
106 Parent, ParentDC, SymbolRoleSet(), Relations);
111 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
112 if (const TemplateSpecializationType *T = TL.getTypePtr()) {
113 if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
114 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
115 IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
116 Parent, ParentDC, SymbolRoleSet(), Relations);
118 if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
119 IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
120 Parent, ParentDC, SymbolRoleSet(), Relations);
126 bool TraverseStmt(Stmt *S) {
127 IndexCtx.indexBody(S, Parent, ParentDC);
132 } // anonymous namespace
134 void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
135 const NamedDecl *Parent,
136 const DeclContext *DC,
139 if (!TInfo || TInfo->getTypeLoc().isNull())
142 indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
145 void IndexingContext::indexTypeLoc(TypeLoc TL,
146 const NamedDecl *Parent,
147 const DeclContext *DC,
154 DC = Parent->getLexicalDeclContext();
155 TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
158 void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
159 const NamedDecl *Parent,
160 const DeclContext *DC) {
164 if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
165 indexNestedNameSpecifierLoc(Prefix, Parent, DC);
168 DC = Parent->getLexicalDeclContext();
169 SourceLocation Loc = NNS.getSourceRange().getBegin();
171 switch (NNS.getNestedNameSpecifier()->getKind()) {
172 case NestedNameSpecifier::Identifier:
173 case NestedNameSpecifier::Global:
174 case NestedNameSpecifier::Super:
177 case NestedNameSpecifier::Namespace:
178 handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
179 Loc, Parent, DC, SymbolRoleSet());
181 case NestedNameSpecifier::NamespaceAlias:
182 handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
183 Loc, Parent, DC, SymbolRoleSet());
186 case NestedNameSpecifier::TypeSpec:
187 case NestedNameSpecifier::TypeSpecWithTemplate:
188 indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
193 void IndexingContext::indexTagDecl(const TagDecl *D) {
194 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
198 if (D->isThisDeclarationADefinition()) {
199 indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
200 if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
201 for (const auto &I : CXXRD->bases()) {
202 indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);