clang API Documentation

Analyzer.cpp
Go to the documentation of this file.
00001 //===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Analyzer interface.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Index/Analyzer.h"
00015 #include "clang/Index/Entity.h"
00016 #include "clang/Index/TranslationUnit.h"
00017 #include "clang/Index/Handlers.h"
00018 #include "clang/Index/ASTLocation.h"
00019 #include "clang/Index/GlobalSelector.h"
00020 #include "clang/Index/DeclReferenceMap.h"
00021 #include "clang/Index/SelectorMap.h"
00022 #include "clang/Index/IndexProvider.h"
00023 #include "clang/AST/DeclObjC.h"
00024 #include "clang/AST/ExprObjC.h"
00025 #include "llvm/ADT/SmallSet.h"
00026 using namespace clang;
00027 using namespace idx;
00028 
00029 namespace  {
00030 
00031 //===----------------------------------------------------------------------===//
00032 // DeclEntityAnalyzer Implementation
00033 //===----------------------------------------------------------------------===//
00034 
00035 class DeclEntityAnalyzer : public TranslationUnitHandler {
00036   Entity Ent;
00037   TULocationHandler &TULocHandler;
00038 
00039 public:
00040   DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
00041     : Ent(ent), TULocHandler(handler) { }
00042 
00043   virtual void Handle(TranslationUnit *TU) {
00044     assert(TU && "Passed null translation unit");
00045 
00046     Decl *D = Ent.getDecl(TU->getASTContext());
00047     assert(D && "Couldn't resolve Entity");
00048 
00049     for (Decl::redecl_iterator I = D->redecls_begin(),
00050                                E = D->redecls_end(); I != E; ++I)
00051       TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
00052   }
00053 };
00054 
00055 //===----------------------------------------------------------------------===//
00056 // RefEntityAnalyzer Implementation
00057 //===----------------------------------------------------------------------===//
00058 
00059 class RefEntityAnalyzer : public TranslationUnitHandler {
00060   Entity Ent;
00061   TULocationHandler &TULocHandler;
00062 
00063 public:
00064   RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
00065     : Ent(ent), TULocHandler(handler) { }
00066 
00067   virtual void Handle(TranslationUnit *TU) {
00068     assert(TU && "Passed null translation unit");
00069 
00070     Decl *D = Ent.getDecl(TU->getASTContext());
00071     assert(D && "Couldn't resolve Entity");
00072     NamedDecl *ND = dyn_cast<NamedDecl>(D);
00073     if (!ND)
00074       return;
00075 
00076     DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
00077     for (DeclReferenceMap::astlocation_iterator
00078            I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
00079       TULocHandler.Handle(TULocation(TU, *I));
00080   }
00081 };
00082 
00083 //===----------------------------------------------------------------------===//
00084 // RefSelectorAnalyzer Implementation
00085 //===----------------------------------------------------------------------===//
00086 
00087 /// \brief Accepts an ObjC method and finds all message expressions that this
00088 /// method may respond to.
00089 class RefSelectorAnalyzer : public TranslationUnitHandler {
00090   Program &Prog;
00091   TULocationHandler &TULocHandler;
00092 
00093   // The original ObjCInterface associated with the method.
00094   Entity IFaceEnt;
00095   GlobalSelector GlobSel;
00096   bool IsInstanceMethod;
00097 
00098   /// \brief Super classes of the ObjCInterface.
00099   typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
00100   EntitiesSetTy HierarchyEntities;
00101 
00102 public:
00103   RefSelectorAnalyzer(ObjCMethodDecl *MD,
00104                       Program &prog, TULocationHandler &handler)
00105     : Prog(prog), TULocHandler(handler) {
00106     assert(MD);
00107 
00108     // FIXME: Protocol methods.
00109     assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
00110            "Protocol methods not supported yet");
00111 
00112     ObjCInterfaceDecl *IFD = MD->getClassInterface();
00113     assert(IFD);
00114     IFaceEnt = Entity::get(IFD, Prog);
00115     GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
00116     IsInstanceMethod = MD->isInstanceMethod();
00117 
00118     for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
00119            Cls; Cls = Cls->getSuperClass())
00120       HierarchyEntities.insert(Entity::get(Cls, Prog));
00121   }
00122 
00123   virtual void Handle(TranslationUnit *TU) {
00124     assert(TU && "Passed null translation unit");
00125 
00126     ASTContext &Ctx = TU->getASTContext();
00127     // Null means it doesn't exist in this translation unit.
00128     ObjCInterfaceDecl *IFace =
00129         cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
00130     Selector Sel = GlobSel.getSelector(Ctx);
00131 
00132     SelectorMap &SelMap = TU->getSelectorMap();
00133     for (SelectorMap::astlocation_iterator
00134            I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
00135       if (ValidReference(*I, IFace))
00136         TULocHandler.Handle(TULocation(TU, *I));
00137     }
00138   }
00139 
00140   /// \brief Determines whether the given message expression is likely to end
00141   /// up at the given interface decl.
00142   ///
00143   /// It returns true "eagerly", meaning it will return false only if it can
00144   /// "prove" statically that the interface cannot accept this message.
00145   bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
00146     assert(ASTLoc.isStmt());
00147 
00148     // FIXME: Finding @selector references should be through another Analyzer
00149     // method, like FindSelectors.
00150     if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
00151       return false;
00152 
00153     ObjCInterfaceDecl *MsgD = 0;
00154     ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
00155 
00156     switch (Msg->getReceiverKind()) {
00157     case ObjCMessageExpr::Instance: {
00158       const ObjCObjectPointerType *OPT =
00159           Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
00160 
00161       // Can be anything! Accept it as a possibility..
00162       if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
00163         return true;
00164 
00165       // Expecting class method.
00166       if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
00167         return !IsInstanceMethod;
00168 
00169       MsgD = OPT->getInterfaceDecl();
00170       assert(MsgD);
00171 
00172       // Should be an instance method.
00173       if (!IsInstanceMethod)
00174         return false;
00175       break;
00176     }
00177 
00178     case ObjCMessageExpr::Class: {
00179       // Expecting class method.
00180       if (IsInstanceMethod)
00181         return false;
00182 
00183       MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
00184       break;
00185     }
00186 
00187     case ObjCMessageExpr::SuperClass:
00188       // Expecting class method.
00189       if (IsInstanceMethod)
00190         return false;
00191 
00192       MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
00193       break;
00194 
00195     case ObjCMessageExpr::SuperInstance:
00196       // Expecting instance method.
00197       if (!IsInstanceMethod)
00198         return false;
00199 
00200       MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
00201                                                           ->getInterfaceDecl();
00202       break;
00203     }
00204 
00205     assert(MsgD);
00206 
00207     // Same interface ? We have a winner!
00208     if (declaresSameEntity(MsgD, IFace))
00209       return true;
00210 
00211     // If the message interface is a superclass of the original interface,
00212     // accept this message as a possibility.
00213     if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
00214       return true;
00215 
00216     // If the message interface is a subclass of the original interface, accept
00217     // the message unless there is a subclass in the hierarchy that will
00218     // "steal" the message (thus the message "will go" to the subclass and not
00219     /// the original interface).
00220     if (IFace) {
00221       Selector Sel = Msg->getSelector();
00222       for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
00223         if (declaresSameEntity(Cls, IFace))
00224           return true;
00225         if (Cls->getMethod(Sel, IsInstanceMethod))
00226           return false;
00227       }
00228     }
00229 
00230     // The interfaces are unrelated, don't accept the message.
00231     return false;
00232   }
00233 };
00234 
00235 //===----------------------------------------------------------------------===//
00236 // MessageAnalyzer Implementation
00237 //===----------------------------------------------------------------------===//
00238 
00239 /// \brief Accepts an ObjC message expression and finds all methods that may
00240 /// respond to it.
00241 class MessageAnalyzer : public TranslationUnitHandler {
00242   Program &Prog;
00243   TULocationHandler &TULocHandler;
00244 
00245   // The ObjCInterface associated with the message. Can be null/invalid.
00246   Entity MsgIFaceEnt;
00247   GlobalSelector GlobSel;
00248   bool CanBeInstanceMethod;
00249   bool CanBeClassMethod;
00250 
00251   /// \brief Super classes of the ObjCInterface.
00252   typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
00253   EntitiesSetTy HierarchyEntities;
00254 
00255   /// \brief The interface in the message interface hierarchy that "intercepts"
00256   /// the selector.
00257   Entity ReceiverIFaceEnt;
00258 
00259 public:
00260   MessageAnalyzer(ObjCMessageExpr *Msg,
00261                   Program &prog, TULocationHandler &handler)
00262     : Prog(prog), TULocHandler(handler),
00263       CanBeInstanceMethod(false),
00264       CanBeClassMethod(false) {
00265 
00266     assert(Msg);
00267 
00268     ObjCInterfaceDecl *MsgD = 0;
00269 
00270     while (true) {
00271       switch (Msg->getReceiverKind()) {
00272       case ObjCMessageExpr::Instance: {
00273         const ObjCObjectPointerType *OPT =
00274           Msg->getInstanceReceiver()->getType()
00275                                       ->getAsObjCInterfacePointerType();
00276 
00277         if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
00278           CanBeInstanceMethod = CanBeClassMethod = true;
00279           break;
00280         }
00281 
00282         if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
00283           CanBeClassMethod = true;
00284           break;
00285         }
00286 
00287         MsgD = OPT->getInterfaceDecl();
00288         assert(MsgD);
00289         CanBeInstanceMethod = true;
00290         break;
00291       }
00292         
00293       case ObjCMessageExpr::Class:
00294         CanBeClassMethod = true;
00295         MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
00296         break;
00297 
00298       case ObjCMessageExpr::SuperClass:
00299         CanBeClassMethod = true;
00300         MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
00301         break;
00302 
00303       case ObjCMessageExpr::SuperInstance:
00304         CanBeInstanceMethod = true;
00305         MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
00306                                                            ->getInterfaceDecl();
00307         break;
00308       }
00309     }
00310 
00311     assert(CanBeInstanceMethod || CanBeClassMethod);
00312 
00313     Selector sel = Msg->getSelector();
00314     assert(!sel.isNull());
00315 
00316     MsgIFaceEnt = Entity::get(MsgD, Prog);
00317     GlobSel = GlobalSelector::get(sel, Prog);
00318 
00319     if (MsgD) {
00320       for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
00321              Cls; Cls = Cls->getSuperClass())
00322         HierarchyEntities.insert(Entity::get(Cls, Prog));
00323 
00324       // Find the interface in the hierarchy that "receives" the message.
00325       for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
00326         bool isReceiver = false;
00327 
00328         ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
00329         for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
00330                Meth != MethEnd; ++Meth) {
00331           if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
00332             if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
00333                 (MD->isClassMethod()    && CanBeClassMethod)) {
00334               isReceiver = true;
00335               break;
00336             }
00337         }
00338 
00339         if (isReceiver) {
00340           ReceiverIFaceEnt = Entity::get(Cls, Prog);
00341           break;
00342         }
00343       }
00344     }
00345   }
00346 
00347   virtual void Handle(TranslationUnit *TU) {
00348     assert(TU && "Passed null translation unit");
00349     ASTContext &Ctx = TU->getASTContext();
00350 
00351     // Null means it doesn't exist in this translation unit or there was no
00352     // interface that was determined to receive the original message.
00353     ObjCInterfaceDecl *ReceiverIFace =
00354         cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
00355 
00356     // No subclass for the original receiver interface, so it remains the
00357     // receiver.
00358     if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
00359       return;
00360 
00361     // Null means it doesn't exist in this translation unit or there was no
00362     // interface associated with the message in the first place.
00363     ObjCInterfaceDecl *MsgIFace =
00364         cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
00365 
00366     Selector Sel = GlobSel.getSelector(Ctx);
00367     SelectorMap &SelMap = TU->getSelectorMap();
00368     for (SelectorMap::method_iterator
00369            I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
00370            I != E; ++I) {
00371       ObjCMethodDecl *D = *I;
00372       if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
00373         for (ObjCMethodDecl::redecl_iterator
00374                RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
00375           TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
00376       }
00377     }
00378   }
00379 
00380   /// \brief Determines whether the given method is likely to accept the
00381   /// original message.
00382   ///
00383   /// It returns true "eagerly", meaning it will return false only if it can
00384   /// "prove" statically that the method cannot accept the original message.
00385   bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
00386                    ObjCInterfaceDecl *ReceiverIFace) {
00387     assert(D);
00388 
00389     // FIXME: Protocol methods ?
00390     if (isa<ObjCProtocolDecl>(D->getDeclContext()))
00391       return false;
00392 
00393     // No specific interface associated with the message. Can be anything.
00394     if (MsgIFaceEnt.isInvalid())
00395       return true;
00396 
00397     if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
00398         (!CanBeClassMethod    && D->isClassMethod()))
00399       return false;
00400 
00401     ObjCInterfaceDecl *IFace = D->getClassInterface();
00402     assert(IFace);
00403 
00404     // If the original message interface is the same or a superclass of the
00405     // given interface, accept the method as a possibility.
00406     if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
00407       return true;
00408 
00409     if (ReceiverIFace) {
00410       // The given interface, "overrides" the receiver.
00411       if (ReceiverIFace->isSuperClassOf(IFace))
00412         return true;
00413     } else {
00414       // No receiver was found for the original message.
00415       assert(ReceiverIFaceEnt.isInvalid());
00416 
00417       // If the original message interface is a subclass of the given interface,
00418       // accept the message.
00419       if (HierarchyEntities.count(Entity::get(IFace, Prog)))
00420         return true;
00421     }
00422 
00423     // The interfaces are unrelated, or the receiver interface wasn't
00424     // "overriden".
00425     return false;
00426   }
00427 };
00428 
00429 } // end anonymous namespace
00430 
00431 //===----------------------------------------------------------------------===//
00432 // Analyzer Implementation
00433 //===----------------------------------------------------------------------===//
00434 
00435 void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
00436   assert(D && "Passed null declaration");
00437   Entity Ent = Entity::get(D, Prog);
00438   if (Ent.isInvalid())
00439     return;
00440 
00441   DeclEntityAnalyzer DEA(Ent, Handler);
00442   Idxer.GetTranslationUnitsFor(Ent, DEA);
00443 }
00444 
00445 void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
00446   assert(D && "Passed null declaration");
00447   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
00448     RefSelectorAnalyzer RSA(MD, Prog, Handler);
00449     GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
00450     Idxer.GetTranslationUnitsFor(Sel, RSA);
00451     return;
00452   }
00453 
00454   Entity Ent = Entity::get(D, Prog);
00455   if (Ent.isInvalid())
00456     return;
00457 
00458   RefEntityAnalyzer REA(Ent, Handler);
00459   Idxer.GetTranslationUnitsFor(Ent, REA);
00460 }
00461 
00462 /// \brief Find methods that may respond to the given message and pass them
00463 /// to Handler.
00464 void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
00465                                TULocationHandler &Handler) {
00466   assert(Msg);
00467   MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
00468   GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
00469   Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
00470 }