From d4f2afa23c8b4a26d553c5e5126351f1d7157f93 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 9 Oct 2015 20:36:17 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/SemaObjCProperty.cpp | 9 +-------- clang/lib/Sema/SemaType.cpp | 11 ++++++++--- clang/test/SemaObjC/arc-unavailable-for-weakref.m | 6 +++--- clang/test/SemaObjC/nullable-weak-property.m | 10 +++++++++- .../SemaObjCXX/Inputs/nullability-consistency-2.h | 5 +++++ .../SemaObjCXX/Inputs/nullability-consistency-6.h | 10 ++++++++++ 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 15843fde39da..374e5ccd9187 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -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(ClassDecl) || isa(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); } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 049698d38204..d1bf6cc6bb2f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -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: diff --git a/clang/test/SemaObjC/arc-unavailable-for-weakref.m b/clang/test/SemaObjC/arc-unavailable-for-weakref.m index 35d5d9830445..82748027435e 100644 --- a/clang/test/SemaObjC/arc-unavailable-for-weakref.m +++ b/clang/test/SemaObjC/arc-unavailable-for-weakref.m @@ -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 @@ -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 diff --git a/clang/test/SemaObjC/nullable-weak-property.m b/clang/test/SemaObjC/nullable-weak-property.m index faafd204675e..7de7edf1eee6 100644 --- a/clang/test/SemaObjC/nullable-weak-property.m +++ b/clang/test/SemaObjC/nullable-weak-property.m @@ -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 diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h index 4517738c552b..5203146353ea 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h @@ -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 diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h index cb712e94c661..d1764a87dc63 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h @@ -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