434 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-output=text -verify %s2 3typedef unsigned int NSUInteger;4typedef __typeof__(sizeof(int)) size_t;5 6void *malloc(size_t);7void *calloc(size_t nmemb, size_t size);8void free(void *);9 10void clang_analyzer_eval(int);11 12struct s {13 int data;14};15 16struct s global;17 18void g(int);19 20void f4(void) {21 int a;22 if (global.data == 0)23 a = 3;24 if (global.data == 0) // When the true branch is feasible 'a = 3'.25 g(a); // no-warning26}27 28 29// Test uninitialized value due to part of the structure being uninitialized.30struct TestUninit { int x; int y; };31struct TestUninit test_uninit_aux(void);32void test_unit_aux2(int);33void test_uninit_pos(void) {34 struct TestUninit v1 = { 0, 0 };35 struct TestUninit v2 = test_uninit_aux();36 int z; // expected-note{{'z' declared without an initial value}}37 v1.y = z; // expected-warning{{Assigned value is uninitialized}}38 // expected-note@-1{{Assigned value is uninitialized}}39 test_unit_aux2(v2.x + v1.y);40}41void test_uninit_pos_2(void) {42 struct TestUninit v1 = { 0, 0 };43 struct TestUninit v2;44 test_unit_aux2(v2.x + v1.y); // expected-warning{{The left operand of '+' is a garbage value}}45 // expected-note@-1{{The left operand of '+' is a garbage value}}46}47void test_uninit_pos_3(void) {48 struct TestUninit v1 = { 0, 0 };49 struct TestUninit v2;50 test_unit_aux2(v1.y + v2.x); // expected-warning{{The right operand of '+' is a garbage value}}51 // expected-note@-1{{The right operand of '+' is a garbage value}}52}53 54void test_uninit_neg(void) {55 struct TestUninit v1 = { 0, 0 };56 struct TestUninit v2 = test_uninit_aux();57 test_unit_aux2(v2.x + v1.y);58}59 60extern void test_uninit_struct_arg_aux(struct TestUninit arg);61void test_uninit_struct_arg(void) {62 struct TestUninit x; // expected-note{{'x' initialized here}}63 test_uninit_struct_arg_aux(x); // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}64 // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}65}66 67@interface Foo68- (void) passVal:(struct TestUninit)arg;69@end70void testFoo(Foo *o) {71 struct TestUninit x; // expected-note{{'x' initialized here}}72 [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}73 // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}74}75 76// Test case shows an uninitialized value being used in the LHS of a compound77// assignment.78void rdar_7780304(void) {79 typedef struct s_r7780304 { int x; } s_r7780304;80 s_r7780304 b;81 b.x |= 1; // expected-warning{{The left expression of the compound assignment uses uninitialized memory}}82 // expected-note@-1{{The left expression of the compound assignment uses uninitialized memory}}83}84 85 86// The flip side of PR10163 -- float arrays that are actually uninitialized87void test_PR10163(float);88void PR10163 (void) {89 float x[2];90 test_PR10163(x[1]); // expected-warning{{uninitialized value}}91 // expected-note@-1{{1st function call argument is an uninitialized value}}92}93 94// PR10163 -- don't warn for default-initialized float arrays.95void PR10163_default_initialized_arrays(void) {96 float x[2] = {0};97 test_PR10163(x[1]); // no-warning 98}99 100struct MyStr {101 int x;102 int y;103};104void swap(struct MyStr *To, struct MyStr *From) {105 // This is not really a swap but close enough for our test.106 To->x = From->x;107 To->y = From->y; // expected-note{{Uninitialized value stored to field 'y'}}108}109int test_undefined_member_assignment_in_swap(struct MyStr *s2) {110 struct MyStr s1;111 s1.x = 5;112 swap(s2, &s1); // expected-note{{Calling 'swap'}}113 // expected-note@-1{{Returning from 'swap'}}114 return s2->y; // expected-warning{{Undefined or garbage value returned to caller}}115 // expected-note@-1{{Undefined or garbage value returned to caller}}116}117 118@interface A119- (NSUInteger)foo;120@end121 122NSUInteger f8(A* x){123 const NSUInteger n = [x foo];124 int* bogus; 125 126 if (n > 0) { // tests const cast transfer function logic127 NSUInteger i;128 129 for (i = 0; i < n; ++i)130 bogus = 0;131 132 if (bogus) // no-warning133 return n+1;134 }135 136 return n;137}138 139 140 141 142typedef struct {143 float x;144 float y;145 float z;146} Point;147typedef struct {148 Point origin;149 int size;150} Circle;151 152Point makePoint(float x, float y) {153 Point result;154 result.x = x;155 result.y = y;156 result.z = 0.0;157 return result;158}159 160void PR14765_test(void) {161 Circle *testObj = calloc(1, sizeof(Circle));162 163 clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}164 // expected-note@-1{{TRUE}}165 166 testObj->origin = makePoint(0.0, 0.0);167 if (testObj->size > 0) { ; } // expected-note{{Assuming field 'size' is <= 0}}168 // expected-note@-1{{Taking false branch}}169 170 // FIXME: Assigning to 'testObj->origin' kills the default binding for the171 // whole region, meaning that we've forgotten that testObj->size should also172 // default to 0.173 // This should be TRUE.174 clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}175 // expected-note@-1{{UNKNOWN}}176 177 free(testObj);178}179 180void PR14765_argument(Circle *testObj) {181 int oldSize = testObj->size;182 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}183 // expected-note@-1{{TRUE}}184 185 testObj->origin = makePoint(0.0, 0.0);186 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}187 // expected-note@-1{{TRUE}}188}189 190 191typedef struct {192 int x;193 int y;194 int z;195} IntPoint;196typedef struct {197 IntPoint origin;198 int size;199} IntCircle;200 201IntPoint makeIntPoint(int x, int y) {202 IntPoint result;203 result.x = x;204 result.y = y;205 result.z = 0;206 return result;207}208 209void PR14765_test_int(void) {210 IntCircle *testObj = calloc(1, sizeof(IntCircle));211 212 clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}213 // expected-note@-1{{TRUE}}214 clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}215 // expected-note@-1{{TRUE}}216 clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}217 // expected-note@-1{{TRUE}}218 clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}219 // expected-note@-1{{TRUE}}220 221 testObj->origin = makeIntPoint(1, 2);222 if (testObj->size > 0) { ; } // expected-note{{Assuming field 'size' is <= 0}}223 // expected-note@-1{{Taking false branch}}224 // expected-note@-2{{Assuming field 'size' is <= 0}}225 // expected-note@-3{{Taking false branch}}226 // expected-note@-4{{Assuming field 'size' is <= 0}}227 // expected-note@-5{{Taking false branch}}228 // expected-note@-6{{Assuming field 'size' is <= 0}}229 // expected-note@-7{{Taking false branch}}230 231 // FIXME: Assigning to 'testObj->origin' kills the default binding for the232 // whole region, meaning that we've forgotten that testObj->size should also233 // default to 0.234 // This should be TRUE.235 clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}236 // expected-note@-1{{UNKNOWN}}237 clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}238 // expected-note@-1{{TRUE}}239 clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}240 // expected-note@-1{{TRUE}}241 clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}242 // expected-note@-1{{TRUE}}243 244 free(testObj);245}246 247void PR14765_argument_int(IntCircle *testObj) {248 int oldSize = testObj->size;249 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}250 // expected-note@-1{{TRUE}}251 252 testObj->origin = makeIntPoint(1, 2);253 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}254 // expected-note@-1{{TRUE}}255 clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}256 // expected-note@-1{{TRUE}}257 clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}258 // expected-note@-1{{TRUE}}259 clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}260 // expected-note@-1{{TRUE}}261}262 263 264void rdar13292559(Circle input) {265 extern void useCircle(Circle);266 267 Circle obj = input;268 useCircle(obj); // no-warning269 270 // This generated an "uninitialized 'size' field" warning for a (short) while.271 obj.origin = makePoint(0.0, 0.0);272 useCircle(obj); // no-warning273}274 275 276typedef struct {277 int x;278 int y;279} IntPoint2D;280typedef struct {281 IntPoint2D origin;282 int size;283} IntCircle2D;284 285IntPoint2D makeIntPoint2D(int x, int y) {286 IntPoint2D result;287 result.x = x;288 result.y = y;289 return result;290}291 292void testSmallStructsCopiedPerField(void) {293 IntPoint2D a;294 a.x = 0;295 296 IntPoint2D b = a;297 extern void useInt(int);298 useInt(b.x); // no-warning299 useInt(b.y); // expected-warning{{uninitialized}}300 // expected-note@-1{{uninitialized}}301}302 303void testLargeStructsNotCopiedPerField(void) {304 IntPoint a;305 a.x = 0;306 307 IntPoint b = a;308 extern void useInt(int);309 useInt(b.x); // no-warning310 useInt(b.y); // no-warning311}312 313void testSmallStructInLargerStruct(void) {314 IntCircle2D *testObj = calloc(1, sizeof(IntCircle2D));315 316 clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}317 // expected-note@-1{{TRUE}}318 clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}319 // expected-note@-1{{TRUE}}320 clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}321 // expected-note@-1{{TRUE}}322 323 testObj->origin = makeIntPoint2D(1, 2);324 if (testObj->size > 0) { ; } // expected-note{{Field 'size' is <= 0}}325 // expected-note@-1{{Taking false branch}}326 // expected-note@-2{{Field 'size' is <= 0}}327 // expected-note@-3{{Taking false branch}}328 // expected-note@-4{{Field 'size' is <= 0}}329 // expected-note@-5{{Taking false branch}}330 331 clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}332 // expected-note@-1{{TRUE}}333 clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}334 // expected-note@-1{{TRUE}}335 clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}336 // expected-note@-1{{TRUE}}337 338 free(testObj);339}340 341void testCopySmallStructIntoArgument(IntCircle2D *testObj) {342 int oldSize = testObj->size;343 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}344 // expected-note@-1{{TRUE}}345 346 testObj->origin = makeIntPoint2D(1, 2);347 clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}348 // expected-note@-1{{TRUE}}349 clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}350 // expected-note@-1{{TRUE}}351 clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}352 // expected-note@-1{{TRUE}}353}354 355void testSmallStructBitfields(void) {356 struct {357 int x : 4;358 int y : 4;359 } a, b;360 361 a.x = 1;362 a.y = 2;363 364 b = a;365 clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}366 // expected-note@-1{{TRUE}}367 clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}368 // expected-note@-1{{TRUE}}369}370 371void testSmallStructBitfieldsFirstUndef(void) {372 struct {373 int x : 4;374 int y : 4;375 } a, b;376 377 a.y = 2;378 379 b = a;380 clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}381 // expected-note@-1{{TRUE}}382 clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}383 // expected-note@-1{{garbage}}384}385 386void testSmallStructBitfieldsSecondUndef(void) {387 struct {388 int x : 4;389 int y : 4;390 } a, b;391 392 a.x = 1;393 394 b = a;395 clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}396 // expected-note@-1{{TRUE}}397 clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}398 // expected-note@-1{{garbage}}399}400 401void testSmallStructBitfieldsFirstUnnamed(void) {402 struct {403 int : 4;404 int y : 4;405 } a, b, c; // expected-note{{'c' initialized here}}406 407 a.y = 2;408 409 b = a;410 clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}411 // expected-note@-1{{TRUE}}412 413 b = c; // expected-note{{Uninitialized value stored to 'b.y'}}414 clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}415 // expected-note@-1{{garbage}}416}417 418void testSmallStructBitfieldsSecondUnnamed(void) {419 struct {420 int x : 4;421 int : 4;422 } a, b, c; // expected-note{{'c' initialized here}}423 424 a.x = 1;425 426 b = a;427 clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}428 // expected-note@-1{{TRUE}}429 430 b = c; // expected-note{{Uninitialized value stored to 'b.x'}}431 clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}432 // expected-note@-1{{garbage}}433}434