Stephen Hines | c568f1e | 2014-07-21 00:47:37 -0700 | [diff] [blame] | 1 | // RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare |
| 2 | // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 3 | |
| 4 | void clang_analyzer_warnIfReached(); |
Ted Kremenek | d87682e | 2009-12-17 01:44:13 +0000 | [diff] [blame] | 5 | |
Ted Kremenek | 5328751 | 2009-12-18 20:13:39 +0000 | [diff] [blame] | 6 | // Test basic handling of references. |
Ted Kremenek | d87682e | 2009-12-17 01:44:13 +0000 | [diff] [blame] | 7 | char &test1_aux(); |
| 8 | char *test1() { |
| 9 | return &test1_aux(); |
| 10 | } |
Ted Kremenek | 5328751 | 2009-12-18 20:13:39 +0000 | [diff] [blame] | 11 | |
Zhongxing Xu | 910e408 | 2009-12-19 03:17:55 +0000 | [diff] [blame] | 12 | // Test test1_aux() evaluates to char &. |
Ted Kremenek | 5328751 | 2009-12-18 20:13:39 +0000 | [diff] [blame] | 13 | char test1_as_rvalue() { |
| 14 | return test1_aux(); |
| 15 | } |
| 16 | |
Ted Kremenek | 949bdb4 | 2009-12-23 00:26:16 +0000 | [diff] [blame] | 17 | // Test passing a value as a reference. The 'const' in test2_aux() adds |
| 18 | // an ImplicitCastExpr, which is evaluated as an lvalue. |
| 19 | int test2_aux(const int &n); |
| 20 | int test2(int n) { |
| 21 | return test2_aux(n); |
| 22 | } |
| 23 | |
| 24 | int test2_b_aux(const short &n); |
| 25 | int test2_b(int n) { |
| 26 | return test2_b_aux(n); |
| 27 | } |
Ted Kremenek | 077a40d | 2009-12-23 01:19:20 +0000 | [diff] [blame] | 28 | |
| 29 | // Test getting the lvalue of a derived and converting it to a base. This |
| 30 | // previously crashed. |
| 31 | class Test3_Base {}; |
| 32 | class Test3_Derived : public Test3_Base {}; |
| 33 | |
| 34 | int test3_aux(Test3_Base &x); |
| 35 | int test3(Test3_Derived x) { |
| 36 | return test3_aux(x); |
| 37 | } |
| 38 | |
Ted Kremenek | de0d263 | 2010-01-05 02:18:06 +0000 | [diff] [blame] | 39 | //===---------------------------------------------------------------------===// |
| 40 | // Test CFG support for C++ condition variables. |
| 41 | //===---------------------------------------------------------------------===// |
| 42 | |
Ted Kremenek | 61dfbec | 2009-12-23 04:49:01 +0000 | [diff] [blame] | 43 | int test_init_in_condition_aux(); |
| 44 | int test_init_in_condition() { |
| 45 | if (int x = test_init_in_condition_aux()) { // no-warning |
| 46 | return 1; |
| 47 | } |
| 48 | return 0; |
| 49 | } |
Ted Kremenek | fcfb503 | 2009-12-24 00:40:03 +0000 | [diff] [blame] | 50 | |
| 51 | int test_init_in_condition_switch() { |
| 52 | switch (int x = test_init_in_condition_aux()) { // no-warning |
| 53 | case 1: |
| 54 | return 0; |
| 55 | case 2: |
| 56 | if (x == 2) |
| 57 | return 0; |
| 58 | else { |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 59 | clang_analyzer_warnIfReached(); // unreachable |
Ted Kremenek | fcfb503 | 2009-12-24 00:40:03 +0000 | [diff] [blame] | 60 | } |
| 61 | default: |
| 62 | break; |
| 63 | } |
| 64 | return 0; |
| 65 | } |
Ted Kremenek | 4c508a1 | 2009-12-24 00:54:56 +0000 | [diff] [blame] | 66 | |
| 67 | int test_init_in_condition_while() { |
Ted Kremenek | 4ec010a | 2009-12-24 01:34:10 +0000 | [diff] [blame] | 68 | int z = 0; |
| 69 | while (int x = ++z) { // no-warning |
| 70 | if (x == 2) |
Ted Kremenek | 4c508a1 | 2009-12-24 00:54:56 +0000 | [diff] [blame] | 71 | break; |
Ted Kremenek | 4c508a1 | 2009-12-24 00:54:56 +0000 | [diff] [blame] | 72 | } |
Ted Kremenek | 4ec010a | 2009-12-24 01:34:10 +0000 | [diff] [blame] | 73 | |
| 74 | if (z == 2) |
| 75 | return 0; |
| 76 | |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 77 | clang_analyzer_warnIfReached(); // unreachable |
Ted Kremenek | 4c508a1 | 2009-12-24 00:54:56 +0000 | [diff] [blame] | 78 | return 0; |
| 79 | } |
Ted Kremenek | 4ec010a | 2009-12-24 01:34:10 +0000 | [diff] [blame] | 80 | |
Ted Kremenek | dd8b441 | 2009-12-24 02:41:19 +0000 | [diff] [blame] | 81 | |
| 82 | int test_init_in_condition_for() { |
| 83 | int z = 0; |
| 84 | for (int x = 0; int y = ++z; ++x) { |
| 85 | if (x == y) // no-warning |
| 86 | break; |
| 87 | } |
| 88 | if (z == 1) |
| 89 | return 0; |
| 90 | |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 91 | clang_analyzer_warnIfReached(); // unreachable |
Ted Kremenek | dd8b441 | 2009-12-24 02:41:19 +0000 | [diff] [blame] | 92 | return 0; |
| 93 | } |
Ted Kremenek | de0d263 | 2010-01-05 02:18:06 +0000 | [diff] [blame] | 94 | |
| 95 | //===---------------------------------------------------------------------===// |
| 96 | // Test handling of 'this' pointer. |
| 97 | //===---------------------------------------------------------------------===// |
| 98 | |
| 99 | class TestHandleThis { |
| 100 | int x; |
| 101 | |
| 102 | TestHandleThis(); |
| 103 | int foo(); |
| 104 | int null_deref_negative(); |
| 105 | int null_deref_positive(); |
| 106 | }; |
| 107 | |
| 108 | int TestHandleThis::foo() { |
| 109 | // Assume that 'x' is initialized. |
| 110 | return x + 1; // no-warning |
| 111 | } |
| 112 | |
| 113 | int TestHandleThis::null_deref_negative() { |
| 114 | x = 10; |
| 115 | if (x == 10) { |
| 116 | return 1; |
| 117 | } |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 118 | clang_analyzer_warnIfReached(); // unreachable |
Ted Kremenek | de0d263 | 2010-01-05 02:18:06 +0000 | [diff] [blame] | 119 | return 0; |
| 120 | } |
| 121 | |
| 122 | int TestHandleThis::null_deref_positive() { |
| 123 | x = 10; |
| 124 | if (x == 9) { |
| 125 | return 1; |
| 126 | } |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 127 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Ted Kremenek | de0d263 | 2010-01-05 02:18:06 +0000 | [diff] [blame] | 128 | return 0; |
| 129 | } |
| 130 | |
Ted Kremenek | 741b9be | 2010-07-29 01:31:59 +0000 | [diff] [blame] | 131 | // PR 7675 - passing literals by-reference |
| 132 | void pr7675(const double &a); |
| 133 | void pr7675(const int &a); |
| 134 | void pr7675(const char &a); |
| 135 | void pr7675_i(const _Complex double &a); |
| 136 | |
| 137 | void pr7675_test() { |
| 138 | pr7675(10.0); |
| 139 | pr7675(10); |
| 140 | pr7675('c'); |
| 141 | pr7675_i(4.0i); |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 142 | |
| 143 | // Add check to ensure we are analyzing the code up to this point. |
| 144 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Ted Kremenek | 741b9be | 2010-07-29 01:31:59 +0000 | [diff] [blame] | 145 | } |
| 146 | |
Ted Kremenek | a427f1d | 2010-08-31 18:47:34 +0000 | [diff] [blame] | 147 | // <rdar://problem/8375510> - CFGBuilder should handle temporaries. |
| 148 | struct R8375510 { |
| 149 | R8375510(); |
| 150 | ~R8375510(); |
| 151 | R8375510 operator++(int); |
| 152 | }; |
| 153 | |
| 154 | int r8375510(R8375510 x, R8375510 y) { |
| 155 | for (; ; x++) { } |
| 156 | } |
| 157 | |
Zhanyong Wan | 99cae5b | 2010-11-22 08:45:56 +0000 | [diff] [blame] | 158 | // PR8419 -- this used to crash. |
| 159 | |
| 160 | class String8419 { |
| 161 | public: |
| 162 | char& get(int n); |
| 163 | char& operator[](int n); |
| 164 | }; |
| 165 | |
| 166 | char& get8419(); |
| 167 | |
| 168 | void Test8419() { |
| 169 | String8419 s; |
| 170 | ++(s.get(0)); |
| 171 | get8419()--; // used to crash |
| 172 | --s[0]; // used to crash |
| 173 | s[0] &= 1; // used to crash |
| 174 | s[0]++; // used to crash |
| 175 | } |
| 176 | |
Zhanyong Wan | 739830d | 2010-10-31 04:22:34 +0000 | [diff] [blame] | 177 | // PR8426 -- this used to crash. |
| 178 | |
| 179 | void Use(void* to); |
| 180 | |
| 181 | template <class T> class Foo { |
| 182 | ~Foo(); |
| 183 | struct Bar; |
| 184 | Bar* bar_; |
| 185 | }; |
| 186 | |
| 187 | template <class T> Foo<T>::~Foo() { |
| 188 | Use(bar_); |
| 189 | T::DoSomething(); |
| 190 | bar_->Work(); |
| 191 | } |
| 192 | |
| 193 | // PR8427 -- this used to crash. |
| 194 | |
| 195 | class Dummy {}; |
| 196 | |
| 197 | bool operator==(Dummy, int); |
| 198 | |
| 199 | template <typename T> |
| 200 | class Foo2 { |
| 201 | bool Bar(); |
| 202 | }; |
| 203 | |
| 204 | template <typename T> |
| 205 | bool Foo2<T>::Bar() { |
| 206 | return 0 == T(); |
| 207 | } |
| 208 | |
| 209 | // PR8433 -- this used to crash. |
| 210 | |
| 211 | template <typename T> |
| 212 | class Foo3 { |
| 213 | public: |
| 214 | void Bar(); |
| 215 | void Baz(); |
| 216 | T value_; |
| 217 | }; |
| 218 | |
| 219 | template <typename T> |
| 220 | void Foo3<T>::Bar() { |
| 221 | Baz(); |
| 222 | value_(); |
| 223 | } |
Ted Kremenek | b8b07b1 | 2011-02-14 17:00:16 +0000 | [diff] [blame] | 224 | |
| 225 | //===---------------------------------------------------------------------===// |
| 226 | // Handle misc. C++ constructs. |
| 227 | //===---------------------------------------------------------------------===// |
| 228 | |
| 229 | namespace fum { |
| 230 | int i = 3; |
| 231 | }; |
| 232 | |
| 233 | void test_namespace() { |
| 234 | // Previously triggered a crash. |
| 235 | using namespace fum; |
| 236 | int x = i; |
| 237 | } |
| 238 | |
Ted Kremenek | b277159 | 2011-03-30 17:41:19 +0000 | [diff] [blame] | 239 | // Test handling methods that accept references as parameters, and that |
| 240 | // variables are properly invalidated. |
| 241 | class RDar9203355 { |
| 242 | bool foo(unsigned valA, long long &result) const; |
| 243 | bool foo(unsigned valA, int &result) const; |
| 244 | }; |
| 245 | bool RDar9203355::foo(unsigned valA, int &result) const { |
| 246 | long long val; |
| 247 | if (foo(valA, val) || |
| 248 | (int)val != val) // no-warning |
| 249 | return true; |
| 250 | result = val; // no-warning |
| 251 | return false; |
| 252 | } |
| 253 | |
Ted Kremenek | 41c5f49 | 2011-03-31 04:04:48 +0000 | [diff] [blame] | 254 | // Test handling of new[]. |
| 255 | void rdar9212512() { |
| 256 | int *x = new int[10]; |
| 257 | for (unsigned i = 0 ; i < 2 ; ++i) { |
| 258 | // This previously triggered an uninitialized values warning. |
| 259 | x[i] = 1; // no-warning |
| 260 | } |
| 261 | } |
Ted Kremenek | b277159 | 2011-03-30 17:41:19 +0000 | [diff] [blame] | 262 | |
Ted Kremenek | 94ae8fd | 2011-03-31 04:46:53 +0000 | [diff] [blame] | 263 | // Test basic support for dynamic_cast<>. |
| 264 | struct Rdar9212495_C { virtual void bar() const; }; |
| 265 | class Rdar9212495_B : public Rdar9212495_C {}; |
| 266 | class Rdar9212495_A : public Rdar9212495_B {}; |
| 267 | const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) { |
| 268 | const Rdar9212495_A& val = dynamic_cast<const Rdar9212495_A&>(*ptr); |
| 269 | |
Jordan Rose | 9f3b9d5 | 2012-08-02 21:33:42 +0000 | [diff] [blame] | 270 | // This is not valid C++; dynamic_cast with a reference type will throw an |
Jordan Rose | a869518 | 2012-08-04 01:04:52 +0000 | [diff] [blame] | 271 | // exception if the pointer does not match the expected type. However, our |
| 272 | // implementation of dynamic_cast will pass through a null pointer...or a |
| 273 | // "null reference"! So this branch is actually possible. |
Ted Kremenek | 94ae8fd | 2011-03-31 04:46:53 +0000 | [diff] [blame] | 274 | if (&val == 0) { |
Jordan Rose | a869518 | 2012-08-04 01:04:52 +0000 | [diff] [blame] | 275 | val.bar(); // expected-warning{{Called C++ object pointer is null}} |
Ted Kremenek | 94ae8fd | 2011-03-31 04:46:53 +0000 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | return val; |
| 279 | } |
| 280 | |
Jordan Rose | 9f3b9d5 | 2012-08-02 21:33:42 +0000 | [diff] [blame] | 281 | const Rdar9212495_A* rdar9212495_ptr(const Rdar9212495_C* ptr) { |
| 282 | const Rdar9212495_A* val = dynamic_cast<const Rdar9212495_A*>(ptr); |
| 283 | |
| 284 | if (val == 0) { |
| 285 | val->bar(); // expected-warning{{Called C++ object pointer is null}} |
| 286 | } |
| 287 | |
| 288 | return val; |
| 289 | } |
| 290 | |
Ted Kremenek | 5fe9872 | 2011-04-08 22:42:35 +0000 | [diff] [blame] | 291 | // Test constructors invalidating arguments. Previously this raised |
| 292 | // an uninitialized value warning. |
| 293 | extern "C" void __attribute__((noreturn)) PR9645_exit(int i); |
| 294 | |
| 295 | class PR9645_SideEffect |
| 296 | { |
| 297 | public: |
| 298 | PR9645_SideEffect(int *pi); // caches pi in i_ |
| 299 | void Read(int *pi); // copies *pi into *i_ |
| 300 | private: |
| 301 | int *i_; |
| 302 | }; |
| 303 | |
| 304 | void PR9645() { |
| 305 | int i; |
| 306 | |
| 307 | PR9645_SideEffect se(&i); |
| 308 | int j = 1; |
| 309 | se.Read(&j); // this has a side-effect of initializing i. |
| 310 | |
| 311 | PR9645_exit(i); // no-warning |
| 312 | } |
| 313 | |
| 314 | PR9645_SideEffect::PR9645_SideEffect(int *pi) : i_(pi) {} |
| 315 | void PR9645_SideEffect::Read(int *pi) { *i_ = *pi; } |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 316 | |
| 317 | // Invalidate fields during C++ method calls. |
| 318 | class RDar9267815 { |
| 319 | int x; |
| 320 | void test(); |
| 321 | void test_pos(); |
| 322 | void test2(); |
| 323 | void invalidate(); |
| 324 | }; |
| 325 | |
| 326 | void RDar9267815::test_pos() { |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 327 | if (x == 42) |
| 328 | return; |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 329 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 330 | } |
| 331 | void RDar9267815::test() { |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 332 | if (x == 42) |
| 333 | return; |
| 334 | if (x == 42) |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 335 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 336 | } |
| 337 | |
| 338 | void RDar9267815::test2() { |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 339 | if (x == 42) |
| 340 | return; |
| 341 | invalidate(); |
| 342 | if (x == 42) |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 343 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Ted Kremenek | 9fec9b1 | 2011-04-11 22:22:05 +0000 | [diff] [blame] | 344 | } |
| 345 | |
Ted Kremenek | 235c02f | 2011-04-12 00:28:12 +0000 | [diff] [blame] | 346 | // Test reference parameters. |
| 347 | void test_ref_double_aux(double &Value); |
| 348 | float test_ref_double() { |
| 349 | double dVal; |
| 350 | test_ref_double_aux(dVal); |
| 351 | // This previously warned because 'dVal' was thought to be uninitialized. |
| 352 | float Val = (float)dVal; // no-warning |
| 353 | return Val; |
| 354 | } |
| 355 | |
Ted Kremenek | bf1a667 | 2011-04-12 00:44:31 +0000 | [diff] [blame] | 356 | // Test invalidation of class fields. |
| 357 | class TestInvalidateClass { |
| 358 | public: |
| 359 | int x; |
| 360 | }; |
| 361 | |
| 362 | void test_invalidate_class_aux(TestInvalidateClass &x); |
| 363 | |
| 364 | int test_invalidate_class() { |
| 365 | TestInvalidateClass y; |
| 366 | test_invalidate_class_aux(y); |
| 367 | return y.x; // no-warning |
| 368 | } |
| 369 | |
Ted Kremenek | 3bab50b | 2011-04-12 03:49:37 +0000 | [diff] [blame] | 370 | // Test correct pointer arithmetic using 'p--'. This is to warn that we |
| 371 | // were loading beyond the written characters in buf. |
| 372 | char *RDar9269695(char *dst, unsigned int n) |
| 373 | { |
| 374 | char buff[40], *p; |
| 375 | |
| 376 | p = buff; |
| 377 | do |
| 378 | *p++ = '0' + n % 10; |
| 379 | while (n /= 10); |
| 380 | |
| 381 | do |
| 382 | *dst++ = *--p; // no-warning |
| 383 | while (p != buff); |
| 384 | |
| 385 | return dst; |
| 386 | } |
| 387 | |
Ted Kremenek | 9d5d308 | 2011-04-12 05:12:39 +0000 | [diff] [blame] | 388 | // Test that we invalidate byref arguments passed to constructors. |
| 389 | class TestInvalidateInCtor { |
| 390 | public: |
| 391 | TestInvalidateInCtor(unsigned &x); |
| 392 | }; |
| 393 | |
| 394 | unsigned test_invalidate_in_ctor() { |
| 395 | unsigned x; |
| 396 | TestInvalidateInCtor foo(x); |
| 397 | return x; // no-warning |
| 398 | } |
| 399 | unsigned test_invalidate_in_ctor_new() { |
| 400 | unsigned x; |
| 401 | delete (new TestInvalidateInCtor(x)); |
| 402 | return x; // no-warning |
| 403 | } |
Ted Kremenek | 3bab50b | 2011-04-12 03:49:37 +0000 | [diff] [blame] | 404 | |
Ted Kremenek | c46d641 | 2011-05-19 23:37:58 +0000 | [diff] [blame] | 405 | // Test assigning into a symbolic offset. |
| 406 | struct TestAssignIntoSymbolicOffset { |
| 407 | int **stuff[100]; |
| 408 | void test(int x, int y); |
| 409 | }; |
| 410 | |
| 411 | void TestAssignIntoSymbolicOffset::test(int x, int y) { |
| 412 | x--; |
| 413 | if (x > 8 || x < 0) |
| 414 | return; |
| 415 | if (stuff[x]) |
| 416 | return; |
| 417 | if (!stuff[x]) { |
| 418 | stuff[x] = new int*[y+1]; |
| 419 | // Previously triggered a null dereference. |
| 420 | stuff[x][y] = 0; // no-warning |
| 421 | } |
| 422 | } |
| 423 | |
Ted Kremenek | 5bd0495 | 2011-08-16 21:37:52 +0000 | [diff] [blame] | 424 | // Test loads from static fields. This previously triggered an uninitialized |
| 425 | // value warning. |
| 426 | class ClassWithStatic { |
| 427 | public: |
| 428 | static const unsigned value = 1; |
| 429 | }; |
| 430 | |
| 431 | int rdar9948787_negative() { |
| 432 | ClassWithStatic classWithStatic; |
| 433 | unsigned value = classWithStatic.value; |
| 434 | if (value == 1) |
| 435 | return 1; |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 436 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | 5bd0495 | 2011-08-16 21:37:52 +0000 | [diff] [blame] | 437 | return 0; |
| 438 | } |
| 439 | |
| 440 | int rdar9948787_positive() { |
| 441 | ClassWithStatic classWithStatic; |
| 442 | unsigned value = classWithStatic.value; |
| 443 | if (value == 0) |
| 444 | return 1; |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 445 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Ted Kremenek | 5bd0495 | 2011-08-16 21:37:52 +0000 | [diff] [blame] | 446 | return 0; |
| 447 | } |
| 448 | |
Ted Kremenek | e4c6675 | 2011-09-30 03:51:54 +0000 | [diff] [blame] | 449 | // Regression test against global constants and switches. |
| 450 | enum rdar10202899_ValT { rdar10202899_ValTA, rdar10202899_ValTB, rdar10202899_ValTC }; |
| 451 | const rdar10202899_ValT val = rdar10202899_ValTA; |
| 452 | void rdar10202899_test1() { |
| 453 | switch (val) { |
| 454 | case rdar10202899_ValTA: {} |
| 455 | }; |
| 456 | } |
| 457 | |
| 458 | void rdar10202899_test2() { |
| 459 | if (val == rdar10202899_ValTA) |
| 460 | return; |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 461 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | e4c6675 | 2011-09-30 03:51:54 +0000 | [diff] [blame] | 462 | } |
| 463 | |
| 464 | void rdar10202899_test3() { |
| 465 | switch (val) { |
| 466 | case rdar10202899_ValTA: return; |
| 467 | default: ; |
| 468 | }; |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 469 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | e4c6675 | 2011-09-30 03:51:54 +0000 | [diff] [blame] | 470 | } |
| 471 | |
Jim Goodnow II | e42a0ab | 2011-11-16 20:29:27 +0000 | [diff] [blame] | 472 | // This used to crash the analyzer because of the unnamed bitfield. |
| 473 | void PR11249() |
| 474 | { |
| 475 | struct { |
| 476 | char f1:4; |
| 477 | char :4; |
| 478 | char f2[1]; |
| 479 | char f3; |
| 480 | } V = { 1, {2}, 3 }; |
Jim Goodnow II | e42a0ab | 2011-11-16 20:29:27 +0000 | [diff] [blame] | 481 | if (V.f1 != 1) |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 482 | clang_analyzer_warnIfReached(); // no-warning |
Jim Goodnow II | e42a0ab | 2011-11-16 20:29:27 +0000 | [diff] [blame] | 483 | if (V.f2[0] != 2) |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 484 | clang_analyzer_warnIfReached(); // no-warning |
Jim Goodnow II | e42a0ab | 2011-11-16 20:29:27 +0000 | [diff] [blame] | 485 | if (V.f3 != 3) |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 486 | clang_analyzer_warnIfReached(); // no-warning |
Jim Goodnow II | e42a0ab | 2011-11-16 20:29:27 +0000 | [diff] [blame] | 487 | } |
Ted Kremenek | e4c6675 | 2011-09-30 03:51:54 +0000 | [diff] [blame] | 488 | |
Ted Kremenek | 214323b | 2011-11-29 19:39:29 +0000 | [diff] [blame] | 489 | // Handle doing a load from the memory associated with the code for |
| 490 | // a function. |
| 491 | extern double nan( const char * ); |
| 492 | double PR11450() { |
| 493 | double NaN = *(double*) nan; |
| 494 | return NaN; |
| 495 | } |
| 496 | |
Ted Kremenek | 60a4481 | 2011-12-01 07:39:23 +0000 | [diff] [blame] | 497 | // Test that 'this' is assumed non-null upon analyzing the entry to a "top-level" |
Ted Kremenek | a078ecf | 2011-12-01 05:29:42 +0000 | [diff] [blame] | 498 | // function (i.e., when not analyzing from a specific caller). |
| 499 | struct TestNullThis { |
| 500 | int field; |
| 501 | void test(); |
| 502 | }; |
| 503 | |
| 504 | void TestNullThis::test() { |
| 505 | int *p = &field; |
| 506 | if (p) |
| 507 | return; |
| 508 | field = 2; // no-warning |
| 509 | } |
| 510 | |
Ted Kremenek | 337e4db | 2012-03-10 01:34:17 +0000 | [diff] [blame] | 511 | // Test handling of 'catch' exception variables, and not warning |
| 512 | // about uninitialized values. |
| 513 | enum MyEnum { MyEnumValue }; |
| 514 | MyEnum rdar10892489() { |
| 515 | try { |
| 516 | throw MyEnumValue; |
| 517 | } catch (MyEnum e) { |
| 518 | return e; // no-warning |
| 519 | } |
| 520 | return MyEnumValue; |
| 521 | } |
| 522 | |
| 523 | MyEnum rdar10892489_positive() { |
| 524 | try { |
| 525 | throw MyEnumValue; |
| 526 | } catch (MyEnum e) { |
| 527 | int *p = 0; |
Jordan Rose | c32a453 | 2012-08-18 00:30:23 +0000 | [diff] [blame] | 528 | // FALSE NEGATIVE |
| 529 | *p = 0xDEADBEEF; // {{null}} |
Ted Kremenek | 337e4db | 2012-03-10 01:34:17 +0000 | [diff] [blame] | 530 | return e; |
| 531 | } |
| 532 | return MyEnumValue; |
| 533 | } |
| 534 | |
Ted Kremenek | ce612f5 | 2012-03-16 05:58:15 +0000 | [diff] [blame] | 535 | // Test handling of catch with no condition variable. |
| 536 | void PR11545() { |
| 537 | try |
| 538 | { |
| 539 | throw; |
| 540 | } |
| 541 | catch (...) |
| 542 | { |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | void PR11545_positive() { |
| 547 | try |
| 548 | { |
| 549 | throw; |
| 550 | } |
| 551 | catch (...) |
| 552 | { |
| 553 | int *p = 0; |
Jordan Rose | c32a453 | 2012-08-18 00:30:23 +0000 | [diff] [blame] | 554 | // FALSE NEGATIVE |
| 555 | *p = 0xDEADBEEF; // {{null}} |
Ted Kremenek | ce612f5 | 2012-03-16 05:58:15 +0000 | [diff] [blame] | 556 | } |
| 557 | } |
| 558 | |
Ted Kremenek | 5aac0b6 | 2012-03-22 21:42:31 +0000 | [diff] [blame] | 559 | // Test handling taking the address of a field. While the analyzer |
| 560 | // currently doesn't do anything intelligent here, this previously |
| 561 | // resulted in a crash. |
| 562 | class PR11146 { |
| 563 | public: |
| 564 | struct Entry; |
| 565 | void baz(); |
| 566 | }; |
| 567 | |
| 568 | struct PR11146::Entry { |
| 569 | int x; |
| 570 | }; |
| 571 | |
| 572 | void PR11146::baz() { |
| 573 | (void) &Entry::x; |
| 574 | } |
Ted Kremenek | b98b998 | 2012-04-05 05:56:31 +0000 | [diff] [blame] | 575 | |
| 576 | // Test symbolicating a reference. In this example, the |
| 577 | // analyzer (originally) didn't know how to handle x[index - index2], |
| 578 | // returning an UnknownVal. The conjured symbol wasn't a location, |
| 579 | // and would result in a crash. |
| 580 | void rdar10924675(unsigned short x[], int index, int index2) { |
| 581 | unsigned short &y = x[index - index2]; |
| 582 | if (y == 0) |
| 583 | return; |
| 584 | } |
Ted Kremenek | c319c58 | 2012-05-08 05:13:40 +0000 | [diff] [blame] | 585 | |
| 586 | // Test handling CXXScalarValueInitExprs. |
| 587 | void rdar11401827() { |
| 588 | int x = int(); |
| 589 | if (!x) { |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 590 | clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 591 | ; // Suppress warning that both branches are identical |
Ted Kremenek | c319c58 | 2012-05-08 05:13:40 +0000 | [diff] [blame] | 592 | } |
| 593 | else { |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 594 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | c319c58 | 2012-05-08 05:13:40 +0000 | [diff] [blame] | 595 | } |
| 596 | } |
| 597 | |
Ted Kremenek | 10f77ad | 2012-06-22 23:55:50 +0000 | [diff] [blame] | 598 | //===---------------------------------------------------------------------===// |
| 599 | // Handle inlining of C++ method calls. |
| 600 | //===---------------------------------------------------------------------===// |
| 601 | |
| 602 | struct A { |
| 603 | int *p; |
| 604 | void foo(int *q) { |
| 605 | p = q; |
| 606 | } |
| 607 | void bar() { |
| 608 | *p = 0; // expected-warning {{null pointer}} |
| 609 | } |
| 610 | }; |
| 611 | |
| 612 | void test_inline() { |
| 613 | A a; |
| 614 | a.foo(0); |
| 615 | a.bar(); |
| 616 | } |
| 617 | |
Anna Zaks | dac6cd5 | 2012-11-26 19:11:46 +0000 | [diff] [blame] | 618 | void test_alloca_in_a_recursive_function(int p1) { |
| 619 | __builtin_alloca (p1); |
| 620 | test_alloca_in_a_recursive_function(1); |
| 621 | test_alloca_in_a_recursive_function(2); |
| 622 | } |
Ted Kremenek | bd8a11e | 2012-11-27 23:05:37 +0000 | [diff] [blame] | 623 | |
| 624 | //===---------------------------------------------------------------------===// |
| 625 | // Random tests. |
| 626 | //===---------------------------------------------------------------------===// |
| 627 | |
| 628 | // Tests assigning using a C-style initializer to a struct |
| 629 | // variable whose sub-field is also a struct. This currently |
| 630 | // results in a CXXTempObjectRegion being created, but not |
| 631 | // properly handled. For now, we just ignore that value |
| 632 | // to avoid a crash (<rdar://problem/12753384>). |
| 633 | struct RDar12753384_ClassA { |
| 634 | unsigned z; |
| 635 | }; |
| 636 | struct RDar12753384_ClassB { |
| 637 | unsigned x; |
| 638 | RDar12753384_ClassA y[ 8 ] ; |
| 639 | }; |
| 640 | unsigned RDar12753384() { |
| 641 | RDar12753384_ClassB w = { 0x00 }; |
| 642 | RDar12753384_ClassA y[8]; |
| 643 | return w.x; |
| 644 | } |
| 645 | |
Ted Kremenek | 1994e39 | 2012-11-28 01:49:01 +0000 | [diff] [blame] | 646 | // This testcase tests whether we treat the anonymous union and union |
| 647 | // the same way. This previously resulted in a "return of stack address" |
| 648 | // warning because the anonymous union resulting in a temporary object |
| 649 | // getting put into the initializer. We still aren't handling this correctly, |
| 650 | // but now if a temporary object appears in an initializer we just ignore it. |
| 651 | // Fixes <rdar://problem/12755044>. |
| 652 | |
| 653 | struct Rdar12755044_foo |
| 654 | { |
| 655 | struct Rdar12755044_bar |
| 656 | { |
| 657 | union baz |
| 658 | { |
| 659 | int i; |
| 660 | }; |
| 661 | } aBar; |
| 662 | }; |
| 663 | |
| 664 | struct Rdar12755044_foo_anon |
| 665 | { |
| 666 | struct Rdar12755044_bar |
| 667 | { |
| 668 | union |
| 669 | { |
| 670 | int i; |
| 671 | }; |
| 672 | } aBar; |
| 673 | }; |
| 674 | |
| 675 | const Rdar12755044_foo_anon *radar12755044_anon() { |
| 676 | static const Rdar12755044_foo_anon Rdar12755044_foo_list[] = { { { } } }; |
| 677 | return Rdar12755044_foo_list; // no-warning |
| 678 | } |
| 679 | |
| 680 | const Rdar12755044_foo *radar12755044() { |
| 681 | static const Rdar12755044_foo Rdar12755044_foo_list[] = { { { } } }; |
| 682 | return Rdar12755044_foo_list; // no-warning |
| 683 | } |
Ted Kremenek | 9c04666 | 2012-11-29 00:50:20 +0000 | [diff] [blame] | 684 | |
| 685 | // Test the correct handling of integer to bool conversions. Previously |
| 686 | // this resulted in a false positive because integers were being truncated |
| 687 | // and not tested for non-zero. |
| 688 | void rdar12759044() { |
| 689 | int flag = 512; |
| 690 | if (!(flag & 512)) { |
Jordan Rose | d000b85 | 2013-10-03 16:57:03 +0000 | [diff] [blame] | 691 | clang_analyzer_warnIfReached(); // no-warning |
Ted Kremenek | 9c04666 | 2012-11-29 00:50:20 +0000 | [diff] [blame] | 692 | } |
| 693 | } |
Ted Kremenek | beac9e3 | 2013-01-09 18:46:17 +0000 | [diff] [blame] | 694 | |
| 695 | // The analyzer currently does not model complex types. Test that the load |
| 696 | // from 'x' is not flagged as being uninitialized. |
| 697 | typedef __complex__ float _ComplexT; |
| 698 | void rdar12964481(_ComplexT *y) { |
| 699 | _ComplexT x; |
| 700 | __real__ x = 1.0; |
| 701 | __imag__ x = 1.0; |
| 702 | *y *= x; // no-warning |
| 703 | } |
| 704 | void rdar12964481_b(_ComplexT *y) { |
| 705 | _ComplexT x; |
| 706 | // Eventually this should be a warning. |
| 707 | *y *= x; // no-warning |
| 708 | } |
| 709 | |
Ted Kremenek | 88de5a0 | 2013-03-22 21:30:22 +0000 | [diff] [blame] | 710 | // Test case for PR 12921. This previously produced |
| 711 | // a bogus warning. |
| 712 | static const int pr12921_arr[] = { 0, 1 }; |
| 713 | static const int pr12921_arrcount = sizeof(pr12921_arr)/sizeof(int); |
| 714 | |
| 715 | int pr12921(int argc, char **argv) { |
| 716 | int i, retval; |
| 717 | for (i = 0; i < pr12921_arrcount; i++) { |
| 718 | if (argc == i) { |
| 719 | retval = i; |
| 720 | break; |
| 721 | } |
| 722 | } |
| 723 | |
| 724 | // No match |
| 725 | if (i == pr12921_arrcount) return 66; |
| 726 | return pr12921_arr[retval]; |
| 727 | } |
| 728 | |