clang API Documentation
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 }