1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify -analyzer-output=text %s |
2 | |
3 | struct FPRec { |
4 | void (*my_func)(int * x); |
5 | }; |
6 | |
7 | int bar(int x); |
8 | |
9 | int f1_a(struct FPRec* foo) { |
10 | int x; |
11 | (*foo->my_func)(&x); |
12 | return bar(x)+1; // no-warning |
13 | } |
14 | |
15 | int f1_b() { |
16 | int x; // expected-note{{'x' declared without an initial value}} |
17 | return bar(x)+1; // expected-warning{{1st function call argument is an uninitialized value}} |
18 | // expected-note@-1{{1st function call argument is an uninitialized value}} |
19 | } |
20 | |
21 | int f2() { |
22 | |
23 | int x; // expected-note{{'x' declared without an initial value}} |
24 | |
25 | if (x+1) // expected-warning{{The left operand of '+' is a garbage value}} |
26 | // expected-note@-1{{The left operand of '+' is a garbage value}} |
27 | return 1; |
28 | |
29 | return 2; |
30 | } |
31 | |
32 | int f2_b() { |
33 | int x; // expected-note{{'x' declared without an initial value}} |
34 | |
35 | return ((1+x)+2+((x))) + 1 ? 1 : 2; // expected-warning{{The right operand of '+' is a garbage value}} |
36 | // expected-note@-1{{The right operand of '+' is a garbage value}} |
37 | } |
38 | |
39 | int f3(void) { |
40 | int i; // expected-note{{'i' declared without an initial value}} |
41 | int *p = &i; |
42 | if (*p > 0) // expected-warning{{The left operand of '>' is a garbage value}} |
43 | // expected-note@-1{{The left operand of '>' is a garbage value}} |
44 | return 0; |
45 | else |
46 | return 1; |
47 | } |
48 | |
49 | void f4_aux(float* x); |
50 | float f4(void) { |
51 | float x; |
52 | f4_aux(&x); |
53 | return x; // no-warning |
54 | } |
55 | |
56 | struct f5_struct { int x; }; |
57 | void f5_aux(struct f5_struct* s); |
58 | int f5(void) { |
59 | struct f5_struct s; |
60 | f5_aux(&s); |
61 | return s.x; // no-warning |
62 | } |
63 | |
64 | void f6(int x) { |
65 | int a[20]; |
66 | if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}} |
67 | // expected-note@-1{{Taking true branch}} |
68 | if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}} |
69 | // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}} |
70 | } |
71 | |
72 | int ret_uninit() { |
73 | int i; // expected-note{{'i' declared without an initial value}} |
74 | int *p = &i; |
75 | return *p; // expected-warning{{Undefined or garbage value returned to caller}} |
76 | // expected-note@-1{{Undefined or garbage value returned to caller}} |
77 | } |
78 | |
79 | // <rdar://problem/6451816> |
80 | typedef unsigned char Boolean; |
81 | typedef const struct __CFNumber * CFNumberRef; |
82 | typedef signed long CFIndex; |
83 | typedef CFIndex CFNumberType; |
84 | typedef unsigned long UInt32; |
85 | typedef UInt32 CFStringEncoding; |
86 | typedef const struct __CFString * CFStringRef; |
87 | extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr); |
88 | extern CFStringRef CFStringConvertEncodingToIANACharSetName(CFStringEncoding encoding); |
89 | |
90 | CFStringRef rdar_6451816(CFNumberRef nr) { |
91 | CFStringEncoding encoding; |
92 | // &encoding is casted to void*. This test case tests whether or not |
93 | // we properly invalidate the value of 'encoding'. |
94 | CFNumberGetValue(nr, 9, &encoding); |
95 | return CFStringConvertEncodingToIANACharSetName(encoding); // no-warning |
96 | } |
97 | |
98 | // PR 4630 - false warning with nonnull attribute |
99 | // This false positive (due to a regression) caused the analyzer to falsely |
100 | // flag a "return of uninitialized value" warning in the first branch due to |
101 | // the nonnull attribute. |
102 | void pr_4630_aux(char *x, int *y) __attribute__ ((nonnull (1))); |
103 | void pr_4630_aux_2(char *x, int *y); |
104 | int pr_4630(char *a, int y) { |
105 | int x; |
106 | if (y) { |
107 | pr_4630_aux(a, &x); |
108 | return x; // no-warning |
109 | } |
110 | else { |
111 | pr_4630_aux_2(a, &x); |
112 | return x; // no-warning |
113 | } |
114 | } |
115 | |
116 | // PR 4631 - False positive with union initializer |
117 | // Previously the analyzer didn't examine the compound initializers of unions, |
118 | // resulting in some false positives for initializers with side-effects. |
119 | union u_4631 { int a; }; |
120 | struct s_4631 { int a; }; |
121 | int pr4631_f2(int *p); |
122 | int pr4631_f3(void *q); |
123 | int pr4631_f1(void) |
124 | { |
125 | int x; |
126 | union u_4631 m = { pr4631_f2(&x) }; |
127 | pr4631_f3(&m); // tell analyzer that we use m |
128 | return x; // no-warning |
129 | } |
130 | int pr4631_f1_b(void) |
131 | { |
132 | int x; |
133 | struct s_4631 m = { pr4631_f2(&x) }; |
134 | pr4631_f3(&m); // tell analyzer that we use m |
135 | return x; // no-warning |
136 | } |
137 | |
138 | // <rdar://problem/12278788> - FP when returning a void-valued expression from |
139 | // a void function...or block. |
140 | void foo_radar12278788() { return; } |
141 | void test_radar12278788() { |
142 | return foo_radar12278788(); // no-warning |
143 | } |
144 | |
145 | void foo_radar12278788_fp() { return; } |
146 | typedef int (*RetIntFuncType)(); |
147 | typedef void (*RetVoidFuncType)(); |
148 | int test_radar12278788_FP() { |
149 | RetVoidFuncType f = foo_radar12278788_fp; |
150 | return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}} |
151 | //expected-note@-1 {{Undefined or garbage value returned to caller}} |
152 | //expected-note@-2 {{Calling 'foo_radar12278788_fp'}} |
153 | //expected-note@-3 {{Returning from 'foo_radar12278788_fp'}} |
154 | } |
155 | |
156 | void rdar13665798() { |
157 | ^() { |
158 | return foo_radar12278788(); // no-warning |
159 | }(); |
160 | ^void() { |
161 | return foo_radar12278788(); // no-warning |
162 | }(); |
163 | ^int() { // expected-note{{Calling anonymous block}} |
164 | RetVoidFuncType f = foo_radar12278788_fp; |
165 | return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}} |
166 | //expected-note@-1 {{Undefined or garbage value returned to caller}} |
167 | //expected-note@-2 {{Calling 'foo_radar12278788_fp'}} |
168 | //expected-note@-3 {{Returning from 'foo_radar12278788_fp'}} |
169 | }(); |
170 | } |
171 | |
172 | struct Point { |
173 | int x, y; |
174 | }; |
175 | |
176 | struct Point getHalfPoint() { |
177 | struct Point p; |
178 | p.x = 0; |
179 | return p; |
180 | } |
181 | |
182 | void use(struct Point p); |
183 | |
184 | void testUseHalfPoint() { |
185 | struct Point p = getHalfPoint(); // expected-note{{Calling 'getHalfPoint'}} |
186 | // expected-note@-1{{Returning from 'getHalfPoint'}} |
187 | // expected-note@-2{{'p' initialized here}} |
188 | use(p); // expected-warning{{uninitialized}} |
189 | // expected-note@-1{{uninitialized}} |
190 | } |
191 | |
192 | void testUseHalfPoint2() { |
193 | struct Point p; |
194 | p = getHalfPoint(); // expected-note{{Calling 'getHalfPoint'}} |
195 | // expected-note@-1{{Returning from 'getHalfPoint'}} |
196 | // expected-note@-2{{Value assigned to 'p'}} |
197 | use(p); // expected-warning{{uninitialized}} |
198 | // expected-note@-1{{uninitialized}} |
199 | } |
200 | |