summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaObjCProperty.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2015-06-19 18:14:46 +0000
committerDouglas Gregor <dgregor@apple.com>2015-06-19 18:14:46 +0000
commit849ebc269fe17def169c812f929746cb98955664 (patch)
tree5866b34d318c220f0fb7b078164e0710e72f7ea8 /clang/lib/Sema/SemaObjCProperty.cpp
parent813a066f16df52783708fdc2ef708bb76a9ff521 (diff)
downloadbcm5719-llvm-849ebc269fe17def169c812f929746cb98955664.tar.gz
bcm5719-llvm-849ebc269fe17def169c812f929746cb98955664.zip
Implement the 'null_resettable' attribute for Objective-C properties.
'null_resettable' properties are those whose getters return nonnull but whose setters take nil, to "reset" the property to some default. Implements rdar://problem/19051334. llvm-svn: 240155
Diffstat (limited to 'clang/lib/Sema/SemaObjCProperty.cpp')
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp62
1 files changed, 60 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index f62af8eb81d..d8e7f64836f 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -361,6 +361,9 @@ Sema::HandlePropertyInClassExtension(Scope *S,
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+ if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
+
// Set setter/getter selector name. Needed later.
PDecl->setGetterName(GetterSel);
PDecl->setSetterName(SetterSel);
@@ -646,6 +649,9 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+ if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
+
return PDecl;
}
@@ -1760,6 +1766,33 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
}
+void Sema::diagnoseNullResettableSynthesizedSetters(ObjCImplDecl *impDecl) {
+ for (const auto *propertyImpl : impDecl->property_impls()) {
+ const auto *property = propertyImpl->getPropertyDecl();
+
+ // Warn about null_resettable properties with synthesized setters,
+ // because the setter won't properly handle nil.
+ if (propertyImpl->getPropertyImplementation()
+ == ObjCPropertyImplDecl::Synthesize &&
+ (property->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_null_resettable) &&
+ property->getGetterMethodDecl() &&
+ property->getSetterMethodDecl()) {
+ auto *getterMethod = property->getGetterMethodDecl();
+ auto *setterMethod = property->getSetterMethodDecl();
+ if (!impDecl->getInstanceMethod(setterMethod->getSelector()) &&
+ !impDecl->getInstanceMethod(getterMethod->getSelector())) {
+ SourceLocation loc = propertyImpl->getLocation();
+ if (loc.isInvalid())
+ loc = impDecl->getLocStart();
+
+ Diag(loc, diag::warn_null_resettable_setter)
+ << setterMethod->getSelector() << property->getDeclName();
+ }
+ }
+ }
+}
+
void
Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl) {
@@ -1995,9 +2028,21 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
redeclaredProperty->getLocation() :
property->getLocation();
+ // 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;
+ if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
+ if (*nullability == NullabilityKind::Unspecified)
+ resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
+ modifiedTy, modifiedTy);
+ }
+ }
+
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
property->getGetterName(),
- property->getType(), nullptr, CD,
+ resultTy, nullptr, CD,
/*isInstance=*/true, /*isVariadic=*/false,
/*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
@@ -2058,12 +2103,25 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
+ // 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;
+ if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
+ if (*nullability == NullabilityKind::Unspecified)
+ paramTy = Context.getAttributedType(AttributedType::attr_nullable,
+ modifiedTy, modifiedTy);
+ }
+ }
+
// Invent the arguments for the setter. We don't bother making a
// nice name for the argument.
ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
Loc, Loc,
property->getIdentifier(),
- property->getType().getUnqualifiedType(),
+ paramTy,
/*TInfo=*/nullptr,
SC_None,
nullptr);
OpenPOWER on IntegriCloud