blob: fb3529d5405cf954f155ad8f6456999df397cdb9 [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
156 if (Msg->getReceiver()) {
157 const ObjCObjectPointerType *OPT =
158 Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
159
160 // Can be anything! Accept it as a possibility..
161 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
162 return true;
163
164 // Expecting class method.
165 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
166 return !IsInstanceMethod;
167
168 MsgD = OPT->getInterfaceDecl();
169 assert(MsgD);
170
171 // Should be an instance method.
172 if (!IsInstanceMethod)
173 return false;
174
175 } else {
176 // Expecting class method.
177 if (IsInstanceMethod)
178 return false;
179
180 MsgD = Msg->getClassInfo().first;
181 // FIXME: Case when we only have an identifier.
Mike Stump1eb44332009-09-09 15:08:12 +0000182 assert(MsgD && "Identifier only");
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000183 }
184
185 assert(MsgD);
186
187 // Same interface ? We have a winner!
188 if (MsgD == IFace)
189 return true;
190
191 // If the message interface is a superclass of the original interface,
192 // accept this message as a possibility.
193 if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
194 return true;
195
196 // If the message interface is a subclass of the original interface, accept
197 // the message unless there is a subclass in the hierarchy that will
198 // "steal" the message (thus the message "will go" to the subclass and not
199 /// the original interface).
200 if (IFace) {
201 Selector Sel = Msg->getSelector();
202 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
203 if (Cls == IFace)
204 return true;
205 if (Cls->getMethod(Sel, IsInstanceMethod))
206 return false;
207 }
208 }
209
210 // The interfaces are unrelated, don't accept the message.
211 return false;
212 }
213};
214
215//===----------------------------------------------------------------------===//
216// MessageAnalyzer Implementation
217//===----------------------------------------------------------------------===//
218
219/// \brief Accepts an ObjC message expression and finds all methods that may
220/// respond to it.
Benjamin Kramer85b45212009-11-28 19:45:26 +0000221class MessageAnalyzer : public TranslationUnitHandler {
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000222 Program &Prog;
223 TULocationHandler &TULocHandler;
224
225 // The ObjCInterface associated with the message. Can be null/invalid.
226 Entity MsgIFaceEnt;
227 GlobalSelector GlobSel;
228 bool CanBeInstanceMethod;
229 bool CanBeClassMethod;
230
231 /// \brief Super classes of the ObjCInterface.
232 typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
233 EntitiesSetTy HierarchyEntities;
Mike Stump1eb44332009-09-09 15:08:12 +0000234
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000235 /// \brief The interface in the message interface hierarchy that "intercepts"
236 /// the selector.
237 Entity ReceiverIFaceEnt;
238
239public:
240 MessageAnalyzer(ObjCMessageExpr *Msg,
241 Program &prog, TULocationHandler &handler)
242 : Prog(prog), TULocHandler(handler),
243 CanBeInstanceMethod(false),
244 CanBeClassMethod(false) {
245
246 assert(Msg);
247
248 ObjCInterfaceDecl *MsgD = 0;
249
250 while (true) {
251 if (Msg->getReceiver() == 0) {
252 CanBeClassMethod = true;
253 MsgD = Msg->getClassInfo().first;
254 // FIXME: Case when we only have an identifier.
Mike Stump1eb44332009-09-09 15:08:12 +0000255 assert(MsgD && "Identifier only");
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000256 break;
257 }
258
259 const ObjCObjectPointerType *OPT =
260 Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
261
262 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
263 CanBeInstanceMethod = CanBeClassMethod = true;
264 break;
265 }
266
267 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
268 CanBeClassMethod = true;
269 break;
270 }
271
272 MsgD = OPT->getInterfaceDecl();
273 assert(MsgD);
274 CanBeInstanceMethod = true;
275 break;
276 }
Mike Stump1eb44332009-09-09 15:08:12 +0000277
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000278 assert(CanBeInstanceMethod || CanBeClassMethod);
279
280 Selector sel = Msg->getSelector();
281 assert(!sel.isNull());
282
283 MsgIFaceEnt = Entity::get(MsgD, Prog);
284 GlobSel = GlobalSelector::get(sel, Prog);
285
286 if (MsgD) {
287 for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
288 Cls; Cls = Cls->getSuperClass())
289 HierarchyEntities.insert(Entity::get(Cls, Prog));
290
291 // Find the interface in the hierarchy that "receives" the message.
292 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
293 bool isReceiver = false;
294
295 ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
296 for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
297 Meth != MethEnd; ++Meth) {
298 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
299 if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
300 (MD->isClassMethod() && CanBeClassMethod)) {
301 isReceiver = true;
302 break;
303 }
304 }
Mike Stump1eb44332009-09-09 15:08:12 +0000305
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000306 if (isReceiver) {
307 ReceiverIFaceEnt = Entity::get(Cls, Prog);
308 break;
309 }
310 }
311 }
312 }
Mike Stump1eb44332009-09-09 15:08:12 +0000313
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000314 virtual void Handle(TranslationUnit *TU) {
315 assert(TU && "Passed null translation unit");
316 ASTContext &Ctx = TU->getASTContext();
317
318 // Null means it doesn't exist in this translation unit or there was no
319 // interface that was determined to receive the original message.
320 ObjCInterfaceDecl *ReceiverIFace =
321 cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
322
323 // No subclass for the original receiver interface, so it remains the
324 // receiver.
325 if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
326 return;
327
328 // Null means it doesn't exist in this translation unit or there was no
329 // interface associated with the message in the first place.
330 ObjCInterfaceDecl *MsgIFace =
331 cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
332
333 Selector Sel = GlobSel.getSelector(Ctx);
334 SelectorMap &SelMap = TU->getSelectorMap();
335 for (SelectorMap::method_iterator
336 I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
337 I != E; ++I) {
338 ObjCMethodDecl *D = *I;
339 if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
340 for (ObjCMethodDecl::redecl_iterator
341 RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
342 TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
343 }
344 }
345 }
346
347 /// \brief Determines whether the given method is likely to accept the
348 /// original message.
349 ///
350 /// It returns true "eagerly", meaning it will return false only if it can
351 /// "prove" statically that the method cannot accept the original message.
352 bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
353 ObjCInterfaceDecl *ReceiverIFace) {
354 assert(D);
355
356 // FIXME: Protocol methods ?
357 if (isa<ObjCProtocolDecl>(D->getDeclContext()))
358 return false;
359
360 // No specific interface associated with the message. Can be anything.
361 if (MsgIFaceEnt.isInvalid())
362 return true;
363
Eli Friedmanbebc4672009-07-30 00:11:31 +0000364 if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
365 (!CanBeClassMethod && D->isClassMethod()))
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000366 return false;
367
368 ObjCInterfaceDecl *IFace = D->getClassInterface();
369 assert(IFace);
370
371 // If the original message interface is the same or a superclass of the
372 // given interface, accept the method as a possibility.
373 if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
374 return true;
375
376 if (ReceiverIFace) {
377 // The given interface, "overrides" the receiver.
378 if (ReceiverIFace->isSuperClassOf(IFace))
379 return true;
380 } else {
381 // No receiver was found for the original message.
382 assert(ReceiverIFaceEnt.isInvalid());
383
384 // If the original message interface is a subclass of the given interface,
385 // accept the message.
386 if (HierarchyEntities.count(Entity::get(IFace, Prog)))
387 return true;
388 }
389
390 // The interfaces are unrelated, or the receiver interface wasn't
391 // "overriden".
392 return false;
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000393 }
394};
395
396} // end anonymous namespace
397
398//===----------------------------------------------------------------------===//
399// Analyzer Implementation
400//===----------------------------------------------------------------------===//
401
402void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
403 assert(D && "Passed null declaration");
404 Entity Ent = Entity::get(D, Prog);
405 if (Ent.isInvalid())
406 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000407
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000408 DeclEntityAnalyzer DEA(Ent, Handler);
409 Idxer.GetTranslationUnitsFor(Ent, DEA);
410}
411
412void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
413 assert(D && "Passed null declaration");
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000414 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
415 RefSelectorAnalyzer RSA(MD, Prog, Handler);
416 GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
417 Idxer.GetTranslationUnitsFor(Sel, RSA);
418 return;
419 }
420
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000421 Entity Ent = Entity::get(D, Prog);
422 if (Ent.isInvalid())
423 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000424
Argyrios Kyrtzidis7f4656e2009-07-29 23:40:14 +0000425 RefEntityAnalyzer REA(Ent, Handler);
426 Idxer.GetTranslationUnitsFor(Ent, REA);
427}
Argyrios Kyrtzidis19b732a2009-07-30 00:03:55 +0000428
429/// \brief Find methods that may respond to the given message and pass them
430/// to Handler.
431void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
432 TULocationHandler &Handler) {
433 assert(Msg);
434 MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
435 GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
436 Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
437}