Home | History | Annotate | Download | only in inlining
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify %s
      2 
      3 #include "InlineObjCInstanceMethod.h"
      4 
      5 void clang_analyzer_eval(int);
      6 
      7 PublicSubClass2 *getObj();
      8 
      9 @implementation PublicParent
     10 - (int) getZeroOverridden {
     11    return 1;
     12 }
     13 - (int) getZero {
     14    return 0;
     15 }
     16 @end
     17 
     18 @implementation PublicSubClass2
     19 - (int) getZeroOverridden {
     20    return 0;
     21 }
     22 
     23 /* Test that we get the right type from call to alloc. */
     24 + (void) testAllocSelf {
     25   id a = [self alloc];
     26   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
     27 }
     28 
     29 
     30 + (void) testAllocClass {
     31   id a = [PublicSubClass2 alloc];
     32   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
     33 }
     34 
     35 + (void) testAllocSuperOverriden {
     36   id a = [super alloc];
     37   // Evaluates to 1 in the parent.
     38   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{FALSE}} 
     39 }
     40 
     41 + (void) testAllocSuper {
     42   id a = [super alloc];
     43   clang_analyzer_eval([a getZero] == 0); // expected-warning{{TRUE}}
     44 }
     45 
     46 + (void) testAllocInit {
     47   id a = [[self alloc] init];
     48   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
     49 }
     50 
     51 + (void) testNewSelf {
     52   id a = [self new];
     53   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
     54 }
     55 
     56 // Casting to parent should not pessimize the dynamic type. 
     57 + (void) testCastToParent {
     58  id a = [[self alloc] init];
     59  PublicParent *p = a;  
     60   clang_analyzer_eval([p getZeroOverridden] == 0); // expected-warning{{TRUE}}
     61 }
     62 
     63 // The type of parameter gets used.
     64 + (void)testTypeFromParam:(PublicParent*) p {
     65   clang_analyzer_eval([p getZero] == 0); // expected-warning{{TRUE}}
     66 }
     67 
     68 // Test implicit cast.
     69 // Note, in this case, p could also be a subclass of MyParent.
     70 + (void) testCastFromId:(id) a {
     71   PublicParent *p = a;  
     72   clang_analyzer_eval([p getZero] == 0); // expected-warning{{TRUE}}
     73 }
     74 @end
     75 
     76 // TODO: Would be nice to handle the case of dynamically obtained class info
     77 // as well. We need a MemRegion for class types for this.
     78 int testDynamicClass(BOOL coin) {
     79  Class AllocClass = (coin ? [NSObject class] : [PublicSubClass2 class]);
     80  id x = [[AllocClass alloc] init];
     81  if (coin)
     82    return [x getZero];
     83  return 1;
     84 }
     85 
     86 @interface UserClass : NSObject
     87 - (PublicSubClass2 *) _newPublicSubClass2;
     88 - (int) getZero;
     89 - (void) callNew;
     90 @end
     91 
     92 @implementation UserClass
     93 - (PublicSubClass2 *) _newPublicSubClass2 {
     94   return [[PublicSubClass2 alloc] init];
     95 }
     96 - (int) getZero { return 5; }
     97 - (void) callNew {
     98   PublicSubClass2 *x = [self _newPublicSubClass2];
     99   clang_analyzer_eval([x getZero] == 0); //expected-warning{{TRUE}}
    100 }
    101 @end