Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s
      2 
      3 extern void clang_analyzer_warnIfReached();
      4 void clang_analyzer_eval(int);
      5 
      6 @interface SomeClass
      7 -(id)someMethodWithReturn;
      8 -(void)someMethod;
      9 @end
     10 
     11 void consistencyOfReturnWithNilReceiver(SomeClass *o) {
     12   id result = [o someMethodWithReturn];
     13   if (result) {
     14     if (!o) {
     15       // It is impossible for both o to be nil and result to be non-nil,
     16       // so this should not be reached.
     17       clang_analyzer_warnIfReached(); // no-warning
     18     }
     19   }
     20 }
     21 
     22 void maybeNilReceiverIsNotNilAfterMessage(SomeClass *o) {
     23   [o someMethod];
     24 
     25   // We intentionally drop the nil flow (losing coverage) after a method
     26   // call when the receiver may be nil in order to avoid inconsistencies of
     27   // the kind tested for in consistencyOfReturnWithNilReceiver().
     28   clang_analyzer_eval(o != 0); // expected-warning{{TRUE}}
     29 }
     30 
     31 void nilReceiverIsStillNilAfterMessage(SomeClass *o) {
     32   if (o == 0) {
     33     id result = [o someMethodWithReturn];
     34 
     35     // Both the receiver and the result should be nil after a message
     36     // sent to a nil receiver returning a value of type id.
     37     clang_analyzer_eval(o == 0); // expected-warning{{TRUE}}
     38     clang_analyzer_eval(result == 0); // expected-warning{{TRUE}}
     39   }
     40 }
     41