• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
2  //
3  //                     The LLVM Compiler Infrastructure
4  //
5  // This file is distributed under the University of Illinois Open Source
6  // License. See LICENSE.TXT for details.
7  //
8  //===----------------------------------------------------------------------===//
9  
10  #include "IndexingContext.h"
11  #include "clang/AST/RecursiveASTVisitor.h"
12  
13  using namespace clang;
14  using namespace index;
15  
16  namespace {
17  
18  class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
19    IndexingContext &IndexCtx;
20    const NamedDecl *Parent;
21    const DeclContext *ParentDC;
22    bool IsBase;
23    SmallVector<SymbolRelation, 3> Relations;
24  
25    typedef RecursiveASTVisitor<TypeIndexer> base;
26  
27  public:
TypeIndexer(IndexingContext & indexCtx,const NamedDecl * parent,const DeclContext * DC,bool isBase)28    TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
29                const DeclContext *DC, bool isBase)
30      : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
31      if (IsBase) {
32        assert(Parent);
33        Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
34      }
35    }
36  
shouldWalkTypesOfTypeLocs() const37    bool shouldWalkTypesOfTypeLocs() const { return false; }
38  
VisitTypedefTypeLoc(TypedefTypeLoc TL)39    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
40      return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
41                                      Parent, ParentDC, SymbolRoleSet(),
42                                      Relations);
43    }
44  
45  #define TRY_TO(CALL_EXPR)                                                      \
46    do {                                                                         \
47      if (!CALL_EXPR)                                                            \
48        return false;                                                            \
49    } while (0)
50  
traverseParamVarHelper(ParmVarDecl * D)51    bool traverseParamVarHelper(ParmVarDecl *D) {
52      TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
53      if (D->getTypeSourceInfo())
54        TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
55      return true;
56    }
57  
TraverseParmVarDecl(ParmVarDecl * D)58    bool TraverseParmVarDecl(ParmVarDecl *D) {
59      // Avoid visiting default arguments from the definition that were already
60      // visited in the declaration.
61      // FIXME: A free function definition can have default arguments.
62      // Avoiding double visitaiton of default arguments should be handled by the
63      // visitor probably with a bit in the AST to indicate if the attached
64      // default argument was 'inherited' or written in source.
65      if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
66        if (FD->isThisDeclarationADefinition()) {
67          return traverseParamVarHelper(D);
68        }
69      }
70  
71      return base::TraverseParmVarDecl(D);
72    }
73  
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)74    bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
75      IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
76      return true;
77    }
78  
VisitTagTypeLoc(TagTypeLoc TL)79    bool VisitTagTypeLoc(TagTypeLoc TL) {
80      TagDecl *D = TL.getDecl();
81      if (D->getParentFunctionOrMethod())
82        return true;
83  
84      if (TL.isDefinition()) {
85        IndexCtx.indexTagDecl(D);
86        return true;
87      }
88  
89      return IndexCtx.handleReference(D, TL.getNameLoc(),
90                                      Parent, ParentDC, SymbolRoleSet(),
91                                      Relations);
92    }
93  
VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL)94    bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
95      return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
96                                      Parent, ParentDC, SymbolRoleSet());
97    }
98  
VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL)99    bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
100      for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
101        IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
102                                 Parent, ParentDC, SymbolRoleSet());
103      }
104      return true;
105    }
106  
VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL)107    bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
108      if (const TemplateSpecializationType *T = TL.getTypePtr()) {
109        if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
110          if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
111            IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
112                                     Parent, ParentDC, SymbolRoleSet(), Relations);
113        } else {
114          if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
115            IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
116                                     Parent, ParentDC, SymbolRoleSet(), Relations);
117        }
118      }
119      return true;
120    }
121  
TraverseStmt(Stmt * S)122    bool TraverseStmt(Stmt *S) {
123      IndexCtx.indexBody(S, Parent, ParentDC);
124      return true;
125    }
126  };
127  
128  } // anonymous namespace
129  
indexTypeSourceInfo(TypeSourceInfo * TInfo,const NamedDecl * Parent,const DeclContext * DC,bool isBase)130  void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
131                                            const NamedDecl *Parent,
132                                            const DeclContext *DC,
133                                            bool isBase) {
134    if (!TInfo || TInfo->getTypeLoc().isNull())
135      return;
136  
137    indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase);
138  }
139  
indexTypeLoc(TypeLoc TL,const NamedDecl * Parent,const DeclContext * DC,bool isBase)140  void IndexingContext::indexTypeLoc(TypeLoc TL,
141                                     const NamedDecl *Parent,
142                                     const DeclContext *DC,
143                                     bool isBase) {
144    if (TL.isNull())
145      return;
146  
147    if (!DC)
148      DC = Parent->getLexicalDeclContext();
149    TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL);
150  }
151  
indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,const NamedDecl * Parent,const DeclContext * DC)152  void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
153                                                    const NamedDecl *Parent,
154                                                    const DeclContext *DC) {
155    if (!NNS)
156      return;
157  
158    if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
159      indexNestedNameSpecifierLoc(Prefix, Parent, DC);
160  
161    if (!DC)
162      DC = Parent->getLexicalDeclContext();
163    SourceLocation Loc = NNS.getSourceRange().getBegin();
164  
165    switch (NNS.getNestedNameSpecifier()->getKind()) {
166    case NestedNameSpecifier::Identifier:
167    case NestedNameSpecifier::Global:
168    case NestedNameSpecifier::Super:
169      break;
170  
171    case NestedNameSpecifier::Namespace:
172      handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
173                      Loc, Parent, DC, SymbolRoleSet());
174      break;
175    case NestedNameSpecifier::NamespaceAlias:
176      handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
177                      Loc, Parent, DC, SymbolRoleSet());
178      break;
179  
180    case NestedNameSpecifier::TypeSpec:
181    case NestedNameSpecifier::TypeSpecWithTemplate:
182      indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
183      break;
184    }
185  }
186  
indexTagDecl(const TagDecl * D)187  void IndexingContext::indexTagDecl(const TagDecl *D) {
188    if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
189      return;
190  
191    if (handleDecl(D)) {
192      if (D->isThisDeclarationADefinition()) {
193        indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
194        if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
195          for (const auto &I : CXXRD->bases()) {
196            indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
197          }
198        }
199        indexDeclContext(D);
200      }
201    }
202  }
203