Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / inlining / ObjCDynTypePopagation.m
blobf98f2adbd0c83d9f7ab0617bf906fed8ffe8fee7
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify %s
3 #include "InlineObjCInstanceMethod.h"
5 void clang_analyzer_eval(int);
7 PublicSubClass2 *getObj(void);
9 @implementation PublicParent
10 - (int)getZeroOverridden {
11   return 1;
13 - (int)getZero {
14   return 0;
16 @end
18 @implementation PublicSubClass2
19 - (int)getZeroOverridden {
20   return 0;
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}}
29 + (void)testAllocClass {
30   id a = [PublicSubClass2 alloc];
31   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
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}}
40 + (void)testAllocSuper {
41   id a = [super alloc];
42   clang_analyzer_eval([a getZero] == 0); // expected-warning{{TRUE}}
45 + (void)testAllocInit {
46   id a = [[self alloc] init];
47   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
50 + (void)testNewSelf {
51   id a = [self new];
52   clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
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}}
62 // The type of parameter gets used.
63 + (void)testTypeFromParam:(PublicParent *)p {
64   clang_analyzer_eval([p getZero] == 0); // expected-warning{{TRUE}}
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}}
73 @end
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.
77 int 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;
85 @interface UserClass : NSObject
86 - (PublicSubClass2 *)_newPublicSubClass2;
87 - (int)getZero;
88 - (void)callNew;
89 @end
91 @implementation UserClass
92 - (PublicSubClass2 *)_newPublicSubClass2 {
93   return [[PublicSubClass2 alloc] init];
95 - (int)getZero {
96   return 5;
98 - (void)callNew {
99   PublicSubClass2 *x = [self _newPublicSubClass2];
100   clang_analyzer_eval([x getZero] == 0); //expected-warning{{TRUE}}
102 @end