1 //===- CIndexHigh.cpp - Higher level API functions ------------------------===//
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/DataRecursiveASTVisitor.h"
12 
13 using namespace clang;
14 using namespace cxindex;
15 
16 namespace {
17 
18 class TypeIndexer : public DataRecursiveASTVisitor<TypeIndexer> {
19   IndexingContext &IndexCtx;
20   const NamedDecl *Parent;
21   const DeclContext *ParentDC;
22 
23 public:
TypeIndexer(IndexingContext & indexCtx,const NamedDecl * parent,const DeclContext * DC)24   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
25               const DeclContext *DC)
26     : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
27 
shouldWalkTypesOfTypeLocs() const28   bool shouldWalkTypesOfTypeLocs() const { return false; }
29 
VisitTypedefTypeLoc(TypedefTypeLoc TL)30   bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
31     IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
32                              Parent, ParentDC);
33     return true;
34   }
35 
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)36   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
37     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
38     return true;
39   }
40 
VisitTagTypeLoc(TagTypeLoc TL)41   bool VisitTagTypeLoc(TagTypeLoc TL) {
42     TagDecl *D = TL.getDecl();
43     if (D->getParentFunctionOrMethod())
44       return true;
45 
46     if (TL.isDefinition()) {
47       IndexCtx.indexTagDecl(D);
48       return true;
49     }
50 
51     if (D->getLocation() == TL.getNameLoc())
52       IndexCtx.handleTagDecl(D);
53     else
54       IndexCtx.handleReference(D, TL.getNameLoc(),
55                                Parent, ParentDC);
56     return true;
57   }
58 
VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL)59   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
60     IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
61                              Parent, ParentDC);
62     return true;
63   }
64 
VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL)65   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
66     for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
67       IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
68                                Parent, ParentDC);
69     }
70     return true;
71   }
72 
VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL)73   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
74     if (const TemplateSpecializationType *T = TL.getTypePtr()) {
75       if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
76         if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
77           IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
78                                    Parent, ParentDC);
79       } else {
80         if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
81           IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
82                                    Parent, ParentDC);
83       }
84     }
85     return true;
86   }
87 
TraverseStmt(Stmt * S)88   bool TraverseStmt(Stmt *S) {
89     IndexCtx.indexBody(S, Parent, ParentDC);
90     return true;
91   }
92 };
93 
94 } // anonymous namespace
95 
indexTypeSourceInfo(TypeSourceInfo * TInfo,const NamedDecl * Parent,const DeclContext * DC)96 void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
97                                           const NamedDecl *Parent,
98                                           const DeclContext *DC) {
99   if (!TInfo || TInfo->getTypeLoc().isNull())
100     return;
101 
102   indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
103 }
104 
indexTypeLoc(TypeLoc TL,const NamedDecl * Parent,const DeclContext * DC)105 void IndexingContext::indexTypeLoc(TypeLoc TL,
106                                    const NamedDecl *Parent,
107                                    const DeclContext *DC) {
108   if (TL.isNull())
109     return;
110 
111   if (!DC)
112     DC = Parent->getLexicalDeclContext();
113   TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
114 }
115 
indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,const NamedDecl * Parent,const DeclContext * DC)116 void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
117                                                   const NamedDecl *Parent,
118                                                   const DeclContext *DC) {
119   if (!NNS)
120     return;
121 
122   if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
123     indexNestedNameSpecifierLoc(Prefix, Parent, DC);
124 
125   if (!DC)
126     DC = Parent->getLexicalDeclContext();
127   SourceLocation Loc = NNS.getSourceRange().getBegin();
128 
129   switch (NNS.getNestedNameSpecifier()->getKind()) {
130   case NestedNameSpecifier::Identifier:
131   case NestedNameSpecifier::Global:
132   case NestedNameSpecifier::Super:
133     break;
134 
135   case NestedNameSpecifier::Namespace:
136     handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
137                     Loc, Parent, DC);
138     break;
139   case NestedNameSpecifier::NamespaceAlias:
140     handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
141                     Loc, Parent, DC);
142     break;
143 
144   case NestedNameSpecifier::TypeSpec:
145   case NestedNameSpecifier::TypeSpecWithTemplate:
146     indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
147     break;
148   }
149 }
150 
indexTagDecl(const TagDecl * D)151 void IndexingContext::indexTagDecl(const TagDecl *D) {
152   if (handleTagDecl(D)) {
153     if (D->isThisDeclarationADefinition())
154       indexDeclContext(D);
155   }
156 }
157