1 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 2 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s 3 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 4 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s 5 6 // This file tests how we construct two different flavors of the Clang CFG - 7 // the CFG used by the Sema analysis-based warnings and the CFG used by the 8 // static analyzer. The difference in the behavior is checked via FileCheck 9 // prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer 10 // flags, no new run lines should be added - just these flags would go to the 11 // respective line depending on where is it turned on and where is it turned 12 // off. Feel free to add tests that test only one of the CFG flavors if you're 13 // not sure how the other flavor is supposed to work in your case. 14 15 // CHECK-LABEL: void checkWrap(int i) 16 // CHECK: ENTRY 17 // CHECK-NEXT: Succs (1): B1 18 // CHECK: [B1] 19 // CHECK: Succs (21): B2 B3 B4 B5 B6 B7 B8 B9 20 // CHECK: B10 B11 B12 B13 B14 B15 B16 B17 B18 B19 21 // CHECK: B20 B21 B0 22 // CHECK: [B0 (EXIT)] 23 // CHECK-NEXT: Preds (21): B2 B3 B4 B5 B6 B7 B8 B9 24 // CHECK-NEXT: B10 B11 B12 B13 B14 B15 B16 B17 B18 B19 25 // CHECK-NEXT: B20 B21 B1 26 void checkWrap(int i) { 27 switch(i) { 28 case 0: break; 29 case 1: break; 30 case 2: break; 31 case 3: break; 32 case 4: break; 33 case 5: break; 34 case 6: break; 35 case 7: break; 36 case 8: break; 37 case 9: break; 38 case 10: break; 39 case 11: break; 40 case 12: break; 41 case 13: break; 42 case 14: break; 43 case 15: break; 44 case 16: break; 45 case 17: break; 46 case 18: break; 47 case 19: break; 48 } 49 } 50 51 // CHECK-LABEL: void checkDeclStmts() 52 // CHECK: ENTRY 53 // CHECK-NEXT: Succs (1): B1 54 // CHECK: [B1] 55 // CHECK-NEXT: 1: int i; 56 // CHECK-NEXT: 2: int j; 57 // CHECK-NEXT: 3: 1 58 // CHECK-NEXT: 4: int k = 1; 59 // CHECK-NEXT: 5: int l; 60 // CHECK-NEXT: 6: 2 61 // CHECK-NEXT: 7: int m = 2; 62 // WARNINGS-NEXT: (CXXConstructExpr, struct standalone) 63 // ANALYZER-NEXT: (CXXConstructExpr, [B1.9], struct standalone) 64 // CHECK-NEXT: 9: struct standalone myStandalone; 65 // WARNINGS-NEXT: (CXXConstructExpr, struct (anonymous struct at {{.*}})) 66 // ANALYZER-NEXT: (CXXConstructExpr, [B1.11], struct (anonymous struct at {{.*}})) 67 // CHECK-NEXT: 11: struct (anonymous struct at {{.*}}) myAnon; 68 // WARNINGS-NEXT: (CXXConstructExpr, struct named) 69 // ANALYZER-NEXT: (CXXConstructExpr, [B1.13], struct named) 70 // CHECK-NEXT: 13: struct named myNamed; 71 // CHECK-NEXT: Preds (1): B2 72 // CHECK-NEXT: Succs (1): B0 73 void checkDeclStmts() { 74 int i, j; 75 int k = 1, l, m = 2; 76 77 struct standalone { int x, y; }; 78 struct standalone myStandalone; 79 80 struct { int x, y; } myAnon; 81 82 struct named { int x, y; } myNamed; 83 84 static_assert(1, "abc"); 85 } 86 87 88 // CHECK-LABEL: void checkGCCAsmRValueOutput() 89 // CHECK: [B2 (ENTRY)] 90 // CHECK-NEXT: Succs (1): B1 91 // CHECK: [B1] 92 // CHECK-NEXT: 1: int arg 93 // CHECK-NEXT: 2: arg 94 // CHECK-NEXT: 3: (int)[B1.2] (CStyleCastExpr, NoOp, int) 95 // CHECK-NEXT: 4: asm ("" : "=r" ([B1.3])); 96 // CHECK-NEXT: 5: arg 97 // CHECK-NEXT: 6: asm ("" : "=r" ([B1.5])); 98 void checkGCCAsmRValueOutput() { 99 int arg; 100 __asm__("" : "=r"((int)arg)); // rvalue output operand 101 __asm__("" : "=r"(arg)); // lvalue output operand 102 } 103 104 105 // CHECK-LABEL: void F(EmptyE e) 106 // CHECK: ENTRY 107 // CHECK-NEXT: Succs (1): B1 108 // CHECK: [B1] 109 // CHECK-NEXT: 1: e 110 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, enum EmptyE) 111 // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, IntegralCast, int) 112 // CHECK-NEXT: T: switch [B1.3] 113 // CHECK-NEXT: Preds (1): B2 114 // CHECK-NEXT: Succs (1): B0 115 // CHECK: [B0 (EXIT)] 116 // CHECK-NEXT: Preds (1): B1 117 enum EmptyE {}; 118 void F(EmptyE e) { 119 switch (e) {} 120 } 121 122 // CHECK-LABEL: void testBuiltinSize() 123 // CHECK: ENTRY 124 // CHECK-NEXT: Succs (1): B1 125 // CHECK: [B1] 126 // CHECK-NEXT: 1: __builtin_object_size 127 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int) noexcept) 128 // CHECK-NEXT: 3: [B1.2](dummy(), 0) 129 // CHECK-NEXT: 4: (void)[B1.3] (CStyleCastExpr, ToVoid, void) 130 // CHECK-NEXT: Preds (1): B2 131 // CHECK-NEXT: Succs (1): B0 132 // CHECK: [B0 (EXIT)] 133 // CHECK-NEXT: Preds (1): B1 134 void testBuiltinSize() { 135 extern int *dummy(); 136 (void)__builtin_object_size(dummy(), 0); 137 } 138 139 140 class A { 141 public: 142 A() {} 143 ~A() {} 144 }; 145 146 // CHECK-LABEL: void test_deletedtor() 147 // CHECK: [B2 (ENTRY)] 148 // CHECK-NEXT: Succs (1): B1 149 // CHECK: [B1] 150 // CHECK-NEXT: 1: CFGNewAllocator(A *) 151 // WARNINGS-NEXT: 2: (CXXConstructExpr, class A) 152 // ANALYZER-NEXT: 2: (CXXConstructExpr, [B1.3], class A) 153 // CHECK-NEXT: 3: new A([B1.2]) 154 // CHECK-NEXT: 4: A *a = new A(); 155 // CHECK-NEXT: 5: a 156 // CHECK-NEXT: 6: [B1.5] (ImplicitCastExpr, LValueToRValue, class A *) 157 // CHECK-NEXT: 7: [B1.6]->~A() (Implicit destructor) 158 // CHECK-NEXT: 8: delete [B1.6] 159 // CHECK-NEXT: Preds (1): B2 160 // CHECK-NEXT: Succs (1): B0 161 // CHECK: [B0 (EXIT)] 162 // CHECK-NEXT: Preds (1): B1 163 void test_deletedtor() { 164 A *a = new A(); 165 delete a; 166 } 167 168 // CHECK-LABEL: void test_deleteArraydtor() 169 // CHECK: [B2 (ENTRY)] 170 // CHECK-NEXT: Succs (1): B1 171 // CHECK: [B1] 172 // CHECK-NEXT: 1: 5 173 // CHECK-NEXT: 2: CFGNewAllocator(A *) 174 // WARNINGS-NEXT: 3: (CXXConstructExpr, class A [5]) 175 // ANALYZER-NEXT: 3: (CXXConstructExpr, [B1.4], class A [5]) 176 // CHECK-NEXT: 4: new A {{\[\[}}B1.1]] 177 // CHECK-NEXT: 5: A *a = new A [5]; 178 // CHECK-NEXT: 6: a 179 // CHECK-NEXT: 7: [B1.6] (ImplicitCastExpr, LValueToRValue, class A *) 180 // CHECK-NEXT: 8: [B1.7]->~A() (Implicit destructor) 181 // CHECK-NEXT: 9: delete [] [B1.7] 182 // CHECK-NEXT: Preds (1): B2 183 // CHECK-NEXT: Succs (1): B0 184 // CHECK: [B0 (EXIT)] 185 // CHECK-NEXT: Preds (1): B1 186 void test_deleteArraydtor() { 187 A *a = new A[5]; 188 delete[] a; 189 } 190 191 192 namespace NoReturnSingleSuccessor { 193 struct A { 194 A(); 195 ~A(); 196 }; 197 198 struct B : public A { 199 B(); 200 ~B() __attribute__((noreturn)); 201 }; 202 203 // CHECK-LABEL: int test1(int *x) 204 // CHECK: 1: 1 205 // CHECK-NEXT: 2: return 206 // CHECK-NEXT: ~B() (Implicit destructor) 207 // CHECK-NEXT: Preds (1) 208 // CHECK-NEXT: Succs (1): B0 209 int test1(int *x) { 210 B b; 211 if (x) 212 return 1; 213 } 214 215 // CHECK-LABEL: int test2(int *x) 216 // CHECK: 1: 1 217 // CHECK-NEXT: 2: return 218 // CHECK-NEXT: destructor 219 // CHECK-NEXT: Preds (1) 220 // CHECK-NEXT: Succs (1): B0 221 int test2(int *x) { 222 const A& a = B(); 223 if (x) 224 return 1; 225 } 226 } 227 228 // Test CFG support for "extending" an enum. 229 // CHECK-LABEL: int test_enum_with_extension(enum MyEnum value) 230 // CHECK: [B7 (ENTRY)] 231 // CHECK-NEXT: Succs (1): B2 232 // CHECK: [B1] 233 // CHECK-NEXT: 1: x 234 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) 235 // CHECK-NEXT: 3: return [B1.2]; 236 // CHECK-NEXT: Preds (5): B3 B4 B5 B6 B2(Unreachable) 237 // CHECK-NEXT: Succs (1): B0 238 // CHECK: [B2] 239 // CHECK-NEXT: 1: 0 240 // CHECK-NEXT: 2: int x = 0; 241 // CHECK-NEXT: 3: value 242 // CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum) 243 // CHECK-NEXT: 5: [B2.4] (ImplicitCastExpr, IntegralCast, int) 244 // CHECK-NEXT: T: switch [B2.5] 245 // CHECK-NEXT: Preds (1): B7 246 // CHECK-NEXT: Succs (5): B3 B4 B5 B6 B1(Unreachable) 247 // CHECK: [B3] 248 // CHECK-NEXT: case D: 249 // CHECK-NEXT: 1: 4 250 // CHECK-NEXT: 2: x 251 // CHECK-NEXT: 3: [B3.2] = [B3.1] 252 // CHECK-NEXT: T: break; 253 // CHECK-NEXT: Preds (1): B2 254 // CHECK-NEXT: Succs (1): B1 255 // CHECK: [B4] 256 // CHECK-NEXT: case C: 257 // CHECK-NEXT: 1: 3 258 // CHECK-NEXT: 2: x 259 // CHECK-NEXT: 3: [B4.2] = [B4.1] 260 // CHECK-NEXT: T: break; 261 // CHECK-NEXT: Preds (1): B2 262 // CHECK-NEXT: Succs (1): B1 263 // CHECK: [B5] 264 // CHECK-NEXT: case B: 265 // CHECK-NEXT: 1: 2 266 // CHECK-NEXT: 2: x 267 // CHECK-NEXT: 3: [B5.2] = [B5.1] 268 // CHECK-NEXT: T: break; 269 // CHECK-NEXT: Preds (1): B2 270 // CHECK-NEXT: Succs (1): B1 271 // CHECK: [B6] 272 // CHECK-NEXT: case A: 273 // CHECK-NEXT: 1: 1 274 // CHECK-NEXT: 2: x 275 // CHECK-NEXT: 3: [B6.2] = [B6.1] 276 // CHECK-NEXT: T: break; 277 // CHECK-NEXT: Preds (1): B2 278 // CHECK-NEXT: Succs (1): B1 279 // CHECK: [B0 (EXIT)] 280 // CHECK-NEXT: Preds (1): B1 281 enum MyEnum { A, B, C }; 282 static const enum MyEnum D = (enum MyEnum) 32; 283 284 int test_enum_with_extension(enum MyEnum value) { 285 int x = 0; 286 switch (value) { 287 case A: x = 1; break; 288 case B: x = 2; break; 289 case C: x = 3; break; 290 case D: x = 4; break; 291 } 292 return x; 293 } 294 295 // CHECK-LABEL: int test_enum_with_extension_default(enum MyEnum value) 296 // CHECK: [B7 (ENTRY)] 297 // CHECK-NEXT: Succs (1): B2 298 // CHECK: [B1] 299 // CHECK-NEXT: 1: x 300 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) 301 // CHECK-NEXT: 3: return [B1.2]; 302 // CHECK-NEXT: Preds (4): B3 B4 B5 B6 303 // CHECK-NEXT: Succs (1): B0 304 // CHECK: [B2] 305 // CHECK-NEXT: 1: 0 306 // CHECK-NEXT: 2: int x = 0; 307 // CHECK-NEXT: 3: value 308 // CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum) 309 // CHECK-NEXT: 5: [B2.4] (ImplicitCastExpr, IntegralCast, int) 310 // CHECK-NEXT: T: switch [B2.5] 311 // CHECK-NEXT: Preds (1): B7 312 // CHECK-NEXT: Succs (4): B4 B5 B6 B3(Unreachable) 313 // CHECK: [B3] 314 // CHECK-NEXT: default: 315 // CHECK-NEXT: 1: 4 316 // CHECK-NEXT: 2: x 317 // CHECK-NEXT: 3: [B3.2] = [B3.1] 318 // CHECK-NEXT: T: break; 319 // CHECK-NEXT: Preds (1): B2(Unreachable) 320 // CHECK-NEXT: Succs (1): B1 321 // CHECK: [B4] 322 // CHECK-NEXT: case C: 323 // CHECK-NEXT: 1: 3 324 // CHECK-NEXT: 2: x 325 // CHECK-NEXT: 3: [B4.2] = [B4.1] 326 // CHECK-NEXT: T: break; 327 // CHECK-NEXT: Preds (1): B2 328 // CHECK-NEXT: Succs (1): B1 329 // CHECK: [B5] 330 // CHECK-NEXT: case B: 331 // CHECK-NEXT: 1: 2 332 // CHECK-NEXT: 2: x 333 // CHECK-NEXT: 3: [B5.2] = [B5.1] 334 // CHECK-NEXT: T: break; 335 // CHECK-NEXT: Preds (1): B2 336 // CHECK-NEXT: Succs (1): B1 337 // CHECK: [B6] 338 // CHECK-NEXT: case A: 339 // CHECK-NEXT: 1: 1 340 // CHECK-NEXT: 2: x 341 // CHECK-NEXT: 3: [B6.2] = [B6.1] 342 // CHECK-NEXT: T: break; 343 // CHECK-NEXT: Preds (1): B2 344 // CHECK-NEXT: Succs (1): B1 345 // CHECK: [B0 (EXIT)] 346 // CHECK-NEXT: Preds (1): B1 347 int test_enum_with_extension_default(enum MyEnum value) { 348 int x = 0; 349 switch (value) { 350 case A: x = 1; break; 351 case B: x = 2; break; 352 case C: x = 3; break; 353 default: x = 4; break; 354 } 355 return x; 356 } 357 358 359 // CHECK-LABEL: void test_placement_new() 360 // CHECK: [B2 (ENTRY)] 361 // CHECK-NEXT: Succs (1): B1 362 // CHECK: [B1] 363 // CHECK-NEXT: 1: int buffer[16]; 364 // CHECK-NEXT: 2: buffer 365 // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *) 366 // CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, BitCast, void *) 367 // CHECK-NEXT: 5: CFGNewAllocator(MyClass *) 368 // WARNINGS-NEXT: 6: (CXXConstructExpr, class MyClass) 369 // ANALYZER-NEXT: 6: (CXXConstructExpr, [B1.7], class MyClass) 370 // CHECK-NEXT: 7: new ([B1.4]) MyClass([B1.6]) 371 // CHECK-NEXT: 8: MyClass *obj = new (buffer) MyClass(); 372 // CHECK-NEXT: Preds (1): B2 373 // CHECK-NEXT: Succs (1): B0 374 // CHECK: [B0 (EXIT)] 375 // CHECK-NEXT: Preds (1): B1 376 377 extern void* operator new (unsigned long sz, void* v); 378 extern void* operator new[] (unsigned long sz, void* ptr); 379 380 class MyClass { 381 public: 382 MyClass() {} 383 ~MyClass() {} 384 }; 385 386 void test_placement_new() { 387 int buffer[16]; 388 MyClass* obj = new (buffer) MyClass(); 389 } 390 391 // CHECK-LABEL: void test_placement_new_array() 392 // CHECK: [B2 (ENTRY)] 393 // CHECK-NEXT: Succs (1): B1 394 // CHECK: [B1] 395 // CHECK-NEXT: 1: int buffer[16]; 396 // CHECK-NEXT: 2: buffer 397 // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *) 398 // CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, BitCast, void *) 399 // CHECK-NEXT: 5: 5 400 // CHECK-NEXT: 6: CFGNewAllocator(MyClass *) 401 // WARNINGS-NEXT: 7: (CXXConstructExpr, class MyClass [5]) 402 // ANALYZER-NEXT: 7: (CXXConstructExpr, [B1.8], class MyClass [5]) 403 // CHECK-NEXT: 8: new ([B1.4]) MyClass {{\[\[}}B1.5]] 404 // CHECK-NEXT: 9: MyClass *obj = new (buffer) MyClass [5]; 405 // CHECK-NEXT: Preds (1): B2 406 // CHECK-NEXT: Succs (1): B0 407 // CHECK: [B0 (EXIT)] 408 // CHECK-NEXT: Preds (1): B1 409 410 void test_placement_new_array() { 411 int buffer[16]; 412 MyClass* obj = new (buffer) MyClass[5]; 413 } 414 415 416 // CHECK-LABEL: void test_lifetime_extended_temporaries() 417 // CHECK: [B1] 418 struct LifetimeExtend { LifetimeExtend(int); ~LifetimeExtend(); }; 419 struct Aggregate { const LifetimeExtend a; const LifetimeExtend b; }; 420 struct AggregateRef { const LifetimeExtend &a; const LifetimeExtend &b; }; 421 void test_lifetime_extended_temporaries() { 422 // CHECK: LifetimeExtend(1); 423 // CHECK-NEXT: : 1 424 // CHECK-NEXT: ~LifetimeExtend() 425 // CHECK-NOT: ~LifetimeExtend() 426 { 427 const LifetimeExtend &l = LifetimeExtend(1); 428 1; 429 } 430 // CHECK: LifetimeExtend(2) 431 // CHECK-NEXT: ~LifetimeExtend() 432 // CHECK-NEXT: : 2 433 // CHECK-NOT: ~LifetimeExtend() 434 { 435 // No life-time extension. 436 const int &l = (LifetimeExtend(2), 2); 437 2; 438 } 439 // CHECK: LifetimeExtend(3) 440 // CHECK-NEXT: : 3 441 // CHECK-NEXT: ~LifetimeExtend() 442 // CHECK-NOT: ~LifetimeExtend() 443 { 444 // The last one is lifetime extended. 445 const LifetimeExtend &l = (3, LifetimeExtend(3)); 446 3; 447 } 448 // CHECK: LifetimeExtend(4) 449 // CHECK-NEXT: ~LifetimeExtend() 450 // CHECK-NEXT: ~LifetimeExtend() 451 // CHECK-NEXT: : 4 452 // CHECK-NOT: ~LifetimeExtend() 453 { 454 Aggregate a{LifetimeExtend(4), LifetimeExtend(4)}; 455 4; 456 } 457 // CHECK: LifetimeExtend(5) 458 // CHECK-NEXT: : 5 459 // FIXME: We want to emit the destructors of the lifetime 460 // extended variables here. 461 // CHECK-NOT: ~LifetimeExtend() 462 { 463 AggregateRef a{LifetimeExtend(5), LifetimeExtend(5)}; 464 5; 465 } 466 // FIXME: Add tests for lifetime extension via subobject 467 // references (LifetimeExtend().some_member). 468 } 469 470 471 // FIXME: The destructor for 'a' shouldn't be there because it's deleted 472 // in the union. 473 // CHECK-LABEL: void foo() 474 // CHECK: [B2 (ENTRY)] 475 // CHECK-NEXT: Succs (1): B1 476 // CHECK: [B1] 477 // WARNINGS-NEXT: 1: (CXXConstructExpr, struct pr37688_deleted_union_destructor::A) 478 // ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], struct pr37688_deleted_union_destructor::A) 479 // CHECK-NEXT: 2: pr37688_deleted_union_destructor::A a; 480 // CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor) 481 // CHECK-NEXT: Preds (1): B2 482 // CHECK-NEXT: Succs (1): B0 483 // CHECK: [B0 (EXIT)] 484 // CHECK-NEXT: Preds (1): B1 485 486 namespace pr37688_deleted_union_destructor { 487 struct S { ~S(); }; 488 struct A { 489 ~A() noexcept {} 490 union { 491 struct { 492 S s; 493 } ss; 494 }; 495 }; 496 void foo() { 497 A a; 498 } 499 } // end namespace pr37688_deleted_union_destructor 500 501 502 // CHECK-LABEL: template<> int *PR18472<int>() 503 // CHECK: [B2 (ENTRY)] 504 // CHECK-NEXT: Succs (1): B1 505 // CHECK: [B1] 506 // CHECK-NEXT: 1: 0 507 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, PR18472_t) 508 // CHECK-NEXT: 3: (PR18472_t)[B1.2] (CStyleCastExpr, NoOp, PR18472_t) 509 // CHECK-NEXT: 4: CFGNewAllocator(int *) 510 // CHECK-NEXT: 5: new (([B1.3])) int 511 // CHECK-NEXT: 6: return [B1.5]; 512 // CHECK-NEXT: Preds (1): B2 513 // CHECK-NEXT: Succs (1): B0 514 // CHECK: [B0 (EXIT)] 515 // CHECK-NEXT: Preds (1): B1 516 517 extern "C" typedef int *PR18472_t; 518 void *operator new (unsigned long, PR18472_t); 519 template <class T> T *PR18472() { 520 return new (((PR18472_t) 0)) T; 521 } 522 void PR18472_helper() { 523 PR18472<int>(); 524 } 525 526