blob: d901bfee8a066ceb15116c7dfeef8055ff9b0fb2 [file] [log] [blame]
Jordan Rosea34d4f42012-08-21 00:27:33 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify -Wno-null-dereference %s
Jordan Rose6b4be2e2012-07-31 16:34:07 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s
3
4void clang_analyzer_eval(bool);
Zhongxing Xuf45fbad2010-12-19 02:26:37 +00005
Jordy Rose5d553762010-06-04 01:14:56 +00006typedef typeof(sizeof(int)) size_t;
7void malloc (size_t);
Zhongxing Xubc37b8d2010-01-09 09:16:47 +00008
9void f1() {
Jordy Rosee337cba2012-05-16 16:01:14 +000010 int const &i = 3;
Zhongxing Xubc37b8d2010-01-09 09:16:47 +000011 int b = i;
Zhongxing Xu3cd8bd42010-01-10 02:52:56 +000012
13 int *p = 0;
14
15 if (b != 3)
16 *p = 1; // no-warning
Zhongxing Xubc37b8d2010-01-09 09:16:47 +000017}
Zhongxing Xufc61d942010-06-03 06:23:18 +000018
19char* ptr();
20char& ref();
21
22// These next two tests just shouldn't crash.
23char t1 () {
24 ref() = 'c';
25 return '0';
26}
27
28// just a sanity test, the same behavior as t1()
29char t2 () {
30 *ptr() = 'c';
31 return '0';
32}
Jordy Rose5d553762010-06-04 01:14:56 +000033
34// Each of the tests below is repeated with pointers as well as references.
35// This is mostly a sanity check, but then again, both should work!
36char t3 () {
37 char& r = ref();
38 r = 'c'; // no-warning
39 if (r) return r;
40 return *(char*)0; // no-warning
41}
42
43char t4 () {
44 char* p = ptr();
45 *p = 'c'; // no-warning
46 if (*p) return *p;
47 return *(char*)0; // no-warning
48}
49
50char t5 (char& r) {
51 r = 'c'; // no-warning
52 if (r) return r;
53 return *(char*)0; // no-warning
54}
55
56char t6 (char* p) {
57 *p = 'c'; // no-warning
58 if (*p) return *p;
59 return *(char*)0; // no-warning
60}
Jordan Rose6b4be2e2012-07-31 16:34:07 +000061
62
63// PR13440 / <rdar://problem/11977113>
64// Test that the array-to-pointer decay works for array references as well.
65// More generally, when we want an lvalue for a reference field, we still need
66// to do one level of load.
67namespace PR13440 {
68 typedef int T[1];
69 struct S {
70 T &x;
71
72 int *m() { return x; }
73 };
74
75 struct S2 {
76 int (&x)[1];
77
78 int *m() { return x; }
79 };
80
81 void test() {
82 int a[1];
83 S s = { a };
84 S2 s2 = { a };
85
86 if (s.x != a) return;
87 if (s2.x != a) return;
88
89 a[0] = 42;
90 clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}}
91 clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}}
92 }
93}
Jordan Rose9f3b9d52012-08-02 21:33:42 +000094
Jordan Rose522f46f2012-08-04 00:25:30 +000095void testNullReference() {
Jordan Rose9f3b9d52012-08-02 21:33:42 +000096 int *x = 0;
97 int &y = *x; // expected-warning{{Dereference of null pointer}}
98 y = 5;
99}
100
Jordan Rose522f46f2012-08-04 00:25:30 +0000101void testRetroactiveNullReference(int *x) {
102 // According to the C++ standard, there is no such thing as a
103 // "null reference". So the 'if' statement ought to be dead code.
104 // However, Clang (and other compilers) don't actually check that a pointer
105 // value is non-null in the implementation of references, so it is possible
106 // to produce a supposed "null reference" at runtime. The analyzer shoeuld
107 // still warn when it can prove such errors.
108 int &y = *x;
109 if (x != 0)
110 return;
111 y = 5; // expected-warning{{Dereference of null pointer}}
112}
113
Jordan Rosea34d4f42012-08-21 00:27:33 +0000114void testReferenceAddress(int &x) {
115 clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
116 clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
117
118 struct S { int &x; };
119
120 extern S *getS();
121 clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
122}
123
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000124
125// ------------------------------------
126// False negatives
127// ------------------------------------
128
129namespace rdar11212286 {
130 class B{};
131
132 B test() {
133 B *x = 0;
134 return *x; // should warn here!
135 }
136
137 B &testRef() {
138 B *x = 0;
139 return *x; // should warn here!
140 }
Jordan Rosea34d4f42012-08-21 00:27:33 +0000141}
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000142
Jordan Rosea34d4f42012-08-21 00:27:33 +0000143void testReferenceFieldAddress() {
144 struct S { int &x; };
145
146 extern S getS();
147 clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
Jordan Rose9f3b9d52012-08-02 21:33:42 +0000148}