blob: 6be35ab4a37825513add2956ef3dd08e3861073c [file] [log] [blame]
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +00001//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
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// This file implements the Analyzer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Index/Analyzer.h"
15#include "clang/Index/Entity.h"
16#include "clang/Index/TranslationUnit.h"
17#include "clang/Index/Handlers.h"
18#include "clang/Index/ASTLocation.h"
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +000019#include "clang/Index/GlobalSelector.h"
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000020#include "clang/Index/DeclReferenceMap.h"
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +000021#include "clang/Index/SelectorMap.h"
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000022#include "clang/Index/IndexProvider.h"
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +000023#include "clang/AST/DeclObjC.h"
24#include "clang/AST/ExprObjC.h"
25#include "llvm/ADT/SmallSet.h"
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000026using namespace clang;
27using namespace idx;
28
29namespace {
30
31//===----------------------------------------------------------------------===//
32// DeclEntityAnalyzer Implementation
33//===----------------------------------------------------------------------===//
34
Benjamin Kramer85b45212009-11-28 19:45:26 +000035class DeclEntityAnalyzer : public TranslationUnitHandler {
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000036 Entity Ent;
37 TULocationHandler &TULocHandler;
Mike Stump1eb44332009-09-09 15:08:12 +000038
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000039public:
40 DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
41 : Ent(ent), TULocHandler(handler) { }
Mike Stump1eb44332009-09-09 15:08:12 +000042
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000043 virtual void Handle(TranslationUnit *TU) {
44 assert(TU && "Passed null translation unit");
45
46 Decl *D = Ent.getDecl(TU->getASTContext());
47 assert(D && "Couldn't resolve Entity");
48
49 for (Decl::redecl_iterator I = D->redecls_begin(),
50 E = D->redecls_end(); I != E; ++I)
51 TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
52 }
53};
54
55//===----------------------------------------------------------------------===//
56// RefEntityAnalyzer Implementation
57//===----------------------------------------------------------------------===//
58
Benjamin Kramer85b45212009-11-28 19:45:26 +000059class RefEntityAnalyzer : public TranslationUnitHandler {
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000060 Entity Ent;
61 TULocationHandler &TULocHandler;
Mike Stump1eb44332009-09-09 15:08:12 +000062
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000063public:
64 RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
65 : Ent(ent), TULocHandler(handler) { }
Mike Stump1eb44332009-09-09 15:08:12 +000066
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +000067 virtual void Handle(TranslationUnit *TU) {
68 assert(TU && "Passed null translation unit");
69
70 Decl *D = Ent.getDecl(TU->getASTContext());
71 assert(D && "Couldn't resolve Entity");
72 NamedDecl *ND = dyn_cast<NamedDecl>(D);
73 if (!ND)
74 return;
75
76 DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
77 for (DeclReferenceMap::astlocation_iterator
78 I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +000079 TULocHandler.Handle(TULocation(TU, *I));
80 }
81};
82
83//===----------------------------------------------------------------------===//
84// RefSelectorAnalyzer Implementation
85//===----------------------------------------------------------------------===//
86
87/// \brief Accepts an ObjC method and finds all message expressions that this
88/// method may respond to.
Benjamin Kramer85b45212009-11-28 19:45:26 +000089class RefSelectorAnalyzer : public TranslationUnitHandler {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +000090 Program &Prog;
91 TULocationHandler &TULocHandler;
92
93 // The original ObjCInterface associated with the method.
94 Entity IFaceEnt;
95 GlobalSelector GlobSel;
96 bool IsInstanceMethod;
97
98 /// \brief Super classes of the ObjCInterface.
99 typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
100 EntitiesSetTy HierarchyEntities;
101
102public:
103 RefSelectorAnalyzer(ObjCMethodDecl *MD,
104 Program &prog, TULocationHandler &handler)
105 : Prog(prog), TULocHandler(handler) {
106 assert(MD);
107
108 // FIXME: Protocol methods.
109 assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
110 "Protocol methods not supported yet");
111
112 ObjCInterfaceDecl *IFD = MD->getClassInterface();
113 assert(IFD);
114 IFaceEnt = Entity::get(IFD, Prog);
115 GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
116 IsInstanceMethod = MD->isInstanceMethod();
Mike Stump1eb44332009-09-09 15:08:12 +0000117
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000118 for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
119 Cls; Cls = Cls->getSuperClass())
120 HierarchyEntities.insert(Entity::get(Cls, Prog));
121 }
Mike Stump1eb44332009-09-09 15:08:12 +0000122
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000123 virtual void Handle(TranslationUnit *TU) {
124 assert(TU && "Passed null translation unit");
125
126 ASTContext &Ctx = TU->getASTContext();
127 // Null means it doesn't exist in this translation unit.
128 ObjCInterfaceDecl *IFace =
129 cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
130 Selector Sel = GlobSel.getSelector(Ctx);
131
132 SelectorMap &SelMap = TU->getSelectorMap();
133 for (SelectorMap::astlocation_iterator
134 I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
135 if (ValidReference(*I, IFace))
136 TULocHandler.Handle(TULocation(TU, *I));
137 }
138 }
139
140 /// \brief Determines whether the given message expression is likely to end
141 /// up at the given interface decl.
142 ///
143 /// It returns true "eagerly", meaning it will return false only if it can
144 /// "prove" statically that the interface cannot accept this message.
145 bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000146 assert(ASTLoc.isStmt());
147
148 // FIXME: Finding @selector references should be through another Analyzer
149 // method, like FindSelectors.
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000150 if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
Mike Stump1eb44332009-09-09 15:08:12 +0000151 return false;
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000152
153 ObjCInterfaceDecl *MsgD = 0;
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000154 ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000155
Douglas Gregor04badcf2010-04-21 00:45:42 +0000156 switch (Msg->getReceiverKind()) {
157 case ObjCMessageExpr::Instance: {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000158 const ObjCObjectPointerType *OPT =
Douglas Gregor04badcf2010-04-21 00:45:42 +0000159 Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000160
161 // Can be anything! Accept it as a possibility..
162 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
163 return true;
164
165 // Expecting class method.
166 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
167 return !IsInstanceMethod;
168
169 MsgD = OPT->getInterfaceDecl();
170 assert(MsgD);
171
172 // Should be an instance method.
173 if (!IsInstanceMethod)
174 return false;
Douglas Gregor04badcf2010-04-21 00:45:42 +0000175 break;
176 }
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000177
Douglas Gregor04badcf2010-04-21 00:45:42 +0000178 case ObjCMessageExpr::Class: {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000179 // Expecting class method.
180 if (IsInstanceMethod)
181 return false;
182
John McCallc12c5bb2010-05-15 11:32:37 +0000183 MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +0000184 break;
185 }
186
187 case ObjCMessageExpr::SuperClass:
188 // Expecting class method.
189 if (IsInstanceMethod)
190 return false;
191
John McCallc12c5bb2010-05-15 11:32:37 +0000192 MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +0000193 break;
194
195 case ObjCMessageExpr::SuperInstance:
196 // Expecting instance method.
197 if (!IsInstanceMethod)
198 return false;
199
200 MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
201 ->getInterfaceDecl();
202 break;
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000203 }
204
205 assert(MsgD);
206
207 // Same interface ? We have a winner!
208 if (MsgD == IFace)
209 return true;
210
211 // If the message interface is a superclass of the original interface,
212 // accept this message as a possibility.
213 if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
214 return true;
215
216 // If the message interface is a subclass of the original interface, accept
217 // the message unless there is a subclass in the hierarchy that will
218 // "steal" the message (thus the message "will go" to the subclass and not
219 /// the original interface).
220 if (IFace) {
221 Selector Sel = Msg->getSelector();
222 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
223 if (Cls == IFace)
224 return true;
225 if (Cls->getMethod(Sel, IsInstanceMethod))
226 return false;
227 }
228 }
229
230 // The interfaces are unrelated, don't accept the message.
231 return false;
232 }
233};
234
235//===----------------------------------------------------------------------===//
236// MessageAnalyzer Implementation
237//===----------------------------------------------------------------------===//
238
239/// \brief Accepts an ObjC message expression and finds all methods that may
240/// respond to it.
Benjamin Kramer85b45212009-11-28 19:45:26 +0000241class MessageAnalyzer : public TranslationUnitHandler {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000242 Program &Prog;
243 TULocationHandler &TULocHandler;
244
245 // The ObjCInterface associated with the message. Can be null/invalid.
246 Entity MsgIFaceEnt;
247 GlobalSelector GlobSel;
248 bool CanBeInstanceMethod;
249 bool CanBeClassMethod;
250
251 /// \brief Super classes of the ObjCInterface.
252 typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
253 EntitiesSetTy HierarchyEntities;
Mike Stump1eb44332009-09-09 15:08:12 +0000254
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000255 /// \brief The interface in the message interface hierarchy that "intercepts"
256 /// the selector.
257 Entity ReceiverIFaceEnt;
258
259public:
260 MessageAnalyzer(ObjCMessageExpr *Msg,
261 Program &prog, TULocationHandler &handler)
262 : Prog(prog), TULocHandler(handler),
263 CanBeInstanceMethod(false),
264 CanBeClassMethod(false) {
265
266 assert(Msg);
267
268 ObjCInterfaceDecl *MsgD = 0;
269
270 while (true) {
Douglas Gregor04badcf2010-04-21 00:45:42 +0000271 switch (Msg->getReceiverKind()) {
272 case ObjCMessageExpr::Instance: {
273 const ObjCObjectPointerType *OPT =
274 Msg->getInstanceReceiver()->getType()
275 ->getAsObjCInterfacePointerType();
276
277 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
278 CanBeInstanceMethod = CanBeClassMethod = true;
279 break;
280 }
281
282 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
283 CanBeClassMethod = true;
284 break;
285 }
286
287 MsgD = OPT->getInterfaceDecl();
288 assert(MsgD);
289 CanBeInstanceMethod = true;
290 break;
291 }
292
293 case ObjCMessageExpr::Class:
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000294 CanBeClassMethod = true;
John McCallc12c5bb2010-05-15 11:32:37 +0000295 MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000296 break;
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000297
Douglas Gregor04badcf2010-04-21 00:45:42 +0000298 case ObjCMessageExpr::SuperClass:
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000299 CanBeClassMethod = true;
John McCallc12c5bb2010-05-15 11:32:37 +0000300 MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +0000301 break;
302
303 case ObjCMessageExpr::SuperInstance:
304 CanBeInstanceMethod = true;
305 MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
306 ->getInterfaceDecl();
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000307 break;
308 }
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000309 }
Mike Stump1eb44332009-09-09 15:08:12 +0000310
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000311 assert(CanBeInstanceMethod || CanBeClassMethod);
312
313 Selector sel = Msg->getSelector();
314 assert(!sel.isNull());
315
316 MsgIFaceEnt = Entity::get(MsgD, Prog);
317 GlobSel = GlobalSelector::get(sel, Prog);
318
319 if (MsgD) {
320 for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
321 Cls; Cls = Cls->getSuperClass())
322 HierarchyEntities.insert(Entity::get(Cls, Prog));
323
324 // Find the interface in the hierarchy that "receives" the message.
325 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
326 bool isReceiver = false;
327
328 ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
329 for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
330 Meth != MethEnd; ++Meth) {
331 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
332 if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
333 (MD->isClassMethod() && CanBeClassMethod)) {
334 isReceiver = true;
335 break;
336 }
337 }
Mike Stump1eb44332009-09-09 15:08:12 +0000338
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000339 if (isReceiver) {
340 ReceiverIFaceEnt = Entity::get(Cls, Prog);
341 break;
342 }
343 }
344 }
345 }
Mike Stump1eb44332009-09-09 15:08:12 +0000346
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000347 virtual void Handle(TranslationUnit *TU) {
348 assert(TU && "Passed null translation unit");
349 ASTContext &Ctx = TU->getASTContext();
350
351 // Null means it doesn't exist in this translation unit or there was no
352 // interface that was determined to receive the original message.
353 ObjCInterfaceDecl *ReceiverIFace =
354 cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
355
356 // No subclass for the original receiver interface, so it remains the
357 // receiver.
358 if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
359 return;
360
361 // Null means it doesn't exist in this translation unit or there was no
362 // interface associated with the message in the first place.
363 ObjCInterfaceDecl *MsgIFace =
364 cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
365
366 Selector Sel = GlobSel.getSelector(Ctx);
367 SelectorMap &SelMap = TU->getSelectorMap();
368 for (SelectorMap::method_iterator
369 I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
370 I != E; ++I) {
371 ObjCMethodDecl *D = *I;
372 if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
373 for (ObjCMethodDecl::redecl_iterator
374 RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
375 TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
376 }
377 }
378 }
379
380 /// \brief Determines whether the given method is likely to accept the
381 /// original message.
382 ///
383 /// It returns true "eagerly", meaning it will return false only if it can
384 /// "prove" statically that the method cannot accept the original message.
385 bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
386 ObjCInterfaceDecl *ReceiverIFace) {
387 assert(D);
388
389 // FIXME: Protocol methods ?
390 if (isa<ObjCProtocolDecl>(D->getDeclContext()))
391 return false;
392
393 // No specific interface associated with the message. Can be anything.
394 if (MsgIFaceEnt.isInvalid())
395 return true;
396
Eli Friedmanbebc4672009-07-30 00:11:31 +0000397 if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
398 (!CanBeClassMethod && D->isClassMethod()))
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000399 return false;
400
401 ObjCInterfaceDecl *IFace = D->getClassInterface();
402 assert(IFace);
403
404 // If the original message interface is the same or a superclass of the
405 // given interface, accept the method as a possibility.
406 if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
407 return true;
408
409 if (ReceiverIFace) {
410 // The given interface, "overrides" the receiver.
411 if (ReceiverIFace->isSuperClassOf(IFace))
412 return true;
413 } else {
414 // No receiver was found for the original message.
415 assert(ReceiverIFaceEnt.isInvalid());
416
417 // If the original message interface is a subclass of the given interface,
418 // accept the message.
419 if (HierarchyEntities.count(Entity::get(IFace, Prog)))
420 return true;
421 }
422
423 // The interfaces are unrelated, or the receiver interface wasn't
424 // "overriden".
425 return false;
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000426 }
427};
428
429} // end anonymous namespace
430
431//===----------------------------------------------------------------------===//
432// Analyzer Implementation
433//===----------------------------------------------------------------------===//
434
435void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
436 assert(D && "Passed null declaration");
437 Entity Ent = Entity::get(D, Prog);
438 if (Ent.isInvalid())
439 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000440
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000441 DeclEntityAnalyzer DEA(Ent, Handler);
442 Idxer.GetTranslationUnitsFor(Ent, DEA);
443}
444
445void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
446 assert(D && "Passed null declaration");
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000447 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
448 RefSelectorAnalyzer RSA(MD, Prog, Handler);
449 GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
450 Idxer.GetTranslationUnitsFor(Sel, RSA);
451 return;
452 }
453
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000454 Entity Ent = Entity::get(D, Prog);
455 if (Ent.isInvalid())
456 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000457
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000458 RefEntityAnalyzer REA(Ent, Handler);
459 Idxer.GetTranslationUnitsFor(Ent, REA);
460}
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000461
462/// \brief Find methods that may respond to the given message and pass them
463/// to Handler.
464void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
465 TULocationHandler &Handler) {
466 assert(Msg);
467 MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
468 GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
469 Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
470}