diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp | 316 |
1 files changed, 200 insertions, 116 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index 1cb84e44806..5e38751f44a 100644 --- a/gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -303,6 +303,8 @@ makePropertyAttributesAsWritten(unsigned Attributes) { attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; if (Attributes & ObjCDeclSpec::DQ_PR_atomic) attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; + if (Attributes & ObjCDeclSpec::DQ_PR_class) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_class; return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; } @@ -334,7 +336,6 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName, } } while (Tok.isNot(tok::r_paren)); return false; - } /// Check for a mismatch in the atomicity of the given properties. @@ -431,10 +432,13 @@ Sema::HandlePropertyInClassExtension(Scope *S, return nullptr; } + bool isClassProperty = (AttributesAsWritten & ObjCDeclSpec::DQ_PR_class) || + (Attributes & ObjCDeclSpec::DQ_PR_class); + // Find the property in the extended class's primary class or // extensions. - ObjCPropertyDecl *PIDecl = - CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); + ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass( + PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty)); // If we found a property in an extension, complain. if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) { @@ -612,8 +616,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PropertyId, AtLoc, LParenLoc, T, TInfo); - if (ObjCPropertyDecl *prevDecl = - ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { + bool isClassProperty = (AttributesAsWritten & ObjCDeclSpec::DQ_PR_class) || + (Attributes & ObjCDeclSpec::DQ_PR_class); + // Class property and instance property can have the same name. + if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl( + DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) { Diag(PDecl->getLocation(), diag::err_duplicate_property); Diag(prevDecl->getLocation(), diag::note_property_declare); PDecl->setInvalidDecl(); @@ -691,6 +698,9 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable); + if (Attributes & ObjCDeclSpec::DQ_PR_class) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class); + return PDecl; } @@ -794,7 +804,6 @@ static void setImpliedPropertyAttributeForReadOnlyProperty( property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); else if (ivarLifetime == Qualifiers::OCL_Weak) property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); - return; } /// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared @@ -847,7 +856,8 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, } /// Determine whether any storage attributes were written on the property. -static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) { +static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop, + ObjCPropertyQueryKind QueryKind) { if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true; // If this is a readwrite property in a class extension that refines @@ -870,8 +880,8 @@ static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) { // Look through all of the protocols. for (const auto *Proto : OrigClass->all_referenced_protocols()) { - if (ObjCPropertyDecl *OrigProp = - Proto->FindPropertyDeclaration(Prop->getIdentifier())) + if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration( + Prop->getIdentifier(), QueryKind)) return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; } @@ -888,7 +898,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, bool Synthesize, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc) { + SourceLocation PropertyIvarLoc, + ObjCPropertyQueryKind QueryKind) { ObjCContainerDecl *ClassImpDecl = dyn_cast<ObjCContainerDecl>(CurContext); // Make sure we have a context for the property implementation declaration. @@ -915,11 +926,15 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, "ActOnPropertyImplDecl - @implementation without @interface"); // Look for this property declaration in the @implementation's @interface - property = IDecl->FindPropertyDeclaration(PropertyId); + property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind); if (!property) { Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); return nullptr; } + if (property->isClassProperty() && Synthesize) { + Diag(PropertyLoc, diag::error_synthesize_on_class_property) << PropertyId; + return nullptr; + } unsigned PIkind = property->getPropertyAttributesAsWritten(); if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { @@ -993,7 +1008,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (!Category) return nullptr; // Look for this property declaration in @implementation's category - property = Category->FindPropertyDeclaration(PropertyId); + property = Category->FindPropertyDeclaration(PropertyId, QueryKind); if (!property) { Diag(PropertyLoc, diag::error_bad_category_property_decl) << Category->getDeclName(); @@ -1105,7 +1120,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // It's an error if we have to do this and the user didn't // explicitly write an ownership attribute on the property. - if (!hasWrittenStorageAttribute(property) && + if (!hasWrittenStorageAttribute(property, QueryKind) && !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { Diag(PropertyDiagLoc, diag::err_arc_objc_property_default_assign_on_object); @@ -1340,7 +1355,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (ObjCPropertyImplDecl *PPIDecl - = IC->FindPropertyImplDecl(PropertyId)) { + = IC->FindPropertyImplDecl(PropertyId, QueryKind)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return nullptr; @@ -1379,7 +1394,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (ObjCPropertyImplDecl *PPIDecl = - CatImplClass->FindPropertyImplDecl(PropertyId)) { + CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) { Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return nullptr; @@ -1478,24 +1493,26 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, if (!GetterMethod) return false; QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); - QualType PropertyIvarType = property->getType().getNonReferenceType(); - bool compat = Context.hasSameType(PropertyIvarType, GetterType); + QualType PropertyRValueType = + property->getType().getNonReferenceType().getAtomicUnqualifiedType(); + bool compat = Context.hasSameType(PropertyRValueType, GetterType); if (!compat) { const ObjCObjectPointerType *propertyObjCPtr = nullptr; const ObjCObjectPointerType *getterObjCPtr = nullptr; - if ((propertyObjCPtr = PropertyIvarType->getAs<ObjCObjectPointerType>()) && + if ((propertyObjCPtr = + PropertyRValueType->getAs<ObjCObjectPointerType>()) && (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>())) compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr); - else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) + else if (CheckAssignmentConstraints(Loc, GetterType, PropertyRValueType) != Compatible) { Diag(Loc, diag::error_property_accessor_type) - << property->getDeclName() << PropertyIvarType + << property->getDeclName() << PropertyRValueType << GetterMethod->getSelector() << GetterType; Diag(GetterMethod->getLocation(), diag::note_declared_at); return true; } else { compat = true; - QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType lhsType = Context.getCanonicalType(PropertyRValueType); QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); if (lhsType != rhsType && lhsType->isArithmeticType()) compat = false; @@ -1515,49 +1532,68 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those in its super class. -static void CollectImmediateProperties(ObjCContainerDecl *CDecl, - ObjCContainerDecl::PropertyMap &PropMap, - ObjCContainerDecl::PropertyMap &SuperPropMap, - bool IncludeProtocols = true) { - +static void +CollectImmediateProperties(ObjCContainerDecl *CDecl, + ObjCContainerDecl::PropertyMap &PropMap, + ObjCContainerDecl::PropertyMap &SuperPropMap, + bool CollectClassPropsOnly = false, + bool IncludeProtocols = true) { if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { - for (auto *Prop : IDecl->properties()) - PropMap[Prop->getIdentifier()] = Prop; + for (auto *Prop : IDecl->properties()) { + if (CollectClassPropsOnly && !Prop->isClassProperty()) + continue; + PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = + Prop; + } // Collect the properties from visible extensions. for (auto *Ext : IDecl->visible_extensions()) - CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols); + CollectImmediateProperties(Ext, PropMap, SuperPropMap, + CollectClassPropsOnly, IncludeProtocols); if (IncludeProtocols) { // Scan through class's protocols. for (auto *PI : IDecl->all_referenced_protocols()) - CollectImmediateProperties(PI, PropMap, SuperPropMap); + CollectImmediateProperties(PI, PropMap, SuperPropMap, + CollectClassPropsOnly); } } if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { - for (auto *Prop : CATDecl->properties()) - PropMap[Prop->getIdentifier()] = Prop; + for (auto *Prop : CATDecl->properties()) { + if (CollectClassPropsOnly && !Prop->isClassProperty()) + continue; + PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = + Prop; + } if (IncludeProtocols) { // Scan through class's protocols. for (auto *PI : CATDecl->protocols()) - CollectImmediateProperties(PI, PropMap, SuperPropMap); + CollectImmediateProperties(PI, PropMap, SuperPropMap, + CollectClassPropsOnly); } } else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { for (auto *Prop : PDecl->properties()) { - ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; + if (CollectClassPropsOnly && !Prop->isClassProperty()) + continue; + ObjCPropertyDecl *PropertyFromSuper = + SuperPropMap[std::make_pair(Prop->getIdentifier(), + Prop->isClassProperty())]; // Exclude property for protocols which conform to class's super-class, // as super-class has to implement the property. if (!PropertyFromSuper || PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) { - ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; + ObjCPropertyDecl *&PropEntry = + PropMap[std::make_pair(Prop->getIdentifier(), + Prop->isClassProperty())]; if (!PropEntry) PropEntry = Prop; } } - // scan through protocol's protocols. + // Scan through protocol's protocols. for (auto *PI : PDecl->protocols()) - CollectImmediateProperties(PI, PropMap, SuperPropMap); + CollectImmediateProperties(PI, PropMap, SuperPropMap, + CollectClassPropsOnly); } } @@ -1590,7 +1626,7 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, // look up a property declaration whose one of its accessors is implemented // by this method. - for (const auto *Property : IFace->properties()) { + for (const auto *Property : IFace->instance_properties()) { if ((Property->getGetterName() == IMD->getSelector() || Property->getSetterName() == IMD->getSelector()) && (Property->getPropertyIvarDecl() == IV)) @@ -1599,7 +1635,7 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, // Also look up property declaration in class extension whose one of its // accessors is implemented by this method. for (const auto *Ext : IFace->known_extensions()) - for (const auto *Property : Ext->properties()) + for (const auto *Property : Ext->instance_properties()) if ((Property->getGetterName() == IMD->getSelector() || Property->getSetterName() == IMD->getSelector()) && (Property->getPropertyIvarDecl() == IV)) @@ -1632,7 +1668,6 @@ static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, /// in class's \@implementation. void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl) { - ObjCInterfaceDecl::PropertyMap PropMap; ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder; IDecl->collectPropertiesToImplement(PropMap, PropertyOrder); @@ -1645,10 +1680,12 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCPropertyDecl *Prop = PropertyOrder[i]; // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || + Prop->isClassProperty() || Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) continue; // Property may have been synthesized by user. - if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) + if (IMPDecl->FindPropertyImplDecl( + Prop->getIdentifier(), Prop->getQueryKind())) continue; if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) @@ -1664,7 +1701,9 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, Diag(PID->getLocation(), diag::note_property_synthesize); continue; } - ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; + ObjCPropertyDecl *PropInSuperClass = + SuperPropMap[std::make_pair(Prop->getIdentifier(), + Prop->isClassProperty())]; if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) { // We won't auto-synthesize properties declared in protocols. @@ -1707,7 +1746,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, true, /* property = */ Prop->getIdentifier(), /* ivar = */ Prop->getDefaultSynthIvarName(Context), - Prop->getLocation())); + Prop->getLocation(), Prop->getQueryKind())); if (PIDecl) { Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); @@ -1726,34 +1765,42 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { DefaultSynthesizeProperties(S, IC, IDecl); } -static void DiagnoseUnimplementedAccessor(Sema &S, - ObjCInterfaceDecl *PrimaryClass, - Selector Method, - ObjCImplDecl* IMPDecl, - ObjCContainerDecl *CDecl, - ObjCCategoryDecl *C, - ObjCPropertyDecl *Prop, - Sema::SelectorSet &SMap) { +static void DiagnoseUnimplementedAccessor( + Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method, + ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C, + ObjCPropertyDecl *Prop, + llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) { + // Check to see if we have a corresponding selector in SMap and with the + // right method type. + auto I = std::find_if(SMap.begin(), SMap.end(), + [&](const ObjCMethodDecl *x) { + return x->getSelector() == Method && + x->isClassMethod() == Prop->isClassProperty(); + }); // When reporting on missing property setter/getter implementation in // categories, do not report when they are declared in primary class, // class's protocol, or one of it super classes. This is because, // the class is going to implement them. - if (!SMap.count(Method) && + if (I == SMap.end() && (PrimaryClass == nullptr || - !PrimaryClass->lookupPropertyAccessor(Method, C))) { - S.Diag(IMPDecl->getLocation(), - isa<ObjCCategoryDecl>(CDecl) ? - diag::warn_setter_getter_impl_required_in_category : - diag::warn_setter_getter_impl_required) - << Prop->getDeclName() << Method; - S.Diag(Prop->getLocation(), - diag::note_property_declare); - if (S.LangOpts.ObjCDefaultSynthProperties && - S.LangOpts.ObjCRuntime.isNonFragile()) - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) - if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) - S.Diag(RID->getLocation(), diag::note_suppressed_class_declare); - } + !PrimaryClass->lookupPropertyAccessor(Method, C, + Prop->isClassProperty()))) { + unsigned diag = + isa<ObjCCategoryDecl>(CDecl) + ? (Prop->isClassProperty() + ? diag::warn_impl_required_in_category_for_class_property + : diag::warn_setter_getter_impl_required_in_category) + : (Prop->isClassProperty() + ? diag::warn_impl_required_for_class_property + : diag::warn_setter_getter_impl_required); + S.Diag(IMPDecl->getLocation(), diag) << Prop->getDeclName() << Method; + S.Diag(Prop->getLocation(), diag::note_property_declare); + if (S.LangOpts.ObjCDefaultSynthProperties && + S.LangOpts.ObjCRuntime.isNonFragile()) + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) + if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) + S.Diag(RID->getLocation(), diag::note_suppressed_class_declare); + } } void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, @@ -1762,25 +1809,27 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl::PropertyMap PropMap; ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); - if (!SynthesizeProperties) { - ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; - // Gather properties which need not be implemented in this class - // or category. - if (!IDecl) - if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { - // For categories, no need to implement properties declared in - // its primary class (and its super classes) if property is - // declared in one of those containers. - if ((IDecl = C->getClassInterface())) { - ObjCInterfaceDecl::PropertyDeclOrder PO; - IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); - } + // Since we don't synthesize class properties, we should emit diagnose even + // if SynthesizeProperties is true. + ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; + // Gather properties which need not be implemented in this class + // or category. + if (!IDecl) + if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { + // For categories, no need to implement properties declared in + // its primary class (and its super classes) if property is + // declared in one of those containers. + if ((IDecl = C->getClassInterface())) { + ObjCInterfaceDecl::PropertyDeclOrder PO; + IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); } - if (IDecl) - CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); + } + if (IDecl) + CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); - CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap); - } + // When SynthesizeProperties is true, we only check class properties. + CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap, + SynthesizeProperties/*CollectClassPropsOnly*/); // Scan the @interface to see if any of the protocols it adopts // require an explicit implementation, via attribute @@ -1802,14 +1851,17 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; LazyMap.reset(new ObjCContainerDecl::PropertyMap()); CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap, + /* CollectClassPropsOnly */ false, /* IncludeProtocols */ false); } // Add the properties of 'PDecl' to the list of properties that // need to be implemented. for (auto *PropDecl : PDecl->properties()) { - if ((*LazyMap)[PropDecl->getIdentifier()]) + if ((*LazyMap)[std::make_pair(PropDecl->getIdentifier(), + PropDecl->isClassProperty())]) continue; - PropMap[PropDecl->getIdentifier()] = PropDecl; + PropMap[std::make_pair(PropDecl->getIdentifier(), + PropDecl->isClassProperty())] = PropDecl; } } } @@ -1821,10 +1873,10 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, for (const auto *I : IMPDecl->property_impls()) PropImplMap.insert(I->getPropertyDecl()); - SelectorSet InsMap; + llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap; // Collect property accessors implemented in current implementation. - for (const auto *I : IMPDecl->instance_methods()) - InsMap.insert(I->getSelector()); + for (const auto *I : IMPDecl->methods()) + InsMap.insert(I); ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl); ObjCInterfaceDecl *PrimaryClass = nullptr; @@ -1835,14 +1887,14 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, // When reporting on missing setter/getters, do not report when // setter/getter is implemented in category's primary class // implementation. - for (const auto *I : IMP->instance_methods()) - InsMap.insert(I->getSelector()); + for (const auto *I : IMP->methods()) + InsMap.insert(I); } for (ObjCContainerDecl::PropertyMap::iterator P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { ObjCPropertyDecl *Prop = P->second; - // Is there a matching propery synthesize/dynamic? + // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || PropImplMap.count(Prop) || @@ -1894,13 +1946,13 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, return; ObjCContainerDecl::PropertyMap PM; for (auto *Prop : IDecl->properties()) - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; for (const auto *Ext : IDecl->known_extensions()) for (auto *Prop : Ext->properties()) - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; - for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end(); - I != E; ++I) { + for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end(); + I != E; ++I) { const ObjCPropertyDecl *Property = I->second; ObjCMethodDecl *GetterMethod = nullptr; ObjCMethodDecl *SetterMethod = nullptr; @@ -1911,8 +1963,12 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) && !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) { - GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); - SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + GetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getGetterName()) : + IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getSetterName()) : + IMPDecl->getInstanceMethod(Property->getSetterName()); LookedUpGetterSetter = true; if (GetterMethod) { Diag(GetterMethod->getLocation(), @@ -1932,13 +1988,17 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) continue; - if (const ObjCPropertyImplDecl *PIDecl - = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { + if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl( + Property->getIdentifier(), Property->getQueryKind())) { if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; if (!LookedUpGetterSetter) { - GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); - SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + GetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getGetterName()) : + IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getSetterName()) : + IMPDecl->getInstanceMethod(Property->getSetterName()); } if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { SourceLocation MethodLoc = @@ -1981,6 +2041,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D for (const auto *PID : D->property_impls()) { const ObjCPropertyDecl *PD = PID->getPropertyDecl(); if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && + !PD->isClassProperty() && !D->getInstanceMethod(PD->getGetterName())) { ObjCMethodDecl *method = PD->getGetterMethodDecl(); if (!method) @@ -2086,20 +2147,30 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { if (CD->isInvalidDecl()) return; - GetterMethod = CD->getInstanceMethod(property->getGetterName()); + bool IsClassProperty = property->isClassProperty(); + GetterMethod = IsClassProperty ? + CD->getClassMethod(property->getGetterName()) : + CD->getInstanceMethod(property->getGetterName()); + // if setter or getter is not found in class extension, it might be // in the primary class. if (!GetterMethod) if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) if (CatDecl->IsClassExtension()) - GetterMethod = CatDecl->getClassInterface()-> + GetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> + getClassMethod(property->getGetterName()) : + CatDecl->getClassInterface()-> getInstanceMethod(property->getGetterName()); - SetterMethod = CD->getInstanceMethod(property->getSetterName()); + SetterMethod = IsClassProperty ? + CD->getClassMethod(property->getSetterName()) : + CD->getInstanceMethod(property->getSetterName()); if (!SetterMethod) if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) if (CatDecl->IsClassExtension()) - SetterMethod = CatDecl->getClassInterface()-> + SetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> + getClassMethod(property->getSetterName()) : + CatDecl->getClassInterface()-> getInstanceMethod(property->getSetterName()); DiagnosePropertyAccessorMismatch(property, GetterMethod, property->getLocation()); @@ -2130,13 +2201,16 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { // (which is odd, but allowed). Sema should be typechecking that the // declarations jive in that situation (which it is not currently). if (!GetterMethod) { - // No instance method of same name as property getter name was found. + // No instance/class method of same name as property getter name was found. // Declare a getter method and add it to the list of methods // for this class. SourceLocation Loc = property->getLocation(); + // The getter returns the declared property type with all qualifiers + // removed. + QualType resultTy = property->getType().getAtomicUnqualifiedType(); + // If the property is null_resettable, the getter returns nonnull. - QualType resultTy = property->getType(); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_null_resettable) { QualType modifiedTy = resultTy; @@ -2150,7 +2224,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD, - /*isInstance=*/true, /*isVariadic=*/false, + !IsClassProperty, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, (property->getPropertyImplementation() == @@ -2186,7 +2260,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { if (!property->isReadOnly()) { // Find the default setter and if one not found, add one. if (!SetterMethod) { - // No instance method of same name as property setter name was found. + // No instance/class method of same name as property setter name was + // found. // Declare a setter method and add it to the list of methods // for this class. SourceLocation Loc = property->getLocation(); @@ -2194,7 +2269,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { SetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, property->getSetterName(), Context.VoidTy, - nullptr, CD, /*isInstance=*/true, + nullptr, CD, !IsClassProperty, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, @@ -2204,9 +2279,12 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { ObjCMethodDecl::Optional : ObjCMethodDecl::Required); + // Remove all qualifiers from the setter's parameter type. + QualType paramTy = + property->getType().getUnqualifiedType().getAtomicUnqualifiedType(); + // If the property is null_resettable, the setter accepts a // nullable value. - QualType paramTy = property->getType().getUnqualifiedType(); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_null_resettable) { QualType modifiedTy = paramTy; @@ -2257,10 +2335,17 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { // double bar = [foo bar]; // } // - if (GetterMethod) - AddInstanceMethodToGlobalPool(GetterMethod); - if (SetterMethod) - AddInstanceMethodToGlobalPool(SetterMethod); + if (!IsClassProperty) { + if (GetterMethod) + AddInstanceMethodToGlobalPool(GetterMethod); + if (SetterMethod) + AddInstanceMethodToGlobalPool(SetterMethod); + } else { + if (GetterMethod) + AddFactoryMethodToGlobalPool(GetterMethod); + if (SetterMethod) + AddFactoryMethodToGlobalPool(SetterMethod); + } ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD); if (!CurrentClass) { @@ -2447,5 +2532,4 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && (Attributes & ObjCDeclSpec::DQ_PR_setter)) Diag(Loc, diag::warn_objc_readonly_property_has_setter); - } |
