summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-01-14 19:55:43 +0000
committerpatrick <patrick@openbsd.org>2017-01-14 19:55:43 +0000
commitbd3306aecb3a15e8967143b8cdbbccf2b1b19b74 (patch)
tree309a8132b44564b9e634c0da6815187ce8eab27c /gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
parentkillp -a should not kill the window if only one pane. (diff)
downloadwireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.tar.xz
wireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.zip
Import LLVM 3.9.1 including clang and lld.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp316
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);
-
}