Fix inference of _Nullable for weak Objective-C properties.

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.

llvm-svn: 249896
This commit is contained in:
Douglas Gregor 2015-10-09 20:36:17 +00:00
parent 6ccc8ca6d9
commit d4f2afa23c
6 changed files with 36 additions and 15 deletions

View File

@ -181,7 +181,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
}
// Validate the attributes on the @property.
CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
(isa<ObjCInterfaceDecl>(ClassDecl) ||
isa<ObjCProtocolDecl>(ClassDecl)));
@ -2301,13 +2301,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
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);
}
}

View File

@ -3311,9 +3311,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// 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(
@ -3392,6 +3390,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
complainAboutMissingNullability = CAMN_No;
break;
}
// Weak properties are inferred to be nullable.
if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
inferNullability = NullabilityKind::Nullable;
break;
}
// fallthrough
case Declarator::FileContext:

View File

@ -56,7 +56,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
@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}}
@ -65,7 +65,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
// 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>
@ -76,7 +76,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
@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

View File

@ -11,8 +11,16 @@ void foo (NSFoo * _Nonnull);
@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

View File

@ -13,4 +13,9 @@ void g3(const
@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

View File

@ -4,5 +4,15 @@ int *ptr; // expected-warning {{missing a nullability type specifier}}
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