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/DeclVisitor.h"
12
13 using namespace clang;
14 using namespace cxindex;
15
16 namespace {
17
18 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
19 IndexingContext &IndexCtx;
20
21 public:
IndexingDeclVisitor(IndexingContext & indexCtx)22 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
23 : IndexCtx(indexCtx) { }
24
25 /// \brief Returns true if the given method has been defined explicitly by the
26 /// user.
hasUserDefined(const ObjCMethodDecl * D,const ObjCImplDecl * Container)27 static bool hasUserDefined(const ObjCMethodDecl *D,
28 const ObjCImplDecl *Container) {
29 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
30 D->isInstanceMethod());
31 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
32 }
33
handleDeclarator(const DeclaratorDecl * D,const NamedDecl * Parent=0)34 void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = 0) {
35 if (!Parent) Parent = D;
36
37 if (!IndexCtx.shouldIndexFunctionLocalSymbols()) {
38 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
39 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
40 } else {
41 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
42 IndexCtx.handleVar(Parm);
43 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
44 for (FunctionDecl::param_const_iterator PI = FD->param_begin(),
45 PE = FD->param_end();
46 PI != PE; ++PI) {
47 IndexCtx.handleVar(*PI);
48 }
49 }
50 }
51 }
52
handleObjCMethod(const ObjCMethodDecl * D)53 void handleObjCMethod(const ObjCMethodDecl *D) {
54 IndexCtx.handleObjCMethod(D);
55 if (D->isImplicit())
56 return;
57
58 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
59 for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
60 E = D->param_end();
61 I != E; ++I)
62 handleDeclarator(*I, D);
63
64 if (D->isThisDeclarationADefinition()) {
65 const Stmt *Body = D->getBody();
66 if (Body) {
67 IndexCtx.indexBody(Body, D, D);
68 }
69 }
70 }
71
VisitFunctionDecl(const FunctionDecl * D)72 bool VisitFunctionDecl(const FunctionDecl *D) {
73 IndexCtx.handleFunction(D);
74 handleDeclarator(D);
75
76 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
77 // Constructor initializers.
78 for (CXXConstructorDecl::init_const_iterator I = Ctor->init_begin(),
79 E = Ctor->init_end();
80 I != E; ++I) {
81 CXXCtorInitializer *Init = *I;
82 if (Init->isWritten()) {
83 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
84 if (const FieldDecl *Member = Init->getAnyMember())
85 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D);
86 IndexCtx.indexBody(Init->getInit(), D, D);
87 }
88 }
89 }
90
91 if (D->isThisDeclarationADefinition()) {
92 const Stmt *Body = D->getBody();
93 if (Body) {
94 IndexCtx.indexBody(Body, D, D);
95 }
96 }
97 return true;
98 }
99
VisitVarDecl(const VarDecl * D)100 bool VisitVarDecl(const VarDecl *D) {
101 IndexCtx.handleVar(D);
102 handleDeclarator(D);
103 IndexCtx.indexBody(D->getInit(), D);
104 return true;
105 }
106
VisitFieldDecl(const FieldDecl * D)107 bool VisitFieldDecl(const FieldDecl *D) {
108 IndexCtx.handleField(D);
109 handleDeclarator(D);
110 if (D->isBitField())
111 IndexCtx.indexBody(D->getBitWidth(), D);
112 else if (D->hasInClassInitializer())
113 IndexCtx.indexBody(D->getInClassInitializer(), D);
114 return true;
115 }
116
VisitMSPropertyDecl(const MSPropertyDecl * D)117 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
118 handleDeclarator(D);
119 return true;
120 }
121
VisitEnumConstantDecl(const EnumConstantDecl * D)122 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
123 IndexCtx.handleEnumerator(D);
124 IndexCtx.indexBody(D->getInitExpr(), D);
125 return true;
126 }
127
VisitTypedefNameDecl(const TypedefNameDecl * D)128 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
129 IndexCtx.handleTypedefName(D);
130 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
131 return true;
132 }
133
VisitTagDecl(const TagDecl * D)134 bool VisitTagDecl(const TagDecl *D) {
135 // Non-free standing tags are handled in indexTypeSourceInfo.
136 if (D->isFreeStanding())
137 IndexCtx.indexTagDecl(D);
138 return true;
139 }
140
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)141 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
142 IndexCtx.handleObjCInterface(D);
143
144 if (D->isThisDeclarationADefinition()) {
145 IndexCtx.indexTUDeclsInObjCContainer();
146 IndexCtx.indexDeclContext(D);
147 }
148 return true;
149 }
150
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)151 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
152 IndexCtx.handleObjCProtocol(D);
153
154 if (D->isThisDeclarationADefinition()) {
155 IndexCtx.indexTUDeclsInObjCContainer();
156 IndexCtx.indexDeclContext(D);
157 }
158 return true;
159 }
160
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)161 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
162 const ObjCInterfaceDecl *Class = D->getClassInterface();
163 if (!Class)
164 return true;
165
166 if (Class->isImplicitInterfaceDecl())
167 IndexCtx.handleObjCInterface(Class);
168
169 IndexCtx.handleObjCImplementation(D);
170
171 IndexCtx.indexTUDeclsInObjCContainer();
172
173 // Index the ivars first to make sure the synthesized ivars are indexed
174 // before indexing the methods that can reference them.
175 for (ObjCImplementationDecl::ivar_iterator
176 IvarI = D->ivar_begin(),
177 IvarE = D->ivar_end(); IvarI != IvarE; ++IvarI) {
178 IndexCtx.indexDecl(*IvarI);
179 }
180 for (DeclContext::decl_iterator
181 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
182 if (!isa<ObjCIvarDecl>(*I))
183 IndexCtx.indexDecl(*I);
184 }
185
186 return true;
187 }
188
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)189 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
190 IndexCtx.handleObjCCategory(D);
191
192 IndexCtx.indexTUDeclsInObjCContainer();
193 IndexCtx.indexDeclContext(D);
194 return true;
195 }
196
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)197 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
198 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
199 if (!Cat)
200 return true;
201
202 IndexCtx.handleObjCCategoryImpl(D);
203
204 IndexCtx.indexTUDeclsInObjCContainer();
205 IndexCtx.indexDeclContext(D);
206 return true;
207 }
208
VisitObjCMethodDecl(const ObjCMethodDecl * D)209 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
210 // Methods associated with a property, even user-declared ones, are
211 // handled when we handle the property.
212 if (D->isPropertyAccessor())
213 return true;
214
215 handleObjCMethod(D);
216 return true;
217 }
218
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)219 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
220 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
221 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
222 handleObjCMethod(MD);
223 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
224 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
225 handleObjCMethod(MD);
226 IndexCtx.handleObjCProperty(D);
227 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
228 return true;
229 }
230
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)231 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
232 ObjCPropertyDecl *PD = D->getPropertyDecl();
233 IndexCtx.handleSynthesizedObjCProperty(D);
234
235 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
236 return true;
237 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
238
239 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
240 if (!IvarD->getSynthesize())
241 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0,
242 D->getDeclContext());
243 }
244
245 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
246 if (MD->isPropertyAccessor() &&
247 !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
248 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
249 D->getLexicalDeclContext());
250 }
251 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
252 if (MD->isPropertyAccessor() &&
253 !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
254 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
255 D->getLexicalDeclContext());
256 }
257 return true;
258 }
259
VisitNamespaceDecl(const NamespaceDecl * D)260 bool VisitNamespaceDecl(const NamespaceDecl *D) {
261 IndexCtx.handleNamespace(D);
262 IndexCtx.indexDeclContext(D);
263 return true;
264 }
265
VisitUsingDecl(const UsingDecl * D)266 bool VisitUsingDecl(const UsingDecl *D) {
267 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
268 // we should do better.
269
270 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
271 for (UsingDecl::shadow_iterator
272 I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) {
273 IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(),
274 D, D->getLexicalDeclContext());
275 }
276 return true;
277 }
278
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)279 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
280 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
281 // we should do better.
282
283 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
284 IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
285 D->getLocation(), D, D->getLexicalDeclContext());
286 return true;
287 }
288
VisitClassTemplateDecl(const ClassTemplateDecl * D)289 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
290 IndexCtx.handleClassTemplate(D);
291 if (D->isThisDeclarationADefinition())
292 IndexCtx.indexDeclContext(D->getTemplatedDecl());
293 return true;
294 }
295
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)296 bool VisitClassTemplateSpecializationDecl(const
297 ClassTemplateSpecializationDecl *D) {
298 // FIXME: Notify subsequent callbacks if info comes from implicit
299 // instantiation.
300 if (D->isThisDeclarationADefinition() &&
301 (IndexCtx.shouldIndexImplicitTemplateInsts() ||
302 !IndexCtx.isTemplateImplicitInstantiation(D)))
303 IndexCtx.indexTagDecl(D);
304 return true;
305 }
306
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)307 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
308 IndexCtx.handleFunctionTemplate(D);
309 FunctionDecl *FD = D->getTemplatedDecl();
310 handleDeclarator(FD, D);
311 if (FD->isThisDeclarationADefinition()) {
312 const Stmt *Body = FD->getBody();
313 if (Body) {
314 IndexCtx.indexBody(Body, D, FD);
315 }
316 }
317 return true;
318 }
319
VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)320 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
321 IndexCtx.handleTypeAliasTemplate(D);
322 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
323 return true;
324 }
325
VisitImportDecl(const ImportDecl * D)326 bool VisitImportDecl(const ImportDecl *D) {
327 IndexCtx.importedModule(D);
328 return true;
329 }
330 };
331
332 } // anonymous namespace
333
indexDecl(const Decl * D)334 void IndexingContext::indexDecl(const Decl *D) {
335 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
336 return;
337
338 bool Handled = IndexingDeclVisitor(*this).Visit(D);
339 if (!Handled && isa<DeclContext>(D))
340 indexDeclContext(cast<DeclContext>(D));
341 }
342
indexDeclContext(const DeclContext * DC)343 void IndexingContext::indexDeclContext(const DeclContext *DC) {
344 for (DeclContext::decl_iterator
345 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
346 indexDecl(*I);
347 }
348 }
349
indexTopLevelDecl(const Decl * D)350 void IndexingContext::indexTopLevelDecl(const Decl *D) {
351 if (isNotFromSourceFile(D->getLocation()))
352 return;
353
354 if (isa<ObjCMethodDecl>(D))
355 return; // Wait for the objc container.
356
357 indexDecl(D);
358 }
359
indexDeclGroupRef(DeclGroupRef DG)360 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
361 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
362 indexTopLevelDecl(*I);
363 }
364
indexTUDeclsInObjCContainer()365 void IndexingContext::indexTUDeclsInObjCContainer() {
366 while (!TUDeclsInObjCContainer.empty()) {
367 DeclGroupRef DG = TUDeclsInObjCContainer.front();
368 TUDeclsInObjCContainer.pop_front();
369 indexDeclGroupRef(DG);
370 }
371 }
372