blob: e46016b762d55b525d68b19602c1d9285ed91119 [file] [log] [blame]
Ted Kremenekcdc3a892012-08-24 20:39:55 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s
Jordan Rose6b4be2e2012-07-31 16:34:07 +00002
3void clang_analyzer_eval(bool);
Zhongxing Xuf45fbad2010-12-19 02:26:37 +00004
Jordy Rose5d553762010-06-04 01:14:56 +00005typedef typeof(sizeof(int)) size_t;
6void malloc (size_t);
Zhongxing Xubc37b8d2010-01-09 09:16:47 +00007
8void f1() {
Jordy Rosee337cba2012-05-16 16:01:14 +00009 int const &i = 3;
Zhongxing Xubc37b8d2010-01-09 09:16:47 +000010 int b = i;
Zhongxing Xu3cd8bd42010-01-10 02:52:56 +000011
12 int *p = 0;
13
14 if (b != 3)
15 *p = 1; // no-warning
Zhongxing Xubc37b8d2010-01-09 09:16:47 +000016}
Zhongxing Xufc61d942010-06-03 06:23:18 +000017
18char* ptr();
19char& ref();
20
21// These next two tests just shouldn't crash.
22char t1 () {
23 ref() = 'c';
24 return '0';
25}
26
27// just a sanity test, the same behavior as t1()
28char t2 () {
29 *ptr() = 'c';
30 return '0';
31}
Jordy Rose5d553762010-06-04 01:14:56 +000032
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!
35char t3 () {
36 char& r = ref();
37 r = 'c'; // no-warning
38 if (r) return r;
39 return *(char*)0; // no-warning
40}
41
42char t4 () {
43 char* p = ptr();
44 *p = 'c'; // no-warning
45 if (*p) return *p;
46 return *(char*)0; // no-warning
47}
48
49char t5 (char& r) {
50 r = 'c'; // no-warning
51 if (r) return r;
52 return *(char*)0; // no-warning
53}
54
55char t6 (char* p) {
56 *p = 'c'; // no-warning
57 if (*p) return *p;
58 return *(char*)0; // no-warning
59}
Jordan Rose6b4be2e2012-07-31 16:34:07 +000060
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.
66namespace 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}
Jordan Rose9f3b9d52012-08-02 21:33:42 +000093
Jordan Rose522f46f2012-08-04 00:25:30 +000094void testNullReference() {
Jordan Rose9f3b9d52012-08-02 21:33:42 +000095 int *x = 0;
96 int &y = *x; // expected-warning{{Dereference of null pointer}}
97 y = 5;
98}
99
Jordan Rose522f46f2012-08-04 00:25:30 +0000100void testRetroactiveNullReference(int *x) {
101 // According to the C++ standard, there is no such thing as a
102 // "null reference". So the 'if' statement ought to be dead code.
103 // However, Clang (and other compilers) don't actually check that a pointer
104 // value is non-null in the implementation of references, so it is possible
105 // to produce a supposed "null reference" at runtime. The analyzer shoeuld
106 // still warn when it can prove such errors.
107 int &y = *x;
108 if (x != 0)
109 return;
110 y = 5; // expected-warning{{Dereference of null pointer}}
111}
112
Jordan Rosea34d4f42012-08-21 00:27:33 +0000113void testReferenceAddress(int &x) {
114 clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
115 clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
116
117 struct S { int &x; };
118
119 extern S *getS();
120 clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
121}
122
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000123
124// ------------------------------------
125// False negatives
126// ------------------------------------
127
128namespace rdar11212286 {
129 class B{};
130
131 B test() {
132 B *x = 0;
133 return *x; // should warn here!
134 }
135
136 B &testRef() {
137 B *x = 0;
138 return *x; // should warn here!
139 }
Jordan Rosea34d4f42012-08-21 00:27:33 +0000140}
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000141
Jordan Rosea34d4f42012-08-21 00:27:33 +0000142void testReferenceFieldAddress() {
143 struct S { int &x; };
144
145 extern S getS();
146 clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000147}