[RISCV][FMV] Support target_clones (#85786)
[llvm-project.git] / clang / test / Analysis / inline.cpp
blob2b31460330e44a2168edd0bcb6c122a31e382c26
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify -analyzer-config eagerly-assume=false %s
3 void clang_analyzer_eval(bool);
4 void clang_analyzer_checkInlined(bool);
6 typedef __typeof__(sizeof(int)) size_t;
7 extern "C" void *malloc(size_t);
9 // This is the standard placement new.
10 inline void* operator new(size_t, void* __p) throw()
12 clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
13 return __p;
17 class A {
18 public:
19 int getZero() { return 0; }
20 virtual int getNum() { return 0; }
23 void test(A &a) {
24 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}}
25 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}}
27 A copy(a);
28 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}}
29 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}}
33 class One : public A {
34 public:
35 virtual int getNum() { return 1; }
38 void testPathSensitivity(int x) {
39 A a;
40 One b;
42 A *ptr;
43 switch (x) {
44 case 0:
45 ptr = &a;
46 break;
47 case 1:
48 ptr = &b;
49 break;
50 default:
51 return;
54 // This should be true on both branches.
55 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}}
59 namespace PureVirtualParent {
60 class Parent {
61 public:
62 virtual int pureVirtual() const = 0;
63 int callVirtual() const {
64 return pureVirtual();
68 class Child : public Parent {
69 public:
70 virtual int pureVirtual() const {
71 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
72 return 42;
76 void testVirtual() {
77 Child x;
79 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}}
80 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}}
85 namespace PR13569 {
86 class Parent {
87 protected:
88 int m_parent;
89 virtual int impl() const = 0;
91 Parent() : m_parent(0) {}
93 public:
94 int interface() const {
95 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
96 return impl();
100 class Child : public Parent {
101 protected:
102 virtual int impl() const {
103 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104 return m_parent + m_child;
107 public:
108 Child() : m_child(0) {}
110 int m_child;
113 void testVirtual() {
114 Child x;
115 x.m_child = 42;
117 // Don't crash when inlining and devirtualizing.
118 x.interface();
122 class Grandchild : public Child {};
124 void testDevirtualizeToMiddle() {
125 Grandchild x;
126 x.m_child = 42;
128 // Don't crash when inlining and devirtualizing.
129 x.interface();
133 namespace PR13569_virtual {
134 class Parent {
135 protected:
136 int m_parent;
137 virtual int impl() const = 0;
139 Parent() : m_parent(0) {}
141 public:
142 int interface() const {
143 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
144 return impl();
148 class Child : virtual public Parent {
149 protected:
150 virtual int impl() const {
151 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
152 return m_parent + m_child;
155 public:
156 Child() : m_child(0) {}
158 int m_child;
161 void testVirtual() {
162 Child x;
163 x.m_child = 42;
165 // Don't crash when inlining and devirtualizing.
166 x.interface();
170 class Grandchild : virtual public Child {};
172 void testDevirtualizeToMiddle() {
173 Grandchild x;
174 x.m_child = 42;
176 // Don't crash when inlining and devirtualizing.
177 x.interface();
181 namespace Invalidation {
182 struct X {
183 void touch(int &x) const {
184 x = 0;
187 void touch2(int &x) const;
189 virtual void touchV(int &x) const {
190 x = 0;
193 virtual void touchV2(int &x) const;
195 int test() const {
196 // We were accidentally not invalidating under inlining
197 // at one point for virtual methods with visible definitions.
198 int a, b, c, d;
199 touch(a);
200 touch2(b);
201 touchV(c);
202 touchV2(d);
203 return a + b + c + d; // no-warning
208 namespace DefaultArgs {
209 int takesDefaultArgs(int i = 42) {
210 return -i;
213 void testFunction() {
214 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}}
215 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}}
218 class Secret {
219 public:
220 static const int value = 40 + 2;
221 int get(int i = value) {
222 return i;
226 void testMethod() {
227 Secret obj;
228 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
229 clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
230 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
233 enum ABC {
234 A = 0,
235 B = 1,
236 C = 2
239 int enumUser(ABC input = B) {
240 return static_cast<int>(input);
243 void testEnum() {
244 clang_analyzer_eval(enumUser(C) == 2); // expected-warning{{TRUE}}
245 clang_analyzer_eval(enumUser() == 1); // expected-warning{{TRUE}}
249 int exprUser(int input = 2 * 4) {
250 return input;
253 int complicatedExprUser(int input = 2 * Secret::value) {
254 return input;
257 void testExprs() {
258 clang_analyzer_eval(exprUser(1) == 1); // expected-warning{{TRUE}}
259 clang_analyzer_eval(exprUser() == 8); // expected-warning{{TRUE}}
261 clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
262 clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
265 int defaultReference(const int &input = 42) {
266 return -input;
268 int defaultReferenceZero(const int &input = 0) {
269 return -input;
272 void testReference() {
273 clang_analyzer_eval(defaultReference(1) == -1); // expected-warning{{TRUE}}
274 clang_analyzer_eval(defaultReference() == -42); // expected-warning{{TRUE}}
276 clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}}
277 clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}}
280 double defaultFloatReference(const double &i = 42) {
281 return -i;
283 double defaultFloatReferenceZero(const double &i = 0) {
284 return -i;
287 void testFloatReference() {
288 clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}}
289 clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}}
291 clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}}
292 clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}}
295 char defaultString(const char *s = "abc") {
296 return s[1];
299 void testString() {
300 clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}}
301 clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}}
304 const void * const void_string = "abc";
306 void testBitcastedString() {
307 clang_analyzer_eval(0 != void_string); // expected-warning{{TRUE}}
308 clang_analyzer_eval('b' == ((char *)void_string)[1]); // expected-warning{{TRUE}}
312 namespace OperatorNew {
313 class IntWrapper {
314 public:
315 int value;
317 IntWrapper(int input) : value(input) {
318 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
322 void test() {
323 IntWrapper *obj = new IntWrapper(42);
324 clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
325 delete obj;
328 void testPlacement() {
329 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
330 IntWrapper *alias = new (obj) IntWrapper(42);
332 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
334 clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
335 // Because malloc() was never free()d:
336 // expected-warning@-2{{Potential leak of memory pointed to by 'alias'}}
341 namespace VirtualWithSisterCasts {
342 // This entire set of tests exercises casts from sister classes and
343 // from classes outside the hierarchy, which can very much confuse
344 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.
345 // These examples used to cause crashes in +Asserts builds.
346 struct Parent {
347 virtual int foo();
348 int x;
351 struct A : Parent {
352 virtual int foo() { return 42; }
355 struct B : Parent {
356 virtual int foo();
359 struct Grandchild : public A {};
361 struct Unrelated {};
363 void testDowncast(Parent *b) {
364 A *a = (A *)(void *)b;
365 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
367 a->x = 42;
368 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
371 void testRelated(B *b) {
372 A *a = (A *)(void *)b;
373 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
375 a->x = 42;
376 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
379 void testUnrelated(Unrelated *b) {
380 A *a = (A *)(void *)b;
381 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
383 a->x = 42;
384 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
387 void testCastViaNew(B *b) {
388 Grandchild *g = new (b) Grandchild();
389 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
391 g->x = 42;
392 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
397 namespace QualifiedCalls {
398 void test(One *object) {
399 // This uses the One class from the top of the file.
400 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
401 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
402 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
404 // getZero is non-virtual.
405 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
406 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
407 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
412 namespace rdar12409977 {
413 struct Base {
414 int x;
417 struct Parent : public Base {
418 virtual Parent *vGetThis();
419 Parent *getThis() { return vGetThis(); }
422 struct Child : public Parent {
423 virtual Child *vGetThis() { return this; }
426 void test() {
427 Child obj;
428 obj.x = 42;
430 // Originally, calling a devirtualized method with a covariant return type
431 // caused a crash because the return value had the wrong type. When we then
432 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
433 // the object region and we get an assertion failure.
434 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
438 namespace bug16307 {
439 void one_argument(int a) { }
440 void call_with_less() {
441 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument is called with fewer (0)}}