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