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 AttributedType *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.mm =================================================================== --- test/Analysis/nullability.mm +++ test/Analysis/nullability.mm @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -DNOSYSTEMHEADERS=0 -verify %s // RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s +// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -fobjc-arc -DNOSYSTEMHEADERS=0 -verify %s #include "Inputs/system-header-simulator-for-nullability.h" @@ -110,6 +111,10 @@ return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}} } +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 testObjCMessageResultNullability() { // The expected result: the most nullable of self and method return type. TestObject *o = getUnspecifiedTestObject(); @@ -388,6 +393,11 @@ 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 @interface ClassWithInitializers : NSObject 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 {