misc-ps-region-store.cpp revision e42a0ab77ca4ad5201591aac5679ef47a08af4b6
1// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s 2// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s 3 4// Test basic handling of references. 5char &test1_aux(); 6char *test1() { 7 return &test1_aux(); 8} 9 10// Test test1_aux() evaluates to char &. 11char test1_as_rvalue() { 12 return test1_aux(); 13} 14 15// Test passing a value as a reference. The 'const' in test2_aux() adds 16// an ImplicitCastExpr, which is evaluated as an lvalue. 17int test2_aux(const int &n); 18int test2(int n) { 19 return test2_aux(n); 20} 21 22int test2_b_aux(const short &n); 23int test2_b(int n) { 24 return test2_b_aux(n); 25} 26 27// Test getting the lvalue of a derived and converting it to a base. This 28// previously crashed. 29class Test3_Base {}; 30class Test3_Derived : public Test3_Base {}; 31 32int test3_aux(Test3_Base &x); 33int test3(Test3_Derived x) { 34 return test3_aux(x); 35} 36 37//===---------------------------------------------------------------------===// 38// Test CFG support for C++ condition variables. 39//===---------------------------------------------------------------------===// 40 41int test_init_in_condition_aux(); 42int test_init_in_condition() { 43 if (int x = test_init_in_condition_aux()) { // no-warning 44 return 1; 45 } 46 return 0; 47} 48 49int test_init_in_condition_switch() { 50 switch (int x = test_init_in_condition_aux()) { // no-warning 51 case 1: 52 return 0; 53 case 2: 54 if (x == 2) 55 return 0; 56 else { 57 // Unreachable. 58 int *p = 0; 59 *p = 0xDEADBEEF; // no-warning 60 } 61 default: 62 break; 63 } 64 return 0; 65} 66 67int test_init_in_condition_while() { 68 int z = 0; 69 while (int x = ++z) { // no-warning 70 if (x == 2) 71 break; 72 } 73 74 if (z == 2) 75 return 0; 76 77 int *p = 0; 78 *p = 0xDEADBEEF; // no-warning 79 return 0; 80} 81 82 83int test_init_in_condition_for() { 84 int z = 0; 85 for (int x = 0; int y = ++z; ++x) { 86 if (x == y) // no-warning 87 break; 88 } 89 if (z == 1) 90 return 0; 91 92 int *p = 0; 93 *p = 0xDEADBEEF; // no-warning 94 return 0; 95} 96 97//===---------------------------------------------------------------------===// 98// Test handling of 'this' pointer. 99//===---------------------------------------------------------------------===// 100 101class TestHandleThis { 102 int x; 103 104 TestHandleThis(); 105 int foo(); 106 int null_deref_negative(); 107 int null_deref_positive(); 108}; 109 110int TestHandleThis::foo() { 111 // Assume that 'x' is initialized. 112 return x + 1; // no-warning 113} 114 115int TestHandleThis::null_deref_negative() { 116 x = 10; 117 if (x == 10) { 118 return 1; 119 } 120 int *p = 0; 121 *p = 0xDEADBEEF; // no-warning 122 return 0; 123} 124 125int TestHandleThis::null_deref_positive() { 126 x = 10; 127 if (x == 9) { 128 return 1; 129 } 130 int *p = 0; 131 *p = 0xDEADBEEF; // expected-warning{{null pointer}} 132 return 0; 133} 134 135// PR 7675 - passing literals by-reference 136void pr7675(const double &a); 137void pr7675(const int &a); 138void pr7675(const char &a); 139void pr7675_i(const _Complex double &a); 140 141void pr7675_test() { 142 pr7675(10.0); 143 pr7675(10); 144 pr7675('c'); 145 pr7675_i(4.0i); 146 // Add null deref to ensure we are analyzing the code up to this point. 147 int *p = 0; 148 *p = 0xDEADBEEF; // expected-warning{{null pointer}} 149} 150 151// <rdar://problem/8375510> - CFGBuilder should handle temporaries. 152struct R8375510 { 153 R8375510(); 154 ~R8375510(); 155 R8375510 operator++(int); 156}; 157 158int r8375510(R8375510 x, R8375510 y) { 159 for (; ; x++) { } 160} 161 162// PR8419 -- this used to crash. 163 164class String8419 { 165 public: 166 char& get(int n); 167 char& operator[](int n); 168}; 169 170char& get8419(); 171 172void Test8419() { 173 String8419 s; 174 ++(s.get(0)); 175 get8419()--; // used to crash 176 --s[0]; // used to crash 177 s[0] &= 1; // used to crash 178 s[0]++; // used to crash 179} 180 181// PR8426 -- this used to crash. 182 183void Use(void* to); 184 185template <class T> class Foo { 186 ~Foo(); 187 struct Bar; 188 Bar* bar_; 189}; 190 191template <class T> Foo<T>::~Foo() { 192 Use(bar_); 193 T::DoSomething(); 194 bar_->Work(); 195} 196 197// PR8427 -- this used to crash. 198 199class Dummy {}; 200 201bool operator==(Dummy, int); 202 203template <typename T> 204class Foo2 { 205 bool Bar(); 206}; 207 208template <typename T> 209bool Foo2<T>::Bar() { 210 return 0 == T(); 211} 212 213// PR8433 -- this used to crash. 214 215template <typename T> 216class Foo3 { 217 public: 218 void Bar(); 219 void Baz(); 220 T value_; 221}; 222 223template <typename T> 224void Foo3<T>::Bar() { 225 Baz(); 226 value_(); 227} 228 229//===---------------------------------------------------------------------===// 230// Handle misc. C++ constructs. 231//===---------------------------------------------------------------------===// 232 233namespace fum { 234 int i = 3; 235}; 236 237void test_namespace() { 238 // Previously triggered a crash. 239 using namespace fum; 240 int x = i; 241} 242 243// Test handling methods that accept references as parameters, and that 244// variables are properly invalidated. 245class RDar9203355 { 246 bool foo(unsigned valA, long long &result) const; 247 bool foo(unsigned valA, int &result) const; 248}; 249bool RDar9203355::foo(unsigned valA, int &result) const { 250 long long val; 251 if (foo(valA, val) || 252 (int)val != val) // no-warning 253 return true; 254 result = val; // no-warning 255 return false; 256} 257 258// Test handling of new[]. 259void rdar9212512() { 260 int *x = new int[10]; 261 for (unsigned i = 0 ; i < 2 ; ++i) { 262 // This previously triggered an uninitialized values warning. 263 x[i] = 1; // no-warning 264 } 265} 266 267// Test basic support for dynamic_cast<>. 268struct Rdar9212495_C { virtual void bar() const; }; 269class Rdar9212495_B : public Rdar9212495_C {}; 270class Rdar9212495_A : public Rdar9212495_B {}; 271const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) { 272 const Rdar9212495_A& val = dynamic_cast<const Rdar9212495_A&>(*ptr); 273 274 if (&val == 0) { 275 val.bar(); // FIXME: This should eventually be a null dereference. 276 } 277 278 return val; 279} 280 281// Test constructors invalidating arguments. Previously this raised 282// an uninitialized value warning. 283extern "C" void __attribute__((noreturn)) PR9645_exit(int i); 284 285class PR9645_SideEffect 286{ 287public: 288 PR9645_SideEffect(int *pi); // caches pi in i_ 289 void Read(int *pi); // copies *pi into *i_ 290private: 291 int *i_; 292}; 293 294void PR9645() { 295 int i; 296 297 PR9645_SideEffect se(&i); 298 int j = 1; 299 se.Read(&j); // this has a side-effect of initializing i. 300 301 PR9645_exit(i); // no-warning 302} 303 304PR9645_SideEffect::PR9645_SideEffect(int *pi) : i_(pi) {} 305void PR9645_SideEffect::Read(int *pi) { *i_ = *pi; } 306 307// Invalidate fields during C++ method calls. 308class RDar9267815 { 309 int x; 310 void test(); 311 void test_pos(); 312 void test2(); 313 void invalidate(); 314}; 315 316void RDar9267815::test_pos() { 317 int *p = 0; 318 if (x == 42) 319 return; 320 *p = 0xDEADBEEF; // expected-warning {{null}} 321} 322void RDar9267815::test() { 323 int *p = 0; 324 if (x == 42) 325 return; 326 if (x == 42) 327 *p = 0xDEADBEEF; // no-warning 328} 329 330void RDar9267815::test2() { 331 int *p = 0; 332 if (x == 42) 333 return; 334 invalidate(); 335 if (x == 42) 336 *p = 0xDEADBEEF; // expected-warning {{null}} 337} 338 339// Test reference parameters. 340void test_ref_double_aux(double &Value); 341float test_ref_double() { 342 double dVal; 343 test_ref_double_aux(dVal); 344 // This previously warned because 'dVal' was thought to be uninitialized. 345 float Val = (float)dVal; // no-warning 346 return Val; 347} 348 349// Test invalidation of class fields. 350class TestInvalidateClass { 351public: 352 int x; 353}; 354 355void test_invalidate_class_aux(TestInvalidateClass &x); 356 357int test_invalidate_class() { 358 TestInvalidateClass y; 359 test_invalidate_class_aux(y); 360 return y.x; // no-warning 361} 362 363// Test correct pointer arithmetic using 'p--'. This is to warn that we 364// were loading beyond the written characters in buf. 365char *RDar9269695(char *dst, unsigned int n) 366{ 367 char buff[40], *p; 368 369 p = buff; 370 do 371 *p++ = '0' + n % 10; 372 while (n /= 10); 373 374 do 375 *dst++ = *--p; // no-warning 376 while (p != buff); 377 378 return dst; 379} 380 381// Test that we invalidate byref arguments passed to constructors. 382class TestInvalidateInCtor { 383public: 384 TestInvalidateInCtor(unsigned &x); 385}; 386 387unsigned test_invalidate_in_ctor() { 388 unsigned x; 389 TestInvalidateInCtor foo(x); 390 return x; // no-warning 391} 392unsigned test_invalidate_in_ctor_new() { 393 unsigned x; 394 delete (new TestInvalidateInCtor(x)); 395 return x; // no-warning 396} 397 398// Test assigning into a symbolic offset. 399struct TestAssignIntoSymbolicOffset { 400 int **stuff[100]; 401 void test(int x, int y); 402}; 403 404void TestAssignIntoSymbolicOffset::test(int x, int y) { 405 x--; 406 if (x > 8 || x < 0) 407 return; 408 if (stuff[x]) 409 return; 410 if (!stuff[x]) { 411 stuff[x] = new int*[y+1]; 412 // Previously triggered a null dereference. 413 stuff[x][y] = 0; // no-warning 414 } 415} 416 417// Test loads from static fields. This previously triggered an uninitialized 418// value warning. 419class ClassWithStatic { 420public: 421 static const unsigned value = 1; 422}; 423 424int rdar9948787_negative() { 425 ClassWithStatic classWithStatic; 426 unsigned value = classWithStatic.value; 427 if (value == 1) 428 return 1; 429 int *p = 0; 430 *p = 0xDEADBEEF; // no-warning 431 return 0; 432} 433 434int rdar9948787_positive() { 435 ClassWithStatic classWithStatic; 436 unsigned value = classWithStatic.value; 437 if (value == 0) 438 return 1; 439 int *p = 0; 440 *p = 0xDEADBEEF; // expected-warning {{null}} 441 return 0; 442} 443 444// Regression test against global constants and switches. 445enum rdar10202899_ValT { rdar10202899_ValTA, rdar10202899_ValTB, rdar10202899_ValTC }; 446const rdar10202899_ValT val = rdar10202899_ValTA; 447void rdar10202899_test1() { 448 switch (val) { 449 case rdar10202899_ValTA: {} 450 }; 451} 452 453void rdar10202899_test2() { 454 if (val == rdar10202899_ValTA) 455 return; 456 int *p = 0; 457 *p = 0xDEADBEEF; 458} 459 460void rdar10202899_test3() { 461 switch (val) { 462 case rdar10202899_ValTA: return; 463 default: ; 464 }; 465 int *p = 0; 466 *p = 0xDEADBEEF; 467} 468 469// This used to crash the analyzer because of the unnamed bitfield. 470void PR11249() 471{ 472 struct { 473 char f1:4; 474 char :4; 475 char f2[1]; 476 char f3; 477 } V = { 1, {2}, 3 }; 478 int *p = 0; 479 if (V.f1 != 1) 480 *p = 0xDEADBEEF; // no-warning 481 if (V.f2[0] != 2) 482 *p = 0xDEADBEEF; // no-warning 483 if (V.f3 != 3) 484 *p = 0xDEADBEEF; // no-warning 485} 486 487