brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.6 KiB · 64222d9 Raw
659 lines · plain
1// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \2// RUN:   -analyzer-checker=nullability.NullPassedToNonnull \3// RUN:   -analyzer-checker=nullability.NullReturnedFromNonnull \4// RUN:   -analyzer-checker=nullability.NullablePassedToNonnull \5// RUN:   -analyzer-checker=nullability.NullableReturnedFromNonnull \6// RUN:   -analyzer-checker=nullability.NullableDereferenced \7// RUN:   -DNOSYSTEMHEADERS=08 9// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \10// RUN:   -analyzer-checker=nullability.NullPassedToNonnull \11// RUN:   -analyzer-checker=nullability.NullReturnedFromNonnull \12// RUN:   -analyzer-checker=nullability.NullablePassedToNonnull \13// RUN:   -analyzer-checker=nullability.NullableReturnedFromNonnull \14// RUN:   -analyzer-checker=nullability.NullableDereferenced \15// RUN:   -DNOSYSTEMHEADERS=1 \16// RUN:   -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true17 18// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\19// RUN:   -analyzer-checker=nullability.NullPassedToNonnull\20// RUN:   -analyzer-checker=nullability.NullReturnedFromNonnull\21// RUN:   -analyzer-checker=nullability.NullablePassedToNonnull\22// RUN:   -analyzer-checker=nullability.NullableReturnedFromNonnull\23// RUN:   -analyzer-checker=nullability.NullableDereferenced\24// RUN:   -DNOSYSTEMHEADERS=0 -fobjc-arc25 26// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\27// RUN:   -analyzer-checker=nullability.NullPassedToNonnull\28// RUN:   -analyzer-checker=nullability.NullReturnedFromNonnull\29// RUN:   -analyzer-checker=nullability.NullablePassedToNonnull\30// RUN:   -analyzer-checker=nullability.NullableReturnedFromNonnull\31// RUN:   -analyzer-checker=nullability.NullableDereferenced\32// RUN:   -DNOSYSTEMHEADERS=1 -fobjc-arc\33// RUN:   -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true34 35#include "Inputs/system-header-simulator-for-nullability.h"36 37extern void __assert_fail(__const char *__assertion, __const char *__file,38                          unsigned int __line, __const char *__function)39    __attribute__((__noreturn__));40 41#define assert(expr) \42  ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))43 44@interface TestObject : NSObject45- (int *_Nonnull)returnsNonnull;46- (int *_Nullable)returnsNullable;47- (int *)returnsUnspecified;48- (void)takesNonnull:(int *_Nonnull)p;49- (void)takesNonnullBlock:(void (^ _Nonnull)(void))block;50- (void)takesNullable:(int *_Nullable)p;51- (void)takesUnspecified:(int *)p;52@property(readonly, strong) NSString *stuff;53@property(readonly, nonnull) int *propReturnsNonnull;54@property(readonly, nonnull) void (^propReturnsNonnullBlock)(void);55@property(readonly, nullable) void (^propReturnsNullableBlock)(void);56@property(readonly, nullable) int *propReturnsNullable;57@property(readonly) int *propReturnsUnspecified;58+ (nullable TestObject *)getNullableObject;59@end60 61TestObject * getUnspecifiedTestObject();62TestObject *_Nonnull getNonnullTestObject();63TestObject *_Nullable getNullableTestObject();64 65int getRandom();66 67typedef struct Dummy { int val; } Dummy;68 69void takesNullable(Dummy *_Nullable);70void takesNonnull(Dummy *_Nonnull);71void takesUnspecified(Dummy *);72void takesNonnullBlock(void (^ _Nonnull)(void));73void takesNonnullObject(NSObject *_Nonnull);74 75Dummy *_Nullable returnsNullable();76Dummy *_Nonnull returnsNonnull();77Dummy *returnsUnspecified();78int *_Nullable returnsNullableInt();79 80template <typename T> T *eraseNullab(T *p) { return p; }81 82void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));83 84void testBasicRules() {85  Dummy *p = returnsNullable();86  int *ptr = returnsNullableInt();87  // Make every dereference a different path to avoid sinks after errors.88  switch (getRandom()) {89  case 0: {90    Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced}}91  } break;92  case 1: {93    int b = p->val; // expected-warning {{Nullable pointer is dereferenced}}94  } break;95  case 2: {96    int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced}}97  } break;98  case 3:99    takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}100    break;101  case 4: {102    Dummy d;103    takesNullable(&d);104    Dummy dd(d);105    break;106  }107  case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}108  default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}109  }110  if (p) {111    takesNonnull(p);112    if (getRandom()) {113      Dummy &r = *p;114    } else {115      int b = p->val;116    }117  }118  Dummy *q = 0;119  if (getRandom()) {120    takesNullable(q);121    takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}122  }123  Dummy a;124  Dummy *_Nonnull nonnull = &a;125  nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}}126  q = &a;127  takesNullable(q);128  takesNonnull(q);129}130 131void testMultiParamChecking(Dummy *_Nonnull a, Dummy *_Nullable b,132                            Dummy *_Nonnull c);133 134void testArgumentTracking(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {135  Dummy *p = nullable;136  Dummy *q = nonnull;137  switch(getRandom()) {138  case 1: nonnull = p; break; // expected-warning {{Nullable pointer is assigned to a pointer which is expected to have non-null value}}139  case 2: p = 0; break;140  case 3: q = p; break;141  case 4: testMultiParamChecking(nonnull, nullable, nonnull); break;142  case 5: testMultiParamChecking(nonnull, nonnull, nonnull); break;143  case 6: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}144  case 7: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}145  case 8: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}146  case 9: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;147  }148}149 150void testArgumentTrackingDirectly(Dummy *_Nonnull nonnull, Dummy *_Nullable nullable) {151  switch(getRandom()) {152  case 1: testMultiParamChecking(nonnull, nullable, nonnull); break;153  case 2: testMultiParamChecking(nonnull, nonnull, nonnull); break;154  case 3: testMultiParamChecking(nonnull, nullable, nullable); break; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 3rd parameter}}155  case 4: testMultiParamChecking(nullable, nullable, nonnull); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}156  case 5: testMultiParamChecking(nullable, nullable, nullable); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}157  case 6: testMultiParamChecking((Dummy *_Nonnull)0, nullable, nonnull); break;158  }159}160 161Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {162  Dummy *p = a;163  return p; // expected-warning {{Nullable pointer is returned from a function that is expected to return a non-null value}}164}165 166Dummy *_Nonnull testNullReturn() {167  Dummy *p = 0;168  return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}169}170 171void testObjCMessageResultNullability() {172  // The expected result: the most nullable of self and method return type.173  TestObject *o = getUnspecifiedTestObject();174  int *shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNonnull];175  switch (getRandom()) {176  case 0:177    // The core analyzer assumes that the receiver is non-null after a message178    // send. This is to avoid some false positives, and increase performance179    // but it also reduces the coverage and makes this checker unable to reason180    // about the nullness of the receiver. 181    [o takesNonnull:shouldBeNullable]; // No warning expected.182    break;183  case 1:184    shouldBeNullable =185        [eraseNullab(getNullableTestObject()) returnsUnspecified];186    [o takesNonnull:shouldBeNullable]; // No warning expected.187    break;188  case 3:189    shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];190    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}191    break;192  case 4:193    shouldBeNullable = [eraseNullab(getNonnullTestObject()) returnsNullable];194    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}195    break;196  case 5:197    shouldBeNullable =198        [eraseNullab(getUnspecifiedTestObject()) returnsNullable];199    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}200    break;201  case 6:202    shouldBeNullable = [eraseNullab(getNullableTestObject()) returnsNullable];203    [o takesNonnull:shouldBeNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}204    break;205  case 7: {206    int *shouldBeNonnull = [eraseNullab(getNonnullTestObject()) returnsNonnull];207    [o takesNonnull:shouldBeNonnull];208  } break;209  }210}211 212void testObjCPropertyReadNullability() {213  TestObject *o = getNonnullTestObject();214  switch (getRandom()) {215  case 0:216    [o takesNonnull:o.propReturnsNonnull]; // no-warning217    [o takesNonnullBlock:o.propReturnsNonnullBlock]; // no-warning218    break;219  case 1:220    [o takesNonnull:o.propReturnsUnspecified]; // no-warning221    break;222  case 2:223    [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}224    break;225  case 3:226    // If a property is constrained nonnull, assume it remains nonnull227    if (o.propReturnsNullable) {228      [o takesNonnull:o.propReturnsNullable]; // no-warning229      [o takesNonnull:o.propReturnsNullable]; // no-warning230    }231    break;232  case 4:233    if (!o.propReturnsNullable) {234      [o takesNonnull:o.propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}235    }236    break;237  case 5:238    if (!o.propReturnsNullable) {239      if (o.propReturnsNullable) {240        // Nonnull constraint from the more recent call wins241        [o takesNonnull:o.propReturnsNullable]; // no-warning242      }243    }244    break;245  case 6:246    // Constraints on property return values are receiver-qualified247    if (o.propReturnsNullable) {248      [o takesNonnull:o.propReturnsNullable];                      // no-warning249      [o takesNonnull:getNonnullTestObject().propReturnsNullable]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}250    }251    break;252  case 7:253    // Assertions must be effective at suppressing warnings254    assert(o.propReturnsNullable);255    [o takesNonnull:o.propReturnsNullable]; // no-warning256    break;257  case 8:258    [o takesNonnullBlock:o.propReturnsNullableBlock]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}259    break;260  case 9:261    [o takesNonnull:getNullableTestObject().propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}262    break;263  case 10:264    [o takesNonnull:[TestObject getNullableObject].propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}265    break;266  }267}268 269Dummy * _Nonnull testDirectCastNullableToNonnull() {270  Dummy *p = returnsNullable();271  takesNonnull((Dummy * _Nonnull)p);  // no-warning272  return (Dummy * _Nonnull)p;         // no-warning273}274 275Dummy * _Nonnull testIndirectCastNullableToNonnull() {276  Dummy *p = (Dummy * _Nonnull)returnsNullable();277  takesNonnull(p);  // no-warning278  return p;         // no-warning279}280 281Dummy * _Nonnull testDirectCastNilToNonnull() {282  takesNonnull((Dummy * _Nonnull)0);  // no-warning283  return (Dummy * _Nonnull)0;         // no-warning284}285 286void testImplicitCastNilToNonnull() {287  id obj = nil;288  takesNonnullObject(obj); // expected-warning {{nil passed to a callee that requires a non-null 1st parameter}}289}290 291void testImplicitCastNullableArgToNonnull(TestObject *_Nullable obj) {292  if (!obj) {293    takesNonnullObject(obj); // expected-warning {{nil passed to a callee that requires a non-null 1st parameter}}294  }295}296 297void testIndirectCastNilToNonnullAndPass() {298  Dummy *p = (Dummy * _Nonnull)0;299  // FIXME: Ideally the cast above would suppress this warning.300  takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}301}302 303void testDirectCastNilToNonnullAndAssignToLocalInInitializer() {304  Dummy * _Nonnull nonnullLocalWithAssignmentInInitializer = (Dummy * _Nonnull)0; // no-warning305  (void)nonnullLocalWithAssignmentInInitializer;306 307  // Since we've already had an invariant violation along this path,308  // we shouldn't warn here.309  nonnullLocalWithAssignmentInInitializer = 0;310  (void)nonnullLocalWithAssignmentInInitializer;311 312}313 314void testDirectCastNilToNonnullAndAssignToLocal(Dummy * _Nonnull p) {315  Dummy * _Nonnull nonnullLocalWithAssignment = p;316  nonnullLocalWithAssignment = (Dummy * _Nonnull)0; // no-warning317  (void)nonnullLocalWithAssignment;318 319  // Since we've already had an invariant violation along this path,320  // we shouldn't warn here.321  nonnullLocalWithAssignment = 0;322  (void)nonnullLocalWithAssignment;323}324 325void testDirectCastNilToNonnullAndAssignToParam(Dummy * _Nonnull p) {326  p = (Dummy * _Nonnull)0; // no-warning327}328 329@interface ClassWithNonnullIvar : NSObject {330  Dummy *_nonnullIvar;331}332@end333 334@implementation ClassWithNonnullIvar335-(void)testDirectCastNilToNonnullAndAssignToIvar {336  _nonnullIvar = (Dummy * _Nonnull)0; // no-warning;337 338  // Since we've already had an invariant violation along this path,339  // we shouldn't warn here.340  _nonnullIvar = 0;341}342@end343 344void testIndirectNilPassToNonnull() {345  Dummy *p = 0;346  takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}347}348 349void testBlockIndirectNilPassToNonnull() {350  void (^p)(void) = nil;351  takesNonnullBlock(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}352}353 354void testConditionalNilPassToNonnull(Dummy *p) {355  if (!p) {356    takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}357  }358}359 360Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {361  Dummy *p = (Dummy * _Nonnull)0;362  // FIXME: Ideally the cast above would suppress this warning.363  return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}364}365 366void testInvalidPropagation() {367  Dummy *p = returnsUnspecified();368  takesNullable(p);369  takesNonnull(p);370}371 372void onlyReportFirstPreconditionViolationOnPath() {373  Dummy *p = returnsNullable();374  takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}375  takesNonnull(p); // No warning.376  // The first warning was not a sink. The analysis expected to continue.377  int i = 0;378  i = 5 / i; // expected-warning {{Division by zero}}379  (void)i;380}381 382Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(383    Dummy *_Nonnull p) {384  if (!p) {385    Dummy *ret =386        0; // avoid compiler warning (which is not generated by the analyzer)387    if (getRandom())388      return ret; // no warning389    else390      return p; // no warning391  } else {392    return p;393  }394}395 396Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {397  if (!p) {398    Dummy *ret =399        0; // avoid compiler warning (which is not generated by the analyzer)400    if (getRandom())401      return ret; // no warning402    else403      return p; // no warning404  } else {405    return p;406  }407}408 409void testPreconditionViolationInInlinedFunction(Dummy *p) {410  doNotWarnWhenPreconditionIsViolated(p);411}412 413@interface TestInlinedPreconditionViolationClass : NSObject414@end415 416@implementation TestInlinedPreconditionViolationClass417-(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {418  Dummy *x = 0;419  if (!p2) // p2 binding becomes dead at this point.420    return x; // no-warning421  else422   return p2;423}424 425-(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {426  return [self calleeWithParam:p1];427}428 429@end430 431int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {432  int *x = 0;433  if (!p2) // p2 binding becomes dead at this point.434    return x; // no-warning435  else436   return p2;437}438 439int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {440  int *result = 0;441  return result; // expected-warning{{Null returned from a function that is expected to return a non-null value}}442}443 444int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {445  return InlinedReturnNullOverSuppressionCallee(p1);446}447 448void inlinedNullable(Dummy *_Nullable p) {449  if (p) return;450}451void inlinedNonnull(Dummy *_Nonnull p) {452  if (p) return;453}454void inlinedUnspecified(Dummy *p) {455  if (p) return;456}457 458void testNilReturnWithBlock(Dummy *p) {459  p = 0;460  Dummy *_Nonnull (^myblock)(void) = ^Dummy *_Nonnull(void) {461    return p; // TODO: We should warn in blocks.462  };463  myblock();464}465 466Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {467  switch (getRandom()) {468  case 1: inlinedNullable(p); break;469  case 2: inlinedNonnull(p); break;470  case 3: inlinedUnspecified(p); break;471  }472  if (getRandom())473    takesNonnull(p);  // no-warning474 475  if (getRandom()) {476    Dummy *_Nonnull varWithInitializer = p; // no-warning477 478     Dummy *_Nonnull var1WithInitializer = p,  // no-warning479           *_Nonnull var2WithInitializer = p;  // no-warning480  }481 482  if (getRandom()) {483    Dummy *_Nonnull varWithoutInitializer;484    varWithoutInitializer = p; // no-warning485  }486 487  return p;488}489 490 491@interface SomeClass : NSObject {492  int instanceVar;493}494@end495 496@implementation SomeClass (MethodReturn)497- (id)initWithSomething:(int)i {498  if (self = [super init]) {499    instanceVar = i;500  }501 502  return self;503}504 505- (TestObject * _Nonnull)testReturnsNullableInNonnullIndirectly {506  TestObject *local = getNullableTestObject();507  return local; // expected-warning {{Nullable pointer is returned from a method that is expected to return a non-null value}}508}509 510- (TestObject * _Nonnull)testReturnsCastSuppressedNullableInNonnullIndirectly {511  TestObject *local = getNullableTestObject();512  return (TestObject * _Nonnull)local; // no-warning513}514 515- (TestObject * _Nonnull)testReturnsNullableInNonnullWhenPreconditionViolated:(TestObject * _Nonnull) p {516  TestObject *local = getNullableTestObject();517  if (!p) // Pre-condition violated here.518    return local; // no-warning519  else520    return p; // no-warning521}522@end523 524@interface ClassWithInitializers : NSObject525@end526 527@implementation ClassWithInitializers528- (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {529  // This defensive check is a common-enough idiom that we filter don't want530  // to issue a diagnostic for it,531  if (self = [super init]) {532  }533 534  return self; // no-warning535}536 537- (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {538  self = [super init];539  // This leaks, but we're not checking for that here.540 541  ClassWithInitializers *other = nil;542  // False negative. Once we have more subtle suppression of defensive checks in543  // initializers we should warn here.544  return other;545}546@end547 548@interface SubClassWithInitializers : ClassWithInitializers549@end550 551@implementation SubClassWithInitializers552// Note: Because this is overriding553// -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],554// the return type of this method becomes implicitly id _Nonnull.555- (id)initWithNonnullReturnAndSelfCheckingIdiom {556  if (self = [super initWithNonnullReturnAndSelfCheckingIdiom]) {557  }558 559  return self; // no-warning560}561 562- (id _Nonnull)initWithNonnullReturnAndSelfCheckingIdiomV2; {563  // Another common return-checking idiom564  self = [super initWithNonnullReturnAndSelfCheckingIdiom];565  if (!self) {566    return nil; // no-warning567  }568 569  return self;570}571@end572 573@interface ClassWithCopyWithZone : NSObject<NSCopying,NSMutableCopying> {574  id i;575}576 577@end578 579@implementation ClassWithCopyWithZone580-(id)copyWithZone:(NSZone *)zone {581  ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];582  if (!newInstance)583    return nil;584 585  newInstance->i = i;586  return newInstance;587}588 589-(id)mutableCopyWithZone:(NSZone *)zone {590  ClassWithCopyWithZone *newInstance = [[ClassWithCopyWithZone alloc] init];591  if (newInstance) {592    newInstance->i = i;593  }594 595  return newInstance;596}597@end598 599NSString * _Nullable returnsNullableString();600 601void callFunctionInSystemHeader() {602  NSString *s = returnsNullableString();603 604  NSSystemFunctionTakingNonnull(s);605  #if !NOSYSTEMHEADERS606  // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}607  #endif608}609 610void callMethodInSystemHeader() {611  NSString *s = returnsNullableString();612 613  NSSystemClass *sc = [[NSSystemClass alloc] init];614  [sc takesNonnull:s];615  #if !NOSYSTEMHEADERS616  // expected-warning@-2{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}617  #endif618}619 620// Test to make sure the analyzer doesn't warn when an a nullability invariant621// has already been found to be violated on an instance variable.622 623@class MyInternalClass;624@interface MyClass : NSObject {625  MyInternalClass * _Nonnull _internal;626}627@end628 629@interface MyInternalClass : NSObject {630  @public631  id _someIvar;632}633-(id _Nonnull)methodWithInternalImplementation;634@end635 636@interface MyClass () {637  MyInternalClass * _Nonnull _nilledOutInternal;638}639@end640 641@implementation MyClass642-(id _Nonnull)methodWithInternalImplementation {643  if (!_internal)644    return nil; // no-warning645 646  return [_internal methodWithInternalImplementation];647}648 649- (id _Nonnull)methodReturningIvarInImplementation; {650  return _internal == 0 ? nil : _internal->_someIvar; // no-warning651}652 653-(id _Nonnull)methodWithNilledOutInternal {654  _nilledOutInternal = (id _Nonnull)nil;655 656  return nil; // no-warning657}658@end659