Jordan Rose | 6b4be2e | 2012-07-31 16:34:07 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s |
| 2 | |
| 3 | void clang_analyzer_eval(bool); |
Zhongxing Xu | f45fbad | 2010-12-19 02:26:37 +0000 | [diff] [blame] | 4 | |
Jordy Rose | 5d55376 | 2010-06-04 01:14:56 +0000 | [diff] [blame] | 5 | typedef typeof(sizeof(int)) size_t; |
| 6 | void malloc (size_t); |
Zhongxing Xu | bc37b8d | 2010-01-09 09:16:47 +0000 | [diff] [blame] | 7 | |
| 8 | void f1() { |
Jordy Rose | e337cba | 2012-05-16 16:01:14 +0000 | [diff] [blame] | 9 | int const &i = 3; |
Zhongxing Xu | bc37b8d | 2010-01-09 09:16:47 +0000 | [diff] [blame] | 10 | int b = i; |
Zhongxing Xu | 3cd8bd4 | 2010-01-10 02:52:56 +0000 | [diff] [blame] | 11 | |
| 12 | int *p = 0; |
| 13 | |
| 14 | if (b != 3) |
| 15 | *p = 1; // no-warning |
Zhongxing Xu | bc37b8d | 2010-01-09 09:16:47 +0000 | [diff] [blame] | 16 | } |
Zhongxing Xu | fc61d94 | 2010-06-03 06:23:18 +0000 | [diff] [blame] | 17 | |
| 18 | char* ptr(); |
| 19 | char& ref(); |
| 20 | |
| 21 | // These next two tests just shouldn't crash. |
| 22 | char t1 () { |
| 23 | ref() = 'c'; |
| 24 | return '0'; |
| 25 | } |
| 26 | |
| 27 | // just a sanity test, the same behavior as t1() |
| 28 | char t2 () { |
| 29 | *ptr() = 'c'; |
| 30 | return '0'; |
| 31 | } |
Jordy Rose | 5d55376 | 2010-06-04 01:14:56 +0000 | [diff] [blame] | 32 | |
| 33 | // Each of the tests below is repeated with pointers as well as references. |
| 34 | // This is mostly a sanity check, but then again, both should work! |
| 35 | char t3 () { |
| 36 | char& r = ref(); |
| 37 | r = 'c'; // no-warning |
| 38 | if (r) return r; |
| 39 | return *(char*)0; // no-warning |
| 40 | } |
| 41 | |
| 42 | char t4 () { |
| 43 | char* p = ptr(); |
| 44 | *p = 'c'; // no-warning |
| 45 | if (*p) return *p; |
| 46 | return *(char*)0; // no-warning |
| 47 | } |
| 48 | |
| 49 | char t5 (char& r) { |
| 50 | r = 'c'; // no-warning |
| 51 | if (r) return r; |
| 52 | return *(char*)0; // no-warning |
| 53 | } |
| 54 | |
| 55 | char t6 (char* p) { |
| 56 | *p = 'c'; // no-warning |
| 57 | if (*p) return *p; |
| 58 | return *(char*)0; // no-warning |
| 59 | } |
Jordan Rose | 6b4be2e | 2012-07-31 16:34:07 +0000 | [diff] [blame] | 60 | |
| 61 | |
| 62 | // PR13440 / <rdar://problem/11977113> |
| 63 | // Test that the array-to-pointer decay works for array references as well. |
| 64 | // More generally, when we want an lvalue for a reference field, we still need |
| 65 | // to do one level of load. |
| 66 | namespace PR13440 { |
| 67 | typedef int T[1]; |
| 68 | struct S { |
| 69 | T &x; |
| 70 | |
| 71 | int *m() { return x; } |
| 72 | }; |
| 73 | |
| 74 | struct S2 { |
| 75 | int (&x)[1]; |
| 76 | |
| 77 | int *m() { return x; } |
| 78 | }; |
| 79 | |
| 80 | void test() { |
| 81 | int a[1]; |
| 82 | S s = { a }; |
| 83 | S2 s2 = { a }; |
| 84 | |
| 85 | if (s.x != a) return; |
| 86 | if (s2.x != a) return; |
| 87 | |
| 88 | a[0] = 42; |
| 89 | clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}} |
| 90 | clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}} |
| 91 | } |
| 92 | } |