The inference of _Nullable for weak Objective-C properties was broken
in several ways:
* It was back-patching the type information very late in the process
of checking the attributes for an Objective-C property, which is
just wrong.
* It was using ad hoc checks to try to suppress the warning about
missing nullability specifiers (-Wnullability-completeness), which
didn't actual work in all cases (rdar://problem/
22985457)
* It was inferring _Nullable even outside of assumes-nonnull regions,
which is wrong.
Putting the inference of _Nullable for weak Objective-C properties in
the same place as all of the other inference logic fixes all of these
ills.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249896
91177308-0d34-0410-b5e6-
96231b3b80d8
}
// Validate the attributes on the @property.
- CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
+ CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
(isa<ObjCInterfaceDecl>(ClassDecl) ||
isa<ObjCProtocolDecl>(ClassDecl)));
if (*nullability == NullabilityKind::NonNull)
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
<< "nonnull" << "weak";
- } else {
- PropertyTy =
- Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable),
- PropertyTy, PropertyTy);
- TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo();
- PropertyDecl->setType(PropertyTy, TSInfo);
}
}
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
- if (S.PP.getPragmaAssumeNonNullLoc().isValid() &&
- !state.getDeclarator().isObjCWeakProperty() &&
- !S.deduceWeakPropertyFromType(T)) {
+ if (S.PP.getPragmaAssumeNonNullLoc().isValid()) {
inAssumeNonNullRegion = true;
// Determine which file we saw the assume-nonnull region in.
FileID file = getNullabilityCompletenessCheckFileID(
complainAboutMissingNullability = CAMN_No;
break;
}
+
+ // Weak properties are inferred to be nullable.
+ if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
+ inferNullability = NullabilityKind::Nullable;
+ break;
+ }
+
// fallthrough
case Declarator::FileContext:
@interface I
{
}
-@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
+@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}
@end
@implementation I // expected-note {{when implemented by class I}}
// rdar://13676793
@protocol MyProtocol
-@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
+@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}
@end
@interface I1 <MyProtocol>
@end
@interface Super
-@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
+@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}
@end
@property(weak) NSFoo *property1;
@end
+#pragma clang assume_nonnull begin
+@interface NSBar ()
+@property(weak) NSFoo *property2;
+@end
+
+#pragma clang assume_nonnull end
+
@implementation NSBar
- (void) Meth {
- foo (self.property1); // expected-warning {{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ foo (self.property1); // no warning because nothing is inferred
+ foo (self.property2); // expected-warning {{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
}
@end
@property (retain,nullable) SomeClass *property2;
- (nullable SomeClass *)method1;
- (void)method2:(nonnull SomeClass *)param;
+@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
+@end
+
+@interface SomeClass ()
+@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
@end
extern void **blah; // expected-warning 2{{missing a nullability type specifier}}
+__attribute__((objc_root_class))
+@interface ClassWithWeakProperties
+@property (readonly, weak) ClassWithWeakProperties *prop1;
+@property (readonly, weak, null_unspecified) ClassWithWeakProperties *prop2;
+@end
+
+@interface ClassWithWeakProperties ()
+@property (readonly, weak) ClassWithWeakProperties *prop3;
+@end
+
#pragma clang assume_nonnull end