]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/Index/Analyzer.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / Index / Analyzer.cpp
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:
40   DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
41     : Ent(ent), TULocHandler(handler) { }
42
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:
64   RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
65     : Ent(ent), TULocHandler(handler) { }
66
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:
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
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.
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:
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
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.
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
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
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.
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 }