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