/// getFirstClassExtension - Find first class extension of the given class. ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const { for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl; CDecl = CDecl->getNextClassCategory()) if (CDecl->IsClassExtension()) return CDecl; return 0; }
ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { for (ObjCCategoryDecl *Category = getCategoryList(); Category; Category = Category->getNextClassCategory()) if (ObjCCategoryImplDecl *Impl = Category->getImplementation()) if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) return MD; return 0; }
static void CollectOverriddenMethods(CXTranslationUnit TU, DeclContext *Ctx, ObjCMethodDecl *Method, SmallVectorImpl<CXCursor> &Methods) { if (!Ctx) return; // If we have a class or category implementation, jump straight to the // interface. if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx)) return CollectOverriddenMethods(TU, Impl->getClassInterface(), Method, Methods); ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); if (!Container) return; // Check whether we have a matching method at this level. if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(), Method->isInstanceMethod())) if (Method != Overridden) { // We found an override at this level; there is no need to look // into other protocols or categories. Methods.push_back(MakeCXCursor(Overridden, TU)); return; } if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), PEnd = Protocol->protocol_end(); P != PEnd; ++P) CollectOverriddenMethods(TU, *P, Method, Methods); } if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), PEnd = Category->protocol_end(); P != PEnd; ++P) CollectOverriddenMethods(TU, *P, Method, Methods); } if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), PEnd = Interface->protocol_end(); P != PEnd; ++P) CollectOverriddenMethods(TU, *P, Method, Methods); for (ObjCCategoryDecl *Category = Interface->getCategoryList(); Category; Category = Category->getNextClassCategory()) CollectOverriddenMethods(TU, Category, Method, Methods); // We only look into the superclass if we haven't found anything yet. if (Methods.empty()) if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) return CollectOverriddenMethods(TU, Super, Method, Methods); } }
/// FindCategoryDeclaration - Finds category declaration in the list of /// categories for this class and returns it. Name of the category is passed /// in 'CategoryId'. If category not found, return 0; /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { if (ExternallyCompleted) LoadExternalDefinition(); for (ObjCCategoryDecl *Category = getCategoryList(); Category; Category = Category->getNextClassCategory()) if (Category->getIdentifier() == CategoryId) return Category; return 0; }
/// FindPropertyDeclaration - Finds declaration of the property given its name /// in 'PropertyId' and returns it. It returns 0, if not found. ObjCPropertyDecl * ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) return PD; switch (getKind()) { default: break; case Decl::ObjCProtocol: { const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this); for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(), E = PID->protocol_end(); I != E; ++I) if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; break; } case Decl::ObjCInterface: { const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this); // Look through categories. for (ObjCCategoryDecl *Cat = OID->getCategoryList(); Cat; Cat = Cat->getNextClassCategory()) if (!Cat->IsClassExtension()) if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) return P; // Look through protocols. for (ObjCInterfaceDecl::all_protocol_iterator I = OID->all_referenced_protocol_begin(), E = OID->all_referenced_protocol_end(); I != E; ++I) if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; // Finally, check the super class. if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) return superClass->FindPropertyDeclaration(PropertyId); break; } case Decl::ObjCCategory: { const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this); // Look through protocols. if (!OCD->IsClassExtension()) for (ObjCCategoryDecl::protocol_iterator I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I) if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; break; } } return 0; }
void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: GenObjCClass(D->getName()); break; case Decl::ObjCCategory: { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } // Specially handle class extensions, which are anonymous categories. // We want to mangle in the location to uniquely distinguish them. if (CD->IsClassExtension()) { Out << "objc(ext)" << ID->getName() << '@'; GenLoc(CD); } else GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCCategoryImpl: { ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCProtocol: GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); break; } }
/// FindCategoryDeclaration - Finds category declaration in the list of /// categories for this class and returns it. Name of the category is passed /// in 'CategoryId'. If category not found, return 0; /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; if (data().ExternallyCompleted) LoadExternalDefinition(); for (ObjCCategoryDecl *Category = getCategoryList(); Category; Category = Category->getNextClassCategory()) if (Category->getIdentifier() == CategoryId) return Category; return 0; }
/// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, bool isInstance, bool shallowCategoryLookup) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; const ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; if (data().ExternallyCompleted) LoadExternalDefinition(); while (ClassDecl != NULL) { if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - look through protocols. for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(), E = ClassDecl->protocol_end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) return MethodDecl; if (!shallowCategoryLookup) { // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; } CatDecl = CatDecl->getNextClassCategory(); } ClassDecl = ClassDecl->getSuperClass(); } return NULL; }
void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: assert(false && "Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: GenObjCClass(D->getName()); break; case Decl::ObjCCategory: { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCCategoryImpl: { ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCProtocol: GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); break; } }
/// ClassImplementsProtocol - Checks that 'lProto' protocol /// has been implemented in IDecl class, its super class or categories (if /// lookupCategory is true). bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, bool lookupCategory, bool RHSIsQualifiedID) { ObjCInterfaceDecl *IDecl = this; // 1st, look up the class. const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(), E = Protocols.end(); PI != E; ++PI) { if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) return true; // This is dubious and is added to be compatible with gcc. In gcc, it is // also allowed assigning a protocol-qualified 'id' type to a LHS object // when protocol in qualified LHS is in list of protocols in the rhs 'id' // object. This IMO, should be a bug. // FIXME: Treat this as an extension, and flag this as an error when GCC // extensions are not enabled. if (RHSIsQualifiedID && getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto)) return true; } // 2nd, look up the category. if (lookupCategory) for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; CDecl = CDecl->getNextClassCategory()) { for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), E = CDecl->protocol_end(); PI != E; ++PI) if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) return true; } // 3rd, look up the super class(s) if (IDecl->getSuperClass()) return IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory, RHSIsQualifiedID); return false; }
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) { if (DC) { // Ivar's can only appear in interfaces, implementations (via synthesized // properties), and class extensions (via direct declaration, or synthesized // properties). // // FIXME: This should really be asserting this: // (isa<ObjCCategoryDecl>(DC) && // cast<ObjCCategoryDecl>(DC)->IsClassExtension())) // but unfortunately we sometimes place ivars into non-class extension // categories on error. This breaks an AST invariant, and should not be // fixed. assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || isa<ObjCCategoryDecl>(DC)) && "Invalid ivar decl context!"); // Once a new ivar is created in any of class/class-extension/implementation // decl contexts, the previously built IvarList must be rebuilt. ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC); if (!ID) { if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) { ID = IM->getClassInterface(); if (BW) IM->setHasSynthBitfield(true); } else { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC); ID = CD->getClassInterface(); if (BW) CD->setHasSynthBitfield(true); } } ID->setIvarList(0); } return new (C) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, synthesized); }
/// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, bool isInstance) const { const ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; if (ExternallyCompleted) LoadExternalDefinition(); while (ClassDecl != NULL) { if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = ClassDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; CatDecl = CatDecl->getNextClassCategory(); } ClassDecl = ClassDecl->getSuperClass(); } return NULL; }