Home | History | Annotate | Download | only in Index
      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 }
    471