• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- 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"
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;
27 using namespace idx;
28 
29 namespace  {
30 
31 //===----------------------------------------------------------------------===//
32 // DeclEntityAnalyzer Implementation
33 //===----------------------------------------------------------------------===//
34 
35 class DeclEntityAnalyzer : public TranslationUnitHandler {
36   Entity Ent;
37   TULocationHandler &TULocHandler;
38 
39 public:
DeclEntityAnalyzer(Entity ent,TULocationHandler & handler)40   DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
41     : Ent(ent), TULocHandler(handler) { }
42 
Handle(TranslationUnit * TU)43   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 
59 class RefEntityAnalyzer : public TranslationUnitHandler {
60   Entity Ent;
61   TULocationHandler &TULocHandler;
62 
63 public:
RefEntityAnalyzer(Entity ent,TULocationHandler & handler)64   RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
65     : Ent(ent), TULocHandler(handler) { }
66 
Handle(TranslationUnit * TU)67   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)
79       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.
89 class RefSelectorAnalyzer : public TranslationUnitHandler {
90   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 
102 public:
RefSelectorAnalyzer(ObjCMethodDecl * MD,Program & prog,TULocationHandler & handler)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();
117 
118     for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
119            Cls; Cls = Cls->getSuperClass())
120       HierarchyEntities.insert(Entity::get(Cls, Prog));
121   }
122 
Handle(TranslationUnit * TU)123   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.
ValidReference(ASTLocation ASTLoc,ObjCInterfaceDecl * IFace)145   bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
146     assert(ASTLoc.isStmt());
147 
148     // FIXME: Finding @selector references should be through another Analyzer
149     // method, like FindSelectors.
150     if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
151       return false;
152 
153     ObjCInterfaceDecl *MsgD = 0;
154     ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
155 
156     switch (Msg->getReceiverKind()) {
157     case ObjCMessageExpr::Instance: {
158       const ObjCObjectPointerType *OPT =
159           Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
160 
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;
175       break;
176     }
177 
178     case ObjCMessageExpr::Class: {
179       // Expecting class method.
180       if (IsInstanceMethod)
181         return false;
182 
183       MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
184       break;
185     }
186 
187     case ObjCMessageExpr::SuperClass:
188       // Expecting class method.
189       if (IsInstanceMethod)
190         return false;
191 
192       MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
193       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;
203     }
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.
241 class MessageAnalyzer : public TranslationUnitHandler {
242   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;
254 
255   /// \brief The interface in the message interface hierarchy that "intercepts"
256   /// the selector.
257   Entity ReceiverIFaceEnt;
258 
259 public:
MessageAnalyzer(ObjCMessageExpr * Msg,Program & prog,TULocationHandler & handler)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) {
271       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:
294         CanBeClassMethod = true;
295         MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
296         break;
297 
298       case ObjCMessageExpr::SuperClass:
299         CanBeClassMethod = true;
300         MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
301         break;
302 
303       case ObjCMessageExpr::SuperInstance:
304         CanBeInstanceMethod = true;
305         MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
306                                                            ->getInterfaceDecl();
307         break;
308       }
309     }
310 
311     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         }
338 
339         if (isReceiver) {
340           ReceiverIFaceEnt = Entity::get(Cls, Prog);
341           break;
342         }
343       }
344     }
345   }
346 
Handle(TranslationUnit * TU)347   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.
ValidMethod(ObjCMethodDecl * D,ObjCInterfaceDecl * MsgIFace,ObjCInterfaceDecl * ReceiverIFace)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 
397     if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
398         (!CanBeClassMethod    && D->isClassMethod()))
399       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;
426   }
427 };
428 
429 } // end anonymous namespace
430 
431 //===----------------------------------------------------------------------===//
432 // Analyzer Implementation
433 //===----------------------------------------------------------------------===//
434 
FindDeclarations(Decl * D,TULocationHandler & Handler)435 void 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;
440 
441   DeclEntityAnalyzer DEA(Ent, Handler);
442   Idxer.GetTranslationUnitsFor(Ent, DEA);
443 }
444 
FindReferences(Decl * D,TULocationHandler & Handler)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);
451     return;
452   }
453 
454   Entity Ent = Entity::get(D, Prog);
455   if (Ent.isInvalid())
456     return;
457 
458   RefEntityAnalyzer REA(Ent, Handler);
459   Idxer.GetTranslationUnitsFor(Ent, REA);
460 }
461 
462 /// \brief Find methods that may respond to the given message and pass them
463 /// to Handler.
FindObjCMethods(ObjCMessageExpr * Msg,TULocationHandler & Handler)464 void 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 }
471