diff options
Diffstat (limited to 'lib/AST/DeclObjC.cpp')
-rw-r--r-- | lib/AST/DeclObjC.cpp | 115 |
1 files changed, 85 insertions, 30 deletions
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 050a0f53f1e5..d2701211beae 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -152,7 +152,8 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod( ObjCPropertyDecl * ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID) { + const IdentifierInfo *propertyID, + ObjCPropertyQueryKind queryKind) { // If this context is a hidden protocol definition, don't find any // property. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { @@ -166,15 +167,33 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { for (const auto *Ext : IDecl->known_extensions()) if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, - propertyID)) + propertyID, + queryKind)) return PD; } DeclContext::lookup_result R = DC->lookup(propertyID); + ObjCPropertyDecl *classProp = nullptr; for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) - if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) - return PD; + if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) { + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PD->isClassProperty())) + return PD; + + if (PD->isClassProperty()) + classProp = PD; + } + + if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return classProp; return nullptr; } @@ -192,7 +211,8 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { /// FindPropertyDeclaration - Finds declaration of the property given its name /// in 'PropertyId' and returns it. It returns 0, if not found. ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( - const IdentifierInfo *PropertyId) const { + const IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // Don't find properties within hidden protocol definitions. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) @@ -204,13 +224,14 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // the class itself. if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) { for (const auto *Ext : ClassDecl->visible_extensions()) { - if (auto *P = Ext->FindPropertyDeclaration(PropertyId)) + if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind)) return P; } } if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, + QueryKind)) return PD; switch (getKind()) { @@ -219,7 +240,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( case Decl::ObjCProtocol: { const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this); for (const auto *I : PID->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -228,18 +250,20 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // Look through categories (but not extensions; they were handled above). for (const auto *Cat : OID->visible_categories()) { if (!Cat->IsClassExtension()) - if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration( + PropertyId, QueryKind)) return P; } // Look through protocols. for (const auto *I : OID->all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; // Finally, check the super class. if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) - return superClass->FindPropertyDeclaration(PropertyId); + return superClass->FindPropertyDeclaration(PropertyId, QueryKind); break; } case Decl::ObjCCategory: { @@ -247,7 +271,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // Look through protocols. if (!OCD->IsClassExtension()) for (const auto *I : OCD->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -319,7 +344,8 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { /// ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( - IdentifierInfo *PropertyId) const { + IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return nullptr; @@ -328,12 +354,14 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( LoadExternalDefinition(); if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, + QueryKind)) return PD; // Look through protocols. for (const auto *I : all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; return nullptr; @@ -342,13 +370,13 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const { for (auto *Prop : properties()) { - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; PO.push_back(Prop); } for (const auto *Ext : known_extensions()) { const ObjCCategoryDecl *ClassExt = Ext; for (auto *Prop : ClassExt->properties()) { - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; PO.push_back(Prop); } } @@ -1206,23 +1234,29 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (NumArgs > 1) return nullptr; - if (!isInstanceMethod()) - return nullptr; - if (isPropertyAccessor()) { const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent()); bool IsGetter = (NumArgs == 0); + bool IsInstance = isInstanceMethod(); /// Local function that attempts to find a matching property within the /// given Objective-C container. auto findMatchingProperty = [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * { - - for (const auto *I : Container->properties()) { - Selector NextSel = IsGetter ? I->getGetterName() - : I->getSetterName(); - if (NextSel == Sel) - return I; + if (IsInstance) { + for (const auto *I : Container->instance_properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); + if (NextSel == Sel) + return I; + } + } else { + for (const auto *I : Container->class_properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); + if (NextSel == Sel) + return I; + } } return nullptr; @@ -1822,7 +1856,9 @@ void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, if (const ObjCProtocolDecl *PDecl = getDefinition()) { for (auto *Prop : PDecl->properties()) { // Insert into PM if not there already. - PM.insert(std::make_pair(Prop->getIdentifier(), Prop)); + PM.insert(std::make_pair( + std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), + Prop)); PO.push_back(Prop); } // Scan through protocol's protocols. @@ -2011,10 +2047,29 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { /// category \@implementation block. /// ObjCPropertyImplDecl *ObjCImplDecl:: -FindPropertyImplDecl(IdentifierInfo *Id) const { +FindPropertyImplDecl(IdentifierInfo *Id, + ObjCPropertyQueryKind QueryKind) const { + ObjCPropertyImplDecl *ClassPropImpl = nullptr; for (auto *PID : property_impls()) - if (PID->getPropertyDecl()->getIdentifier() == Id) - return PID; + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if (PID->getPropertyDecl()->getIdentifier() == Id) { + if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PID->getPropertyDecl()->isClassProperty())) + return PID; + + if (PID->getPropertyDecl()->isClassProperty()) + ClassPropImpl = PID; + } + + if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return ClassPropImpl; + return nullptr; } |