Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -3340,7 +3340,17 @@ assert(RetValExp || HasDependentReturnType); const VarDecl *NRVOCandidate = nullptr; - QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType; + QualType RetType; + if (RelatedRetType.isNull()) { + RetType = FnRetType; + // The nullability-attributes of the return-type of a function/method + // is not necessarily conforming to the nullability-attributes of + // the expression itself, so we remove the nullability-attributes. + if(const auto *AttrType = RetType->getAs()) + RetType = AttrType->desugar(); + } else { + RetType = RelatedRetType; + } // C99 6.8.6.4p3(136): The return statement is not an assignment. The // overlap restriction of subclause 6.5.16.1 does not apply to the case of Index: test/Analysis/nullability_nullonly.mm =================================================================== --- test/Analysis/nullability_nullonly.mm +++ test/Analysis/nullability_nullonly.mm @@ -64,6 +64,10 @@ } } +NSString *_Nonnull testNullReturnInTernaryOperator(int x) { + return x > 3 ? nil : [@"" stringByAppendingString:@""]; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} +} + void testPreconditionViolationInInlinedFunction(Dummy *p) { doNotWarnWhenPreconditionIsViolated(p); } @@ -145,6 +149,10 @@ else return p; // no-warning } + +- (NSString * _Nonnull)testNullReturnInTernaryOperator:(int)x { + return x > 3 ? nil : [@"" stringByAppendingString:@""]; // expected-warning {{Null is returned from a method that is expected to return a non-null value}} +} @end Index: test/SemaObjC/nullability.m =================================================================== --- test/SemaObjC/nullability.m +++ test/SemaObjC/nullability.m @@ -82,7 +82,7 @@ } - (NSFoo *)redundantMethod1 { int *ip = 0; - return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} + return ip; // expected-warning{{incompatible pointer types returning 'int *' from a function with result type 'NSFoo *'}} } @end @@ -96,7 +96,7 @@ @implementation NSMerge - (NSFoo *)methodA:(NSFoo*)foo { int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}} - return ptr; // expected-warning{{result type 'NSFoo * _Nonnull'}} + return ptr; // expected-warning{{incompatible pointer types returning 'int *' from a function with result type 'NSFoo *'}} } - (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \ @@ -106,7 +106,7 @@ - (nonnull NSFoo *)methodC:(nullable NSFoo*)foo { int *ip = 0; - return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} + return ip; // expected-warning{{incompatible pointer types returning 'int *' from a function with result type 'NSFoo *'}} } @end @@ -191,7 +191,7 @@ @implementation NSResettable // expected-warning{{synthesized setter 'setResettable4:' for null_resettable property 'resettable4' does not handle nil}} - (NSResettable *)resettable1 { int *ip = 0; - return ip; // expected-warning{{result type 'NSResettable * _Nonnull'}} + return ip; // expected-warning{{incompatible pointer types returning 'int *' from a function with result type 'NSResettable *'}} } - (void)setResettable1:(NSResettable *)param {