// RUN: %clang_analyze_cc1 -std=c++11 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true,cfg-implicit-dtors=true,cfg-lifetime=true,cfg-scopes=true %s > %t 2>&1 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK %s class A { public: int x; [[noreturn]] ~A(); }; void foo(); extern const bool UV; // CHECK: [B3 (ENTRY)] // CHECK-NEXT: Succs (1): B2 // // CHECK: [B1] // CHECK-NEXT: 1: CFGScopeEnd(a) // CHECK-NEXT: 2: foo // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(void)) // CHECK-NEXT: 4: [B1.3]() // CHECK-NEXT: Succs (1): B0 // // CHECK: [B2 (NORETURN)] // CHECK-NEXT: 1: CFGScopeBegin(a) // CHECK-NEXT: 2: (CXXConstructExpr, [B2.3], A) // CHECK-NEXT: 3: A a; // CHECK-NEXT: 4: [B2.3].~A() (Implicit destructor) // CHECK-NEXT: 5: [B2.3] (Lifetime ends) // CHECK-NEXT: Preds (1): B3 // CHECK-NEXT: Succs (1): B0 // // CHECK: [B0 (EXIT)] // CHECK-NEXT: Preds (2): B1 B2 void test_single_decl() { { A a; } foo(); } // CHECK: [B6 (ENTRY)] // CHECK-NEXT: Succs (1): B5 // // CHECK: [B1] // CHECK-NEXT: label: // CHECK-NEXT: 1: foo // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(void)) // CHECK-NEXT: 3: [B1.2]() // CHECK-NEXT: Preds (4): B2 B3(Unreachable) B4 B5(Unreachable) // CHECK-NEXT: Succs (1): B0 // // CHECK: [B2] // CHECK-NEXT: 1: CFGScopeEnd(a) // CHECK-NEXT: Succs (1): B1 // // CHECK: [B3 (NORETURN)] // CHECK-NEXT: 1: [B5.3].~A() (Implicit destructor) // CHECK-NEXT: 2: [B5.3] (Lifetime ends) // CHECK-NEXT: Succs (1): B0 // // CHECK: [B4] // CHECK-NEXT: 1: CFGScopeEnd(a) // CHECK-NEXT: T: goto label; // CHECK-NEXT: Succs (1): B1 // // CHECK: [B5 (NORETURN)] // CHECK-NEXT: 1: CFGScopeBegin(a) // CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], A) // CHECK-NEXT: 3: A a; // CHECK-NEXT: 4: [B5.3].~A() (Implicit destructor) // CHECK-NEXT: 5: [B5.3] (Lifetime ends) // CHECK-NEXT: Preds (1): B6 // CHECK-NEXT: Succs (1): B0 // // CHECK: [B0 (EXIT)] // CHECK-NEXT: Preds (3): B1 B3 B5 void test_forward_goto() { { A a; goto label; } label: foo(); } // The blocks B3 and B5, are inserted during backpatching goto stmt, to handle // scope changes. // CHECK: [B6 (ENTRY)] // CHECK-NEXT: Succs (1): B3 // // CHECK: [B1] // CHECK-NEXT: 1: CFGScopeEnd(a) // CHECK-NEXT: 2: foo // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(void)) // CHECK-NEXT: 4: [B1.3]() // CHECK-NEXT: Succs (1): B0 // // CHECK: [B2 (NORETURN)] // CHECK-NEXT: 1: [B3.3].~A() (Implicit destructor) // CHECK-NEXT: 2: [B3.3] (Lifetime ends) // CHECK-NEXT: Succs (1): B0 // // CHECK: [B3] // CHECK-NEXT: label: // CHECK-NEXT: 1: CFGScopeBegin(a) // CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], A) // CHECK-NEXT: 3: A a; // CHECK-NEXT: Preds (3): B4 B5(Unreachable) B6 // CHECK-NEXT: Succs (1): B5 // // CHECK: [B4] // CHECK-NEXT: 1: CFGScopeEnd(a) // CHECK-NEXT: T: goto label; // CHECK-NEXT: Succs (1): B3 // // CHECK: [B5 (NORETURN)] // CHECK-NEXT: 1: [B3.3].~A() (Implicit destructor) // CHECK-NEXT: 2: [B3.3] (Lifetime ends) // CHECK-NEXT: Preds (1): B3 // CHECK-NEXT: Succs (1): B0 // // CHECK: [B0 (EXIT)] // CHECK-NEXT: Preds (3): B1 B2 B5 void test_backward_goto() { label: { A a; goto label; } foo(); }