1 //===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Analyzer interface.
12 //===----------------------------------------------------------------------===//
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"
19 #include "clang/Index/GlobalSelector.h"
20 #include "clang/Index/DeclReferenceMap.h"
21 #include "clang/Index/SelectorMap.h"
22 #include "clang/Index/IndexProvider.h"
23 #include "clang/AST/DeclObjC.h"
24 #include "clang/AST/ExprObjC.h"
25 #include "llvm/ADT/SmallSet.h"
26 using namespace clang;
31 //===----------------------------------------------------------------------===//
32 // DeclEntityAnalyzer Implementation
33 //===----------------------------------------------------------------------===//
35 class DeclEntityAnalyzer : public TranslationUnitHandler {
37 TULocationHandler &TULocHandler;
40 DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
41 : Ent(ent), TULocHandler(handler) { }
43 virtual void Handle(TranslationUnit *TU) {
44 assert(TU && "Passed null translation unit");
46 Decl *D = Ent.getDecl(TU->getASTContext());
47 assert(D && "Couldn't resolve Entity");
49 for (Decl::redecl_iterator I = D->redecls_begin(),
50 E = D->redecls_end(); I != E; ++I)
51 TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
55 //===----------------------------------------------------------------------===//
56 // RefEntityAnalyzer Implementation
57 //===----------------------------------------------------------------------===//
59 class RefEntityAnalyzer : public TranslationUnitHandler {
61 TULocationHandler &TULocHandler;
64 RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
65 : Ent(ent), TULocHandler(handler) { }
67 virtual void Handle(TranslationUnit *TU) {
68 assert(TU && "Passed null translation unit");
70 Decl *D = Ent.getDecl(TU->getASTContext());
71 assert(D && "Couldn't resolve Entity");
72 NamedDecl *ND = dyn_cast<NamedDecl>(D);
76 DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
77 for (DeclReferenceMap::astlocation_iterator
78 I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
79 TULocHandler.Handle(TULocation(TU, *I));
83 //===----------------------------------------------------------------------===//
84 // RefSelectorAnalyzer Implementation
85 //===----------------------------------------------------------------------===//
87 /// \brief Accepts an ObjC method and finds all message expressions that this
88 /// method may respond to.
89 class RefSelectorAnalyzer : public TranslationUnitHandler {
91 TULocationHandler &TULocHandler;
93 // The original ObjCInterface associated with the method.
95 GlobalSelector GlobSel;
96 bool IsInstanceMethod;
98 /// \brief Super classes of the ObjCInterface.
99 typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
100 EntitiesSetTy HierarchyEntities;
103 RefSelectorAnalyzer(ObjCMethodDecl *MD,
104 Program &prog, TULocationHandler &handler)
105 : Prog(prog), TULocHandler(handler) {
108 // FIXME: Protocol methods.
109 assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
110 "Protocol methods not supported yet");
112 ObjCInterfaceDecl *IFD = MD->getClassInterface();
114 IFaceEnt = Entity::get(IFD, Prog);
115 GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
116 IsInstanceMethod = MD->isInstanceMethod();
118 for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
119 Cls; Cls = Cls->getSuperClass())
120 HierarchyEntities.insert(Entity::get(Cls, Prog));
123 virtual void Handle(TranslationUnit *TU) {
124 assert(TU && "Passed null translation unit");
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);
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));
140 /// \brief Determines whether the given message expression is likely to end
141 /// up at the given interface decl.
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) {
146 assert(ASTLoc.isStmt());
148 // FIXME: Finding @selector references should be through another Analyzer
149 // method, like FindSelectors.
150 if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
153 ObjCInterfaceDecl *MsgD = 0;
154 ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
156 switch (Msg->getReceiverKind()) {
157 case ObjCMessageExpr::Instance: {
158 const ObjCObjectPointerType *OPT =
159 Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
161 // Can be anything! Accept it as a possibility..
162 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
165 // Expecting class method.
166 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
167 return !IsInstanceMethod;
169 MsgD = OPT->getInterfaceDecl();
172 // Should be an instance method.
173 if (!IsInstanceMethod)
178 case ObjCMessageExpr::Class: {
179 // Expecting class method.
180 if (IsInstanceMethod)
183 MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
187 case ObjCMessageExpr::SuperClass:
188 // Expecting class method.
189 if (IsInstanceMethod)
192 MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
195 case ObjCMessageExpr::SuperInstance:
196 // Expecting instance method.
197 if (!IsInstanceMethod)
200 MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
201 ->getInterfaceDecl();
207 // Same interface ? We have a winner!
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)))
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).
221 Selector Sel = Msg->getSelector();
222 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
225 if (Cls->getMethod(Sel, IsInstanceMethod))
230 // The interfaces are unrelated, don't accept the message.
235 //===----------------------------------------------------------------------===//
236 // MessageAnalyzer Implementation
237 //===----------------------------------------------------------------------===//
239 /// \brief Accepts an ObjC message expression and finds all methods that may
241 class MessageAnalyzer : public TranslationUnitHandler {
243 TULocationHandler &TULocHandler;
245 // The ObjCInterface associated with the message. Can be null/invalid.
247 GlobalSelector GlobSel;
248 bool CanBeInstanceMethod;
249 bool CanBeClassMethod;
251 /// \brief Super classes of the ObjCInterface.
252 typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
253 EntitiesSetTy HierarchyEntities;
255 /// \brief The interface in the message interface hierarchy that "intercepts"
257 Entity ReceiverIFaceEnt;
260 MessageAnalyzer(ObjCMessageExpr *Msg,
261 Program &prog, TULocationHandler &handler)
262 : Prog(prog), TULocHandler(handler),
263 CanBeInstanceMethod(false),
264 CanBeClassMethod(false) {
268 ObjCInterfaceDecl *MsgD = 0;
271 switch (Msg->getReceiverKind()) {
272 case ObjCMessageExpr::Instance: {
273 const ObjCObjectPointerType *OPT =
274 Msg->getInstanceReceiver()->getType()
275 ->getAsObjCInterfacePointerType();
277 if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
278 CanBeInstanceMethod = CanBeClassMethod = true;
282 if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
283 CanBeClassMethod = true;
287 MsgD = OPT->getInterfaceDecl();
289 CanBeInstanceMethod = true;
293 case ObjCMessageExpr::Class:
294 CanBeClassMethod = true;
295 MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
298 case ObjCMessageExpr::SuperClass:
299 CanBeClassMethod = true;
300 MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
303 case ObjCMessageExpr::SuperInstance:
304 CanBeInstanceMethod = true;
305 MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
306 ->getInterfaceDecl();
311 assert(CanBeInstanceMethod || CanBeClassMethod);
313 Selector sel = Msg->getSelector();
314 assert(!sel.isNull());
316 MsgIFaceEnt = Entity::get(MsgD, Prog);
317 GlobSel = GlobalSelector::get(sel, Prog);
320 for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
321 Cls; Cls = Cls->getSuperClass())
322 HierarchyEntities.insert(Entity::get(Cls, Prog));
324 // Find the interface in the hierarchy that "receives" the message.
325 for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
326 bool isReceiver = false;
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)) {
340 ReceiverIFaceEnt = Entity::get(Cls, Prog);
347 virtual void Handle(TranslationUnit *TU) {
348 assert(TU && "Passed null translation unit");
349 ASTContext &Ctx = TU->getASTContext();
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));
356 // No subclass for the original receiver interface, so it remains the
358 if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
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));
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);
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)));
380 /// \brief Determines whether the given method is likely to accept the
381 /// original message.
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) {
389 // FIXME: Protocol methods ?
390 if (isa<ObjCProtocolDecl>(D->getDeclContext()))
393 // No specific interface associated with the message. Can be anything.
394 if (MsgIFaceEnt.isInvalid())
397 if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
398 (!CanBeClassMethod && D->isClassMethod()))
401 ObjCInterfaceDecl *IFace = D->getClassInterface();
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))
410 // The given interface, "overrides" the receiver.
411 if (ReceiverIFace->isSuperClassOf(IFace))
414 // No receiver was found for the original message.
415 assert(ReceiverIFaceEnt.isInvalid());
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)))
423 // The interfaces are unrelated, or the receiver interface wasn't
429 } // end anonymous namespace
431 //===----------------------------------------------------------------------===//
432 // Analyzer Implementation
433 //===----------------------------------------------------------------------===//
435 void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
436 assert(D && "Passed null declaration");
437 Entity Ent = Entity::get(D, Prog);
441 DeclEntityAnalyzer DEA(Ent, Handler);
442 Idxer.GetTranslationUnitsFor(Ent, DEA);
445 void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
446 assert(D && "Passed null declaration");
447 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);
454 Entity Ent = Entity::get(D, Prog);
458 RefEntityAnalyzer REA(Ent, Handler);
459 Idxer.GetTranslationUnitsFor(Ent, REA);
462 /// \brief Find methods that may respond to the given message and pass them
464 void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
465 TULocationHandler &Handler) {
467 MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
468 GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
469 Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);