blob: 65907762662e9dc0c4b43982316ea76ae1dd2b49 [file] [log] [blame]
Jordan Rosec36b30c2012-07-12 00:16:25 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
2
3void clang_analyzer_eval(bool);
Jordan Rose9584f672012-08-10 22:26:43 +00004void clang_analyzer_checkInlined(bool);
Jordan Rosec36b30c2012-07-12 00:16:25 +00005
6class A {
7public:
8 int getZero() { return 0; }
9 virtual int getNum() { return 0; }
10};
11
12void test(A &a) {
13 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}}
14 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}}
15
16 A copy(a);
17 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}}
18 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}}
19}
20
21
22class One : public A {
23public:
24 virtual int getNum() { return 1; }
25};
26
27void testPathSensitivity(int x) {
28 A a;
29 One b;
30
31 A *ptr;
32 switch (x) {
33 case 0:
34 ptr = &a;
35 break;
36 case 1:
37 ptr = &b;
38 break;
39 default:
40 return;
41 }
42
43 // This should be true on both branches.
44 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}}
45}
46
Jordan Rose9584f672012-08-10 22:26:43 +000047
48namespace PureVirtualParent {
49 class Parent {
50 public:
51 virtual int pureVirtual() const = 0;
52 int callVirtual() const {
53 return pureVirtual();
54 }
55 };
56
57 class Child : public Parent {
58 public:
59 virtual int pureVirtual() const {
60 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
61 return 42;
62 }
63 };
64
65 void testVirtual() {
66 Child x;
67
68 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}}
69 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}}
70 }
71}
72
73
Jordan Roseb6d2bea2012-08-10 22:26:46 +000074namespace PR13569 {
75 class Parent {
76 protected:
77 int m_parent;
78 virtual int impl() const = 0;
79
80 Parent() : m_parent(0) {}
81
82 public:
83 int interface() const {
84 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
85 return impl();
86 }
87 };
88
89 class Child : public Parent {
90 protected:
91 virtual int impl() const {
92 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
93 return m_parent + m_child;
94 }
95
96 public:
97 Child() : m_child(0) {}
98
99 int m_child;
100 };
101
102 void testVirtual() {
103 Child x;
104 x.m_child = 42;
105
106 // Don't crash when inlining and devirtualizing.
107 x.interface();
108 }
Jordan Rose8ec104b2012-08-13 23:46:01 +0000109
110
111 class Grandchild : public Child {};
112
113 void testDevirtualizeToMiddle() {
114 Grandchild x;
115 x.m_child = 42;
116
117 // Don't crash when inlining and devirtualizing.
118 x.interface();
119 }
Jordan Roseb6d2bea2012-08-10 22:26:46 +0000120}
121
Jordan Rose8ec104b2012-08-13 23:46:01 +0000122namespace PR13569_virtual {
123 class Parent {
124 protected:
125 int m_parent;
126 virtual int impl() const = 0;
Jordan Roseb6d2bea2012-08-10 22:26:46 +0000127
Jordan Rose8ec104b2012-08-13 23:46:01 +0000128 Parent() : m_parent(0) {}
129
130 public:
131 int interface() const {
132 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
133 return impl();
134 }
135 };
136
137 class Child : virtual public Parent {
138 protected:
139 virtual int impl() const {
140 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
141 return m_parent + m_child;
142 }
143
144 public:
145 Child() : m_child(0) {}
146
147 int m_child;
148 };
149
150 void testVirtual() {
151 Child x;
152 x.m_child = 42;
153
154 // Don't crash when inlining and devirtualizing.
155 x.interface();
156 }
157
158
159 class Grandchild : virtual public Child {};
160
161 void testDevirtualizeToMiddle() {
162 Grandchild x;
163 x.m_child = 42;
164
165 // Don't crash when inlining and devirtualizing.
166 x.interface();
167 }
168}
Jordan Roseda29ac52012-08-15 21:05:15 +0000169
170namespace Invalidation {
171 struct X {
172 void touch(int &x) const {
173 x = 0;
174 }
175
176 void touch2(int &x) const;
177
178 virtual void touchV(int &x) const {
179 x = 0;
180 }
181
182 virtual void touchV2(int &x) const;
183
184 int test() const {
185 // We were accidentally not invalidating under -analyzer-ipa=inlining
186 // at one point for virtual methods with visible definitions.
187 int a, b, c, d;
188 touch(a);
189 touch2(b);
190 touchV(c);
191 touchV2(d);
192 return a + b + c + d; // no-warning
193 }
194 };
195}
Jordan Roseb66529d2012-08-23 18:10:53 +0000196
197namespace DefaultArgs {
198 int takesDefaultArgs(int i = 42) {
199 return -i;
200 }
201
202 void testFunction() {
203 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}}
204 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}}
205 }
206
207 class Secret {
208 public:
209 static const int value = 42;
210 int get(int i = value) {
211 return i;
212 }
213 };
214
215 void testMethod() {
216 Secret obj;
217 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
218
219 // FIXME: Should be 'TRUE'. See PR13673 or <rdar://problem/11720796>.
220 clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}}
221
222 // FIXME: Even if we constrain the variable, we still have a problem.
223 // See PR13385 or <rdar://problem/12156507>.
224 if (Secret::value != 42)
225 return;
226 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
227 clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}}
228 }
229}